Skip to content

Commit da0fda0

Browse files
ShogunPandajuanarbol
authored andcommittedJul 7, 2022
http: stricter Transfer-Encoding and header separator parsing
Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> PR-URL: #315 Backport-PR-URL: #327 CVE-ID: CVE-2022-32215,CVE-2022-32214,CVE-2022-32213
1 parent b93e048 commit da0fda0

6 files changed

+806
-364
lines changed
 

‎deps/llhttp/include/llhttp.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#define LLHTTP_VERSION_MAJOR 2
55
#define LLHTTP_VERSION_MINOR 1
6-
#define LLHTTP_VERSION_PATCH 4
6+
#define LLHTTP_VERSION_PATCH 5
77

88
#ifndef LLHTTP_STRICT_MODE
99
# define LLHTTP_STRICT_MODE 0
@@ -58,6 +58,7 @@ enum llhttp_errno {
5858
HPE_OK = 0,
5959
HPE_INTERNAL = 1,
6060
HPE_STRICT = 2,
61+
HPE_CR_EXPECTED = 25,
6162
HPE_LF_EXPECTED = 3,
6263
HPE_UNEXPECTED_CONTENT_LENGTH = 4,
6364
HPE_CLOSED_CONNECTION = 5,
@@ -78,7 +79,7 @@ enum llhttp_errno {
7879
HPE_CB_CHUNK_COMPLETE = 20,
7980
HPE_PAUSED = 21,
8081
HPE_PAUSED_UPGRADE = 22,
81-
HPE_USER = 23
82+
HPE_USER = 24
8283
};
8384
typedef enum llhttp_errno llhttp_errno_t;
8485

@@ -153,6 +154,7 @@ typedef enum llhttp_method llhttp_method_t;
153154
XX(0, OK, OK) \
154155
XX(1, INTERNAL, INTERNAL) \
155156
XX(2, STRICT, STRICT) \
157+
XX(25, CR_EXPECTED, CR_EXPECTED) \
156158
XX(3, LF_EXPECTED, LF_EXPECTED) \
157159
XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \
158160
XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \
@@ -173,7 +175,7 @@ typedef enum llhttp_method llhttp_method_t;
173175
XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
174176
XX(21, PAUSED, PAUSED) \
175177
XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
176-
XX(23, USER, USER) \
178+
XX(24, USER, USER) \
177179

178180

179181
#define HTTP_METHOD_MAP(XX) \

‎deps/llhttp/src/llhttp.c

+687-349
Large diffs are not rendered by default.

‎test/parallel/test-http-invalid-te.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Content-Type: text/plain; charset=utf-8
1313
Host: hacker.exploit.com
1414
Connection: keep-alive
1515
Content-Length: 10
16-
Transfer-Encoding: chunked, eee
16+
Transfer-Encoding: eee, chunked
1717
1818
HELLOWORLDPOST / HTTP/1.1
1919
Content-Type: text/plain; charset=utf-8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
6+
const http = require('http');
7+
const net = require('net');
8+
9+
const msg = [
10+
'GET / HTTP/1.1',
11+
'Host: localhost',
12+
'Dummy: x\nContent-Length: 23',
13+
'',
14+
'GET / HTTP/1.1',
15+
'Dummy: GET /admin HTTP/1.1',
16+
'Host: localhost',
17+
'',
18+
'',
19+
].join('\r\n');
20+
21+
const server = http.createServer(common.mustNotCall());
22+
23+
server.listen(0, common.mustSucceed(() => {
24+
const client = net.connect(server.address().port, 'localhost');
25+
26+
let response = '';
27+
28+
client.on('data', common.mustCall((chunk) => {
29+
response += chunk.toString('utf-8');
30+
}));
31+
32+
client.setEncoding('utf8');
33+
client.on('error', common.mustNotCall());
34+
client.on('end', common.mustCall(() => {
35+
assert.strictEqual(
36+
response,
37+
'HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n'
38+
);
39+
server.close();
40+
}));
41+
client.write(msg);
42+
client.resume();
43+
}));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
6+
const http = require('http');
7+
const net = require('net');
8+
9+
const msg = [
10+
'POST / HTTP/1.1',
11+
'Host: 127.0.0.1',
12+
'Transfer-Encoding: chunkedchunked',
13+
'',
14+
'1',
15+
'A',
16+
'0',
17+
'',
18+
].join('\r\n');
19+
20+
const server = http.createServer(common.mustCall((req, res) => {
21+
// Verify that no data is received
22+
23+
req.on('data', common.mustNotCall());
24+
25+
req.on('end', common.mustNotCall(() => {
26+
res.writeHead(200, { 'Content-Type': 'text/plain' });
27+
res.end();
28+
}));
29+
}, 1));
30+
31+
server.listen(0, common.mustSucceed(() => {
32+
const client = net.connect(server.address().port, 'localhost');
33+
34+
let response = '';
35+
36+
client.on('data', common.mustCall((chunk) => {
37+
response += chunk.toString('utf-8');
38+
}));
39+
40+
client.setEncoding('utf8');
41+
client.on('error', common.mustNotCall());
42+
client.on('end', common.mustCall(() => {
43+
assert.strictEqual(
44+
response,
45+
'HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n'
46+
);
47+
server.close();
48+
}));
49+
client.write(msg);
50+
client.resume();
51+
}));

‎test/parallel/test-http-transfer-encoding-smuggling.js

+19-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const common = require('../common');
4+
const assert = require('assert');
45

56
const http = require('http');
67
const net = require('net');
@@ -22,23 +23,30 @@ const msg = [
2223
'',
2324
].join('\r\n');
2425

25-
// Verify that the server is called only once even with a smuggled request.
26-
27-
const server = http.createServer(common.mustCall((req, res) => {
26+
const server = http.createServer(common.mustNotCall((req, res) => {
2827
res.end();
2928
}, 1));
3029

31-
function send(next) {
30+
server.listen(0, common.mustSucceed(() => {
3231
const client = net.connect(server.address().port, 'localhost');
32+
33+
let response = '';
34+
35+
// Verify that the server listener is never called
36+
37+
client.on('data', common.mustCall((chunk) => {
38+
response += chunk.toString('utf-8');
39+
}));
40+
3341
client.setEncoding('utf8');
3442
client.on('error', common.mustNotCall());
35-
client.on('end', next);
36-
client.write(msg);
37-
client.resume();
38-
}
39-
40-
server.listen(0, common.mustSucceed(() => {
41-
send(common.mustCall(() => {
43+
client.on('end', common.mustCall(() => {
44+
assert.strictEqual(
45+
response,
46+
'HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n'
47+
);
4248
server.close();
4349
}));
50+
client.write(msg);
51+
client.resume();
4452
}));

0 commit comments

Comments
 (0)
Please sign in to comment.