From 75590792dbf1d1c79650339c0bb3c8e10d44809f Mon Sep 17 00:00:00 2001 From: zhanghua1831 Date: Mon, 21 Sep 2020 18:28:29 +0800 Subject: [PATCH] CVE-2018-12121 CVE-2018-12123 --- CVE-2018-12121.patch | 265 +++++++++++++++++++++++++++++++++++++++++++ CVE-2018-12123.patch | 107 +++++++++++++++++ nodejs.spec | 7 +- 3 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 CVE-2018-12121.patch create mode 100644 CVE-2018-12123.patch diff --git a/CVE-2018-12121.patch b/CVE-2018-12121.patch new file mode 100644 index 0000000..5a54b5a --- /dev/null +++ b/CVE-2018-12121.patch @@ -0,0 +1,265 @@ +From 186035243fad247e3955fa0c202987cae99e82db Mon Sep 17 00:00:00 2001 +From: Matteo Collina +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 +Reviewed-By: Ben Noordhuis +Reviewed-By: James M Snell +Reviewed-By: Rod Vagg +Reviewed-By: Anna Henningsen +--- + 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(); diff --git a/CVE-2018-12123.patch b/CVE-2018-12123.patch new file mode 100644 index 0000000..e50e42d --- /dev/null +++ b/CVE-2018-12123.patch @@ -0,0 +1,107 @@ +From 8b1405ee014033d9a36873f65ca49be11f15a569 Mon Sep 17 00:00:00 2001 +From: Matteo Collina +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 +Reviewed-By: Michael Dawson +Reviewed-By: Anna Henningsen +--- + 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); ++} diff --git a/nodejs.spec b/nodejs.spec index b6677dd..d2a5b78 100644 --- a/nodejs.spec +++ b/nodejs.spec @@ -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 - 1:10.11.0-6 +- Fix CVE-2018-12121 CVE-2018-12123 + * Fri Aug 28 2020 zhangjiapeng - 1:10.11.0-5 - Fix dist miss problem -- Gitee