Rust PathBuf 如何防止目录遍历攻击?
How does a Rust PathBuf prevent directory traversal attacks?
来自 "A Case for Oxidation: The Rust Programming Language" Sergio Benitez 说,
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、
的构造函数中来简化它
class Path {
constructor(path) { this._path = validateSafety(path) }
}
但我对 Rust 在这里的不同之处(如果有的话)感到困惑。这还有什么吗?
PathBuf
不提供此类保证。它 不能 因为在所有使用 PathBuf
的域中没有 "directory traversal attacks" 的概念。
作者的意思是FromSegments
对PathBuf
的实现执行遍历攻击检查,如果失败从不调用处理程序。
FromSegments
通过返回 Result
:
允许失败情况
pub trait FromSegments<'a>: Sized {
type Error: Debug;
fn from_segments(segments: Segments<'a>) -> Result<Self, Self::Error>;
}
我们可以使用 components()
遍历部分路径,因此我们可以检查 ..
用法,如下所示:
let p = PathBuf::from_str("/tmp/../etc/password").unwrap();
if p.components().into_iter().any(|x| x == Component::ParentDir) {
return Err("directory traversal");
}
来自 "A Case for Oxidation: The Rust Programming Language" Sergio Benitez 说,
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、
的构造函数中来简化它class Path {
constructor(path) { this._path = validateSafety(path) }
}
但我对 Rust 在这里的不同之处(如果有的话)感到困惑。这还有什么吗?
PathBuf
不提供此类保证。它 不能 因为在所有使用 PathBuf
的域中没有 "directory traversal attacks" 的概念。
作者的意思是FromSegments
对PathBuf
的实现执行遍历攻击检查,如果失败从不调用处理程序。
FromSegments
通过返回 Result
:
pub trait FromSegments<'a>: Sized {
type Error: Debug;
fn from_segments(segments: Segments<'a>) -> Result<Self, Self::Error>;
}
我们可以使用 components()
遍历部分路径,因此我们可以检查 ..
用法,如下所示:
let p = PathBuf::from_str("/tmp/../etc/password").unwrap();
if p.components().into_iter().any(|x| x == Component::ParentDir) {
return Err("directory traversal");
}