mirror of https://github.com/fafhrd91/actix-web
Prevent directory traversal attack
This commit is contained in:
parent
e29f0c5468
commit
fb278de4b4
|
@ -1,6 +1,10 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
* Prevent directory traversal attack by checking if the request path is a
|
||||||
|
descendant of the `serve_from` directory. E.g., if the files are served from
|
||||||
|
`./test/`, and someone requests `..%5c/some-secret-file`, they will get a
|
||||||
|
Forbidden response.
|
||||||
|
|
||||||
|
|
||||||
## 0.6.0-beta.2 - 2021-02-10
|
## 0.6.0-beta.2 - 2021-02-10
|
||||||
|
|
|
@ -73,7 +73,8 @@ impl Files {
|
||||||
///
|
///
|
||||||
/// The second argument (`serve_from`) is the location on disk at which files are loaded.
|
/// The second argument (`serve_from`) is the location on disk at which files are loaded.
|
||||||
/// This can be a relative path. For example, `./` would serve files from the current
|
/// This can be a relative path. For example, `./` would serve files from the current
|
||||||
/// working directory.
|
/// working directory. Requests for files outside of the `serve_from` directory
|
||||||
|
/// will receive a Forbidden Response.
|
||||||
///
|
///
|
||||||
/// # Implementation Notes
|
/// # Implementation Notes
|
||||||
/// If the mount path is set as the root path `/`, services registered after this one will
|
/// If the mount path is set as the root path `/`, services registered after this one will
|
||||||
|
|
|
@ -88,6 +88,18 @@ impl Service<ServiceRequest> for FilesService {
|
||||||
Err(e) => return self.handle_err(e, req),
|
Err(e) => return self.handle_err(e, req),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let is_path_descendant = path
|
||||||
|
.as_path()
|
||||||
|
.ancestors()
|
||||||
|
.any(|ancestor| ancestor == self.directory.as_path());
|
||||||
|
if !is_path_descendant {
|
||||||
|
return Either::Left(ok(req.into_response(
|
||||||
|
actix_web::HttpResponse::Forbidden()
|
||||||
|
.insert_header(header::ContentType(mime::TEXT_PLAIN_UTF_8))
|
||||||
|
.body("Requested files outside the server."),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
if let Some(ref redir_index) = self.index {
|
if let Some(ref redir_index) = self.index {
|
||||||
if self.redirect_to_slash && !req.path().ends_with('/') {
|
if self.redirect_to_slash && !req.path().ends_with('/') {
|
||||||
|
|
|
@ -35,4 +35,12 @@ async fn test_utf8_file_contents() {
|
||||||
res.headers().get(header::CONTENT_TYPE),
|
res.headers().get(header::CONTENT_TYPE),
|
||||||
Some(&HeaderValue::from_static("text/plain; charset=utf-8")),
|
Some(&HeaderValue::from_static("text/plain; charset=utf-8")),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// prevent directory traversal attack
|
||||||
|
let srv = test::init_service(App::new().service(Files::new("/", "./tests"))).await;
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("..%5c/README.md").to_request();
|
||||||
|
let res = test::call_service(&srv, req).await;
|
||||||
|
|
||||||
|
assert_eq!(res.status(), StatusCode::FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue