mirror of https://github.com/fafhrd91/actix-web
fix HRS vuln when first CL header is 0
This commit is contained in:
parent
c6eba2da9b
commit
399c5ea426
|
@ -88,20 +88,22 @@ pub(crate) trait MessageType: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
header::CONTENT_LENGTH => match value.to_str() {
|
header::CONTENT_LENGTH => match value.to_str() {
|
||||||
Ok(s) if s.trim().starts_with('+') => {
|
Ok(val) if val.trim().starts_with('+') => {
|
||||||
debug!("illegal Content-Length: {:?}", s);
|
debug!("illegal Content-Length: {:?}", val);
|
||||||
return Err(ParseError::Header);
|
return Err(ParseError::Header);
|
||||||
}
|
}
|
||||||
Ok(s) => {
|
|
||||||
if let Ok(len) = s.parse::<u64>() {
|
Ok(val) => {
|
||||||
if len != 0 {
|
if let Ok(len) = val.trim().parse::<u64>() {
|
||||||
|
// accept 0 lengths here and remove them later in this method after
|
||||||
|
// all headers have been processed
|
||||||
content_length = Some(len);
|
content_length = Some(len);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
debug!("illegal Content-Length: {:?}", s);
|
debug!("illegal Content-Length: {:?}", val);
|
||||||
return Err(ParseError::Header);
|
return Err(ParseError::Header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
debug!("illegal Content-Length: {:?}", value);
|
debug!("illegal Content-Length: {:?}", value);
|
||||||
return Err(ParseError::Header);
|
return Err(ParseError::Header);
|
||||||
|
@ -130,6 +132,7 @@ pub(crate) trait MessageType: Sized {
|
||||||
return Err(ParseError::Header);
|
return Err(ParseError::Header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// connection keep-alive state
|
// connection keep-alive state
|
||||||
header::CONNECTION => {
|
header::CONNECTION => {
|
||||||
ka = if let Ok(conn) = value.to_str().map(str::trim) {
|
ka = if let Ok(conn) = value.to_str().map(str::trim) {
|
||||||
|
@ -146,6 +149,7 @@ pub(crate) trait MessageType: Sized {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
header::UPGRADE => {
|
header::UPGRADE => {
|
||||||
if let Ok(val) = value.to_str().map(str::trim) {
|
if let Ok(val) = value.to_str().map(str::trim) {
|
||||||
if val.eq_ignore_ascii_case("websocket") {
|
if val.eq_ignore_ascii_case("websocket") {
|
||||||
|
@ -153,23 +157,33 @@ pub(crate) trait MessageType: Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header::EXPECT => {
|
header::EXPECT => {
|
||||||
let bytes = value.as_bytes();
|
let bytes = value.as_bytes();
|
||||||
if bytes.len() >= 4 && &bytes[0..4] == b"100-" {
|
if bytes.len() >= 4 && &bytes[0..4] == b"100-" {
|
||||||
expect = true;
|
expect = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
headers.append(name, value);
|
headers.append(name, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_connection_type(ka);
|
self.set_connection_type(ka);
|
||||||
|
|
||||||
if expect {
|
if expect {
|
||||||
self.set_expect()
|
self.set_expect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove CL value if 0 now that all headers are processed. Protects against some request
|
||||||
|
// smuggling attacks. See https://github.com/actix/actix-web/issues/2767.
|
||||||
|
if matches!(content_length, Some(0)) {
|
||||||
|
content_length = None;
|
||||||
|
}
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.3
|
// https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.3
|
||||||
if chunked {
|
if chunked {
|
||||||
// Chunked encoding
|
// Chunked encoding
|
||||||
|
|
Loading…
Reference in New Issue