mirror of https://github.com/fafhrd91/actix-web
fix bug where URIs could traverse server filesystem
This commit is contained in:
parent
5b4105e1e6
commit
e6fcea67f4
|
@ -1,6 +1,8 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
* Fix `PathBufWrap::parse_path` to error if the `path` has `".."`. This is to
|
||||||
|
prevent directory traversal attacks.
|
||||||
|
|
||||||
|
|
||||||
## 0.6.0-beta.2 - 2021-02-10
|
## 0.6.0-beta.2 - 2021-02-10
|
||||||
|
|
|
@ -21,13 +21,13 @@ impl FromStr for PathBufWrap {
|
||||||
|
|
||||||
impl PathBufWrap {
|
impl PathBufWrap {
|
||||||
/// Parse a path, giving the choice of allowing hidden files to be considered valid segments.
|
/// Parse a path, giving the choice of allowing hidden files to be considered valid segments.
|
||||||
|
/// If the path contains `".."`, an error will be returned to prevent someone being able
|
||||||
|
/// to traverse the filesystem.
|
||||||
pub fn parse_path(path: &str, hidden_files: bool) -> Result<Self, UriSegmentError> {
|
pub fn parse_path(path: &str, hidden_files: bool) -> Result<Self, UriSegmentError> {
|
||||||
let mut buf = PathBuf::new();
|
let mut buf = PathBuf::new();
|
||||||
|
|
||||||
for segment in path.split('/') {
|
for segment in path.split('/') {
|
||||||
if segment == ".." {
|
if !hidden_files && segment.starts_with('.') {
|
||||||
buf.pop();
|
|
||||||
} else if !hidden_files && segment.starts_with('.') {
|
|
||||||
return Err(UriSegmentError::BadStart('.'));
|
return Err(UriSegmentError::BadStart('.'));
|
||||||
} else if segment.starts_with('*') {
|
} else if segment.starts_with('*') {
|
||||||
return Err(UriSegmentError::BadStart('*'));
|
return Err(UriSegmentError::BadStart('*'));
|
||||||
|
@ -41,6 +41,8 @@ impl PathBufWrap {
|
||||||
continue;
|
continue;
|
||||||
} else if cfg!(windows) && segment.contains('\\') {
|
} else if cfg!(windows) && segment.contains('\\') {
|
||||||
return Err(UriSegmentError::BadChar('\\'));
|
return Err(UriSegmentError::BadChar('\\'));
|
||||||
|
} else if segment.contains("..") {
|
||||||
|
return Err(UriSegmentError::BadStart('.'));
|
||||||
} else {
|
} else {
|
||||||
buf.push(segment)
|
buf.push(segment)
|
||||||
}
|
}
|
||||||
|
@ -99,8 +101,12 @@ mod tests {
|
||||||
PathBuf::from_iter(vec!["seg1", "seg2"])
|
PathBuf::from_iter(vec!["seg1", "seg2"])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
PathBufWrap::from_str("/seg1/../seg2/").unwrap().0,
|
PathBufWrap::from_str("/seg1/../seg2/").map(|t| t.0),
|
||||||
PathBuf::from_iter(vec!["seg2"])
|
Err(UriSegmentError::BadStart('.'))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
PathBufWrap::from_str("/seg1/..%5c/..%5c/seg2/test.txt").map(|t| t.0),
|
||||||
|
Err(UriSegmentError::BadStart('.'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,5 +121,10 @@ mod tests {
|
||||||
PathBufWrap::parse_path("/test/.tt", true).unwrap().0,
|
PathBufWrap::parse_path("/test/.tt", true).unwrap().0,
|
||||||
PathBuf::from_iter(vec!["test", ".tt"])
|
PathBuf::from_iter(vec!["test", ".tt"])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
PathBufWrap::parse_path("/seg1/..%5c/..%5c/seg2/test.txt", true).map(|t| t.0),
|
||||||
|
Err(UriSegmentError::BadStart('.'))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue