Как Rust PathBuf предотвращает атаки с обходом каталога?

Из «Случай окисления: язык программирования Rust» Серхио Бенитес говорит:

Here is a static file server written in Rocket. It is exactly four lines and it guaranteed to not be vulnerable to directory traversal attacks.

Вот эти четыре строки:

#[get("/<path..>")]
fn files(path: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("static/").join(path)).ok()
}

В нижней части этого слайда говорится:

  • FromParam* реализация для PathBuf проверяет безопасность пути

Я понимаю, как тип может гарантировать безопасность, проверяя ввод (в том же смысле, что любой объект может в конструкторе, или как ввод в функцию может быть обернут проверяющей функцией.

dangerousThing(validateSafety(input))

Многие языки обеспечивают это. Я также понимаю, как это можно упростить, поместив его в конструктор для типа или класса,

class Path {
  constructor(path) { this._path = validateSafety(path) }
}

Но меня смущает то, что (если что-то) Rust здесь делает по-другому. Есть ли что-то еще?

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
0
522
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

PathBuf не дает таких гарантий. Это не можем, потому что во всех доменах, где используется PathBuf, нет концепции «атак с обходом каталога».

Автор имеет в виду, что реализация FromSegments для PathBuf выполняет проверку обходной атаки и никогда не вызывает обработчик в случае сбоя.

FromSegments допускает случаи сбоя, возвращая Result:

pub trait FromSegments<'a>: Sized {
    type Error: Debug;
    fn from_segments(segments: Segments<'a>) -> Result<Self, Self::Error>;
}

Значит, это просто конструктор для типа, который принимает ввод, проверяет ../ (или родительскую нотацию) и не может создать тип во время выполнения, если он обнаружен?

NO WAR WITH RUSSIA 29.05.2019 21:06

Мы можем перебирать части пути с помощью components(), поэтому мы можем проверить использование .., как показано ниже:

let p = PathBuf::from_str("/tmp/../etc/password").unwrap();
if p.components().into_iter().any(|x| x == Component::ParentDir) {
    return Err("directory traversal");
}

Другие вопросы по теме

Похожие вопросы