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
|
||||
|
||||
## 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
|
||||
|
|
|
@ -73,7 +73,8 @@ impl Files {
|
|||
///
|
||||
/// 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
|
||||
/// working directory.
|
||||
/// working directory. Requests for files outside of the `serve_from` directory
|
||||
/// will receive a Forbidden Response.
|
||||
///
|
||||
/// # Implementation Notes
|
||||
/// 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),
|
||||
};
|
||||
|
||||
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 let Some(ref redir_index) = self.index {
|
||||
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),
|
||||
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