CVE-2018-12121 CVE-2018-12123
This commit is contained in:
parent
b16eabab94
commit
75590792db
265
CVE-2018-12121.patch
Normal file
265
CVE-2018-12121.patch
Normal file
@ -0,0 +1,265 @@
|
||||
From 186035243fad247e3955fa0c202987cae99e82db Mon Sep 17 00:00:00 2001
|
||||
From: Matteo Collina <hello@matteocollina.com>
|
||||
Date: Tue, 21 Aug 2018 17:26:51 +0200
|
||||
Subject: [PATCH] deps,http: http_parser set max header size to 8KB
|
||||
|
||||
CVE-2018-12121
|
||||
|
||||
PR-URL: https://github.com/nodejs-private/node-private/pull/143
|
||||
Ref: https://github.com/nodejs-private/security/issues/139
|
||||
Ref: https://github.com/nodejs-private/http-parser-private/pull/2
|
||||
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Reviewed-By: James M Snell <jasnell@gmail.com>
|
||||
Reviewed-By: Rod Vagg <rod@vagg.org>
|
||||
Reviewed-By: Anna Henningsen <anna@addaleax.net>
|
||||
---
|
||||
deps/http_parser/http_parser.gyp | 4 +-
|
||||
test/parallel/test-http-max-headers-count.js | 6 +-
|
||||
test/parallel/test-https-max-headers-count.js | 6 +-
|
||||
test/sequential/test-http-max-http-headers.js | 154 ++++++++++++++++++
|
||||
4 files changed, 162 insertions(+), 8 deletions(-)
|
||||
create mode 100644 test/sequential/test-http-max-http-headers.js
|
||||
|
||||
diff --git a/deps/http_parser/http_parser.gyp b/deps/http_parser/http_parser.gyp
|
||||
index ef34ecaeaea..4364f73d1f4 100644
|
||||
--- a/deps/http_parser/http_parser.gyp
|
||||
+++ b/deps/http_parser/http_parser.gyp
|
||||
@@ -56,7 +56,7 @@
|
||||
'defines': [ 'HTTP_PARSER_STRICT=0' ],
|
||||
'include_dirs': [ '.' ],
|
||||
},
|
||||
- 'defines': [ 'HTTP_PARSER_STRICT=0' ],
|
||||
+ 'defines': [ 'HTTP_MAX_HEADER_SIZE=8192', 'HTTP_PARSER_STRICT=0' ],
|
||||
'sources': [ './http_parser.c', ],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
@@ -79,7 +79,7 @@
|
||||
'defines': [ 'HTTP_PARSER_STRICT=1' ],
|
||||
'include_dirs': [ '.' ],
|
||||
},
|
||||
- 'defines': [ 'HTTP_PARSER_STRICT=1' ],
|
||||
+ 'defines': [ 'HTTP_MAX_HEADER_SIZE=8192', 'HTTP_PARSER_STRICT=1' ],
|
||||
'sources': [ './http_parser.c', ],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
diff --git a/test/parallel/test-http-max-headers-count.js b/test/parallel/test-http-max-headers-count.js
|
||||
index 05f4f774c2c..9fcfe316e39 100644
|
||||
--- a/test/parallel/test-http-max-headers-count.js
|
||||
+++ b/test/parallel/test-http-max-headers-count.js
|
||||
@@ -28,14 +28,14 @@ let requests = 0;
|
||||
let responses = 0;
|
||||
|
||||
const headers = {};
|
||||
-const N = 2000;
|
||||
+const N = 100;
|
||||
for (let i = 0; i < N; ++i) {
|
||||
headers[`key${i}`] = i;
|
||||
}
|
||||
|
||||
const maxAndExpected = [ // for server
|
||||
[50, 50],
|
||||
- [1500, 1500],
|
||||
+ [1500, 102],
|
||||
[0, N + 2] // Host and Connection
|
||||
];
|
||||
let max = maxAndExpected[requests][0];
|
||||
@@ -56,7 +56,7 @@ server.maxHeadersCount = max;
|
||||
server.listen(0, function() {
|
||||
const maxAndExpected = [ // for client
|
||||
[20, 20],
|
||||
- [1200, 1200],
|
||||
+ [1200, 103],
|
||||
[0, N + 3] // Connection, Date and Transfer-Encoding
|
||||
];
|
||||
doRequest();
|
||||
diff --git a/test/parallel/test-https-max-headers-count.js b/test/parallel/test-https-max-headers-count.js
|
||||
index 8c099d1e5fb..12aaaa9cd3a 100644
|
||||
--- a/test/parallel/test-https-max-headers-count.js
|
||||
+++ b/test/parallel/test-https-max-headers-count.js
|
||||
@@ -17,14 +17,14 @@ let requests = 0;
|
||||
let responses = 0;
|
||||
|
||||
const headers = {};
|
||||
-const N = 2000;
|
||||
+const N = 100;
|
||||
for (let i = 0; i < N; ++i) {
|
||||
headers[`key${i}`] = i;
|
||||
}
|
||||
|
||||
const maxAndExpected = [ // for server
|
||||
[50, 50],
|
||||
- [1500, 1500],
|
||||
+ [1500, 102],
|
||||
[0, N + 2] // Host and Connection
|
||||
];
|
||||
let max = maxAndExpected[requests][0];
|
||||
@@ -45,7 +45,7 @@ server.maxHeadersCount = max;
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const maxAndExpected = [ // for client
|
||||
[20, 20],
|
||||
- [1200, 1200],
|
||||
+ [1200, 103],
|
||||
[0, N + 3] // Connection, Date and Transfer-Encoding
|
||||
];
|
||||
const doRequest = common.mustCall(() => {
|
||||
diff --git a/test/sequential/test-http-max-http-headers.js b/test/sequential/test-http-max-http-headers.js
|
||||
new file mode 100644
|
||||
index 00000000000..155b75fb076
|
||||
--- /dev/null
|
||||
+++ b/test/sequential/test-http-max-http-headers.js
|
||||
@@ -0,0 +1,154 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const assert = require('assert');
|
||||
+const common = require('../common');
|
||||
+const http = require('http');
|
||||
+const net = require('net');
|
||||
+const MAX = 8 * 1024; // 8KB
|
||||
+
|
||||
+// Verify that we cannot receive more than 8KB of headers.
|
||||
+
|
||||
+function once(cb) {
|
||||
+ let called = false;
|
||||
+ return () => {
|
||||
+ if (!called) {
|
||||
+ called = true;
|
||||
+ cb();
|
||||
+ }
|
||||
+ };
|
||||
+}
|
||||
+
|
||||
+function finished(client, callback) {
|
||||
+ 'abort error end'.split(' ').forEach((e) => {
|
||||
+ client.on(e, once(() => setImmediate(callback)));
|
||||
+ });
|
||||
+}
|
||||
+
|
||||
+function fillHeaders(headers, currentSize, valid = false) {
|
||||
+ // Generate valid headers
|
||||
+ if (valid) {
|
||||
+ // TODO(mcollina): understand why -9 is needed instead of -1
|
||||
+ headers = headers.slice(0, -9);
|
||||
+ }
|
||||
+ return headers + '\r\n\r\n';
|
||||
+}
|
||||
+
|
||||
+const timeout = common.platformTimeout(10);
|
||||
+
|
||||
+function writeHeaders(socket, headers) {
|
||||
+ const array = [];
|
||||
+
|
||||
+ // this is off from 1024 so that \r\n does not get split
|
||||
+ const chunkSize = 1000;
|
||||
+ let last = 0;
|
||||
+
|
||||
+ for (let i = 0; i < headers.length / chunkSize; i++) {
|
||||
+ const current = (i + 1) * chunkSize;
|
||||
+ array.push(headers.slice(last, current));
|
||||
+ last = current;
|
||||
+ }
|
||||
+
|
||||
+ // safety check we are chunking correctly
|
||||
+ assert.strictEqual(array.join(''), headers);
|
||||
+
|
||||
+ next();
|
||||
+
|
||||
+ function next() {
|
||||
+ if (socket.write(array.shift())) {
|
||||
+ if (array.length === 0) {
|
||||
+ socket.end();
|
||||
+ } else {
|
||||
+ setTimeout(next, timeout);
|
||||
+ }
|
||||
+ } else {
|
||||
+ socket.once('drain', next);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+function test1() {
|
||||
+ let headers =
|
||||
+ 'HTTP/1.1 200 OK\r\n' +
|
||||
+ 'Content-Length: 0\r\n' +
|
||||
+ 'X-CRASH: ';
|
||||
+
|
||||
+ // OK, Content-Length, 0, X-CRASH, aaa...
|
||||
+ const currentSize = 2 + 14 + 1 + 7;
|
||||
+ headers = fillHeaders(headers, currentSize);
|
||||
+
|
||||
+ const server = net.createServer((sock) => {
|
||||
+ sock.once('data', (chunk) => {
|
||||
+ writeHeaders(sock, headers);
|
||||
+ sock.resume();
|
||||
+ });
|
||||
+ });
|
||||
+
|
||||
+ server.listen(0, common.mustCall(() => {
|
||||
+ const port = server.address().port;
|
||||
+ const client = http.get({ port: port }, common.mustNotCall(() => {}));
|
||||
+
|
||||
+ client.on('error', common.mustCall((err) => {
|
||||
+ assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW');
|
||||
+ server.close();
|
||||
+ setImmediate(test2);
|
||||
+ }));
|
||||
+ }));
|
||||
+}
|
||||
+
|
||||
+const test2 = common.mustCall(() => {
|
||||
+ let headers =
|
||||
+ 'GET / HTTP/1.1\r\n' +
|
||||
+ 'Host: localhost\r\n' +
|
||||
+ 'Agent: node\r\n' +
|
||||
+ 'X-CRASH: ';
|
||||
+
|
||||
+ // /, Host, localhost, Agent, node, X-CRASH, a...
|
||||
+ const currentSize = 1 + 4 + 9 + 5 + 4 + 7;
|
||||
+ headers = fillHeaders(headers, currentSize);
|
||||
+
|
||||
+ const server = http.createServer(common.mustNotCall());
|
||||
+
|
||||
+ server.on('clientError', common.mustCall((err) => {
|
||||
+ assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW');
|
||||
+ }));
|
||||
+
|
||||
+ server.listen(0, common.mustCall(() => {
|
||||
+ const client = net.connect(server.address().port);
|
||||
+ client.on('connect', () => {
|
||||
+ writeHeaders(client, headers);
|
||||
+ client.resume();
|
||||
+ });
|
||||
+
|
||||
+ finished(client, common.mustCall((err) => {
|
||||
+ server.close();
|
||||
+ setImmediate(test3);
|
||||
+ }));
|
||||
+ }));
|
||||
+});
|
||||
+
|
||||
+const test3 = common.mustCall(() => {
|
||||
+ let headers =
|
||||
+ 'GET / HTTP/1.1\r\n' +
|
||||
+ 'Host: localhost\r\n' +
|
||||
+ 'Agent: node\r\n' +
|
||||
+ 'X-CRASH: ';
|
||||
+
|
||||
+ // /, Host, localhost, Agent, node, X-CRASH, a...
|
||||
+ const currentSize = 1 + 4 + 9 + 5 + 4 + 7;
|
||||
+ headers = fillHeaders(headers, currentSize, true);
|
||||
+
|
||||
+ const server = http.createServer(common.mustCall((req, res) => {
|
||||
+ res.end('hello world');
|
||||
+ setImmediate(server.close.bind(server));
|
||||
+ }));
|
||||
+
|
||||
+ server.listen(0, common.mustCall(() => {
|
||||
+ const client = net.connect(server.address().port);
|
||||
+ client.on('connect', () => {
|
||||
+ writeHeaders(client, headers);
|
||||
+ client.resume();
|
||||
+ });
|
||||
+ }));
|
||||
+});
|
||||
+
|
||||
+test1();
|
||||
107
CVE-2018-12123.patch
Normal file
107
CVE-2018-12123.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From 8b1405ee014033d9a36873f65ca49be11f15a569 Mon Sep 17 00:00:00 2001
|
||||
From: Matteo Collina <hello@matteocollina.com>
|
||||
Date: Mon, 10 Sep 2018 12:57:07 +0200
|
||||
Subject: [PATCH] url: avoid hostname spoofing w/ javascript protocol
|
||||
|
||||
CVE-2018-12123
|
||||
|
||||
Fixes: https://github.com/nodejs-private/security/issues/205
|
||||
PR-URL: https://github.com/nodejs-private/node-private/pull/145
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
|
||||
Reviewed-By: Anna Henningsen <anna@addaleax.net>
|
||||
---
|
||||
lib/url.js | 4 +-
|
||||
test/parallel/test-url-parse-format.js | 55 ++++++++++++++++++++++++++
|
||||
2 files changed, 57 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/url.js b/lib/url.js
|
||||
index ba2033b4e53..676722de622 100644
|
||||
--- a/lib/url.js
|
||||
+++ b/lib/url.js
|
||||
@@ -267,13 +267,13 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
|
||||
if (slashesDenoteHost || proto || hostPattern.test(rest)) {
|
||||
var slashes = rest.charCodeAt(0) === CHAR_FORWARD_SLASH &&
|
||||
rest.charCodeAt(1) === CHAR_FORWARD_SLASH;
|
||||
- if (slashes && !(proto && hostlessProtocol[proto])) {
|
||||
+ if (slashes && !(proto && hostlessProtocol[lowerProto])) {
|
||||
rest = rest.slice(2);
|
||||
this.slashes = true;
|
||||
}
|
||||
}
|
||||
|
||||
- if (!hostlessProtocol[proto] &&
|
||||
+ if (!hostlessProtocol[lowerProto] &&
|
||||
(slashes || (proto && !slashedProtocol[proto]))) {
|
||||
|
||||
// there's a hostname.
|
||||
diff --git a/test/parallel/test-url-parse-format.js b/test/parallel/test-url-parse-format.js
|
||||
index f4e72ee5ef4..b18a5fe585d 100644
|
||||
--- a/test/parallel/test-url-parse-format.js
|
||||
+++ b/test/parallel/test-url-parse-format.js
|
||||
@@ -890,6 +890,39 @@ const parseTests = {
|
||||
pathname: '/*',
|
||||
path: '/*',
|
||||
href: 'https:///*'
|
||||
+ },
|
||||
+
|
||||
+ // The following two URLs are the same, but they differ for
|
||||
+ // a capital A: it is important that we verify that the protocol
|
||||
+ // is checked in a case-insensitive manner.
|
||||
+ 'javascript:alert(1);a=\x27@white-listed.com\x27': {
|
||||
+ protocol: 'javascript:',
|
||||
+ slashes: null,
|
||||
+ auth: null,
|
||||
+ host: null,
|
||||
+ port: null,
|
||||
+ hostname: null,
|
||||
+ hash: null,
|
||||
+ search: null,
|
||||
+ query: null,
|
||||
+ pathname: "alert(1);a='@white-listed.com'",
|
||||
+ path: "alert(1);a='@white-listed.com'",
|
||||
+ href: "javascript:alert(1);a='@white-listed.com'"
|
||||
+ },
|
||||
+
|
||||
+ 'javAscript:alert(1);a=\x27@white-listed.com\x27': {
|
||||
+ protocol: 'javascript:',
|
||||
+ slashes: null,
|
||||
+ auth: null,
|
||||
+ host: null,
|
||||
+ port: null,
|
||||
+ hostname: null,
|
||||
+ hash: null,
|
||||
+ search: null,
|
||||
+ query: null,
|
||||
+ pathname: "alert(1);a='@white-listed.com'",
|
||||
+ path: "alert(1);a='@white-listed.com'",
|
||||
+ href: "javascript:alert(1);a='@white-listed.com'"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -921,3 +954,25 @@ for (const u in parseTests) {
|
||||
assert.strictEqual(actual, expected,
|
||||
`format(${u}) == ${u}\nactual:${actual}`);
|
||||
}
|
||||
+
|
||||
+{
|
||||
+ const parsed = url.parse('http://nodejs.org/')
|
||||
+ .resolveObject('jAvascript:alert(1);a=\x27@white-listed.com\x27');
|
||||
+
|
||||
+ const expected = Object.assign(new url.Url(), {
|
||||
+ protocol: 'javascript:',
|
||||
+ slashes: null,
|
||||
+ auth: null,
|
||||
+ host: null,
|
||||
+ port: null,
|
||||
+ hostname: null,
|
||||
+ hash: null,
|
||||
+ search: null,
|
||||
+ query: null,
|
||||
+ pathname: "alert(1);a='@white-listed.com'",
|
||||
+ path: "alert(1);a='@white-listed.com'",
|
||||
+ href: "javascript:alert(1);a='@white-listed.com'"
|
||||
+ });
|
||||
+
|
||||
+ assert.deepStrictEqual(parsed, expected);
|
||||
+}
|
||||
@ -6,7 +6,7 @@
|
||||
%global nodejs_patch 0
|
||||
%global nodejs_abi %{nodejs_major}.%{nodejs_minor}
|
||||
%global nodejs_version %{nodejs_major}.%{nodejs_minor}.%{nodejs_patch}
|
||||
%global nodejs_release 5
|
||||
%global nodejs_release 6
|
||||
|
||||
%global v8_major 6
|
||||
%global v8_minor 8
|
||||
@ -42,6 +42,8 @@ Patch0002: Suppress-NPM-message-to-run-global-update.patch
|
||||
Patch0003: CVE-2018-12122.patch
|
||||
#https://github.com/nodejs/node/commit/1a7302bd48
|
||||
Patch0004: CVE-2019-5737.patch
|
||||
Patch0005: CVE-2018-12121.patch
|
||||
Patch0006: CVE-2018-12123.patch
|
||||
|
||||
BuildRequires: gcc gcc-c++ openssl-devel
|
||||
BuildRequires: http-parser-devel
|
||||
@ -216,6 +218,9 @@ NODE_PATH=%{buildroot}%{_prefix}/lib/node_modules:%{buildroot}%{_prefix}/lib/nod
|
||||
%doc %{_mandir}/man1/node.1*
|
||||
|
||||
%changelog
|
||||
* Sun Sep 20 2020 zhangtao <zhangtao221@huawei.com> - 1:10.11.0-6
|
||||
- Fix CVE-2018-12121 CVE-2018-12123
|
||||
|
||||
* Fri Aug 28 2020 zhangjiapeng <zhangjiapeng9@huawei.com> - 1:10.11.0-5
|
||||
- Fix dist miss problem
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user