From 679269932c3f70c5f024bd0b407645d0782e5972 Mon Sep 17 00:00:00 2001 From: sdlzx Date: Sat, 20 Mar 2021 17:49:15 +0800 Subject: [PATCH] fix CVE-2020-22883 and CVE-2020-22884 --- CVE-2020-22883.patch | 138 +++++++++++++++++++++++++++++++++++++++++++ CVE-2020-22884.patch | 35 +++++++++++ nodejs.spec | 5 ++ 3 files changed, 178 insertions(+) create mode 100644 CVE-2020-22883.patch create mode 100644 CVE-2020-22884.patch diff --git a/CVE-2020-22883.patch b/CVE-2020-22883.patch new file mode 100644 index 0000000..9c85255 --- /dev/null +++ b/CVE-2020-22883.patch @@ -0,0 +1,138 @@ +From 4184806deed6b6c393dd8737aab1dc0c78a24c78 Mon Sep 17 00:00:00 2001 +From: Daniel Bevenius +Date: Fri, 22 Jan 2021 12:34:21 +0100 +Subject: [PATCH] http2: add unknownProtocol timeout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit add a configuration options named unknownProtocolTimeout +which can be specified to set a value for the timeout in milliseconds +that a server should wait when an unknowProtocol is sent to it. When +this happens a timer will be started and the if the socket has not been +destroyed during that time the timer callback will destoy it. + +Refs: https://hackerone.com/reports/1043360 +CVE-ID: CVE-2021-22883 +PR-URL: https://github.com/nodejs-private/node-private/pull/246 +Reviewed-By: Beth Griggs +Reviewed-By: Matteo Collina +Reviewed-By: Michael Dawson +Reviewed-By: Rich Trott +Reviewed-By: Tobias Nießen +--- + lib/internal/http2/core.js | 31 ++++++++++++++--- + .../test-http2-server-unknown-protocol.js | 33 +++++++++++++++++++ + 2 files changed, 60 insertions(+), 4 deletions(-) + create mode 100644 test/parallel/test-http2-server-unknown-protocol.js + +diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js +index 2116bc82..e9a63feb 100644 +--- a/lib/internal/http2/core.js ++++ b/lib/internal/http2/core.js +@@ -33,7 +33,7 @@ const net = require('net'); + const { Duplex } = require('stream'); + const tls = require('tls'); + const { URL } = require('url'); +-const { setImmediate } = require('timers'); ++const { setImmediate, setTimeout, clearTimeout } = require('timers'); + + const { kIncomingMessage } = require('_http_common'); + const { kServerResponse } = require('_http_server'); +@@ -2721,14 +2721,14 @@ function handleHeaderContinue(headers) { + this.emit('continue'); + } + +-const setTimeout = { ++const setTimeoutValue = { + configurable: true, + enumerable: true, + writable: true, + value: setStreamTimeout + }; +-ObjectDefineProperty(Http2Stream.prototype, 'setTimeout', setTimeout); +-ObjectDefineProperty(Http2Session.prototype, 'setTimeout', setTimeout); ++ObjectDefineProperty(Http2Stream.prototype, 'setTimeout', setTimeoutValue); ++ObjectDefineProperty(Http2Session.prototype, 'setTimeout', setTimeoutValue); + + + // When the socket emits an error, destroy the associated Http2Session and +@@ -2788,6 +2788,22 @@ function connectionListener(socket) { + debug('Unknown protocol from %s:%s', + socket.remoteAddress, socket.remotePort); + if (!this.emit('unknownProtocol', socket)) { ++ debug('Unknown protocol timeout: %s', options.unknownProtocolTimeout); ++ // Install a timeout if the socket was not successfully closed, then ++ // destroy the socket to ensure that the underlying resources are ++ // released. ++ const timer = setTimeout(() => { ++ if (!socket.destroyed) { ++ debug('UnknownProtocol socket timeout, destroy socket'); ++ socket.destroy(); ++ } ++ }, options.unknownProtocolTimeout); ++ // Un-reference the timer to avoid blocking of application shutdown and ++ // clear the timeout if the socket was successfully closed. ++ timer.unref(); ++ ++ socket.once('close', () => clearTimeout(timer)); ++ + // We don't know what to do, so let's just tell the other side what's + // going on in a format that they *might* understand. + socket.end('HTTP/1.0 403 Forbidden\r\n' + +@@ -2836,6 +2852,13 @@ function initializeOptions(options) { + ); + } + ++ if (options.unknownProtocolTimeout !== undefined) ++ validateUint32(options.unknownProtocolTimeout, 'unknownProtocolTimeout'); ++ else ++ // TODO(danbev): is this a good default value? ++ options.unknownProtocolTimeout = 10000; ++ ++ + // Used only with allowHTTP1 + options.Http1IncomingMessage = options.Http1IncomingMessage || + http.IncomingMessage; +diff --git a/test/parallel/test-http2-server-unknown-protocol.js b/test/parallel/test-http2-server-unknown-protocol.js +new file mode 100644 +index 00000000..639bbe4f +--- /dev/null ++++ b/test/parallel/test-http2-server-unknown-protocol.js +@@ -0,0 +1,33 @@ ++'use strict'; ++const common = require('../common'); ++const fixtures = require('../common/fixtures'); ++ ++// This test verifies that when a server receives an unknownProtocol it will ++// not leave the socket open if the client does not close it. ++ ++if (!common.hasCrypto) ++ common.skip('missing crypto'); ++ ++const h2 = require('http2'); ++const tls = require('tls'); ++ ++const server = h2.createSecureServer({ ++ key: fixtures.readKey('rsa_private.pem'), ++ cert: fixtures.readKey('rsa_cert.crt'), ++ unknownProtocolTimeout: 500, ++ allowHalfOpen: true ++}); ++ ++server.on('connection', (socket) => { ++ socket.on('close', common.mustCall(() => { ++ server.close(); ++ })); ++}); ++ ++server.listen(0, function() { ++ tls.connect({ ++ port: server.address().port, ++ rejectUnauthorized: false, ++ ALPNProtocols: ['bogus'] ++ }); ++}); +-- +2.25.1 + diff --git a/CVE-2020-22884.patch b/CVE-2020-22884.patch new file mode 100644 index 0000000..789727b --- /dev/null +++ b/CVE-2020-22884.patch @@ -0,0 +1,35 @@ +From 43ae9c46c35a935723a9109828c87380d781e147 Mon Sep 17 00:00:00 2001 +From: Matteo Collina +Date: Thu, 14 Jan 2021 16:04:44 +0100 +Subject: [PATCH] src: drop localhost6 as allowed host for inspector +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +CVE-ID: CVE-2021-22884 +Refs: https://hackerone.com/bugs?report_id=1069487 +PR-URL: https://github.com/nodejs-private/node-private/pull/244 +Reviewed-By: Beth Griggs +Reviewed-By: Daniel Bevenius +Reviewed-By: Mary Marchini +Reviewed-By: Michael Dawson +Reviewed-By: Michaël Zasso +Reviewed-By: Rich Trott +--- + src/inspector_socket.cc | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc +index 35306af3c66..9014bf3e3ff 100644 +--- a/src/inspector_socket.cc ++++ b/src/inspector_socket.cc +@@ -580,8 +580,7 @@ class HttpHandler : public ProtocolHandler { + bool IsAllowedHost(const std::string& host_with_port) const { + std::string host = TrimPort(host_with_port); + return host.empty() || IsIPAddress(host) +- || node::StringEqualNoCase(host.data(), "localhost") +- || node::StringEqualNoCase(host.data(), "localhost6"); ++ || node::StringEqualNoCase(host.data(), "localhost"); + } + + bool parsing_value_; diff --git a/nodejs.spec b/nodejs.spec index 2f21052..2dfb40b 100644 --- a/nodejs.spec +++ b/nodejs.spec @@ -85,6 +85,8 @@ Patch0002: 0002-Install-both-binaries-and-use-libdir.patch Patch0003: 0003-Modify-openEuler-aarch64-v8_os_page_size-to-64.patch %endif Patch0004: 0004-Make-AARCH64-compile-on-64KB-physical-pages.patch +Patch0005: CVE-2020-22883.patch +Patch0006: CVE-2020-22884.patch BuildRequires: python3-devel BuildRequires: zlib-devel BuildRequires: brotli-devel @@ -486,6 +488,9 @@ end %{_pkgdocdir}/npm/docs %changelog +* Sat Mar 20 2021 sdlzx - 1:12.18.4-3 +- Fix CVE-2020-22883 and CVE-2020-22884 + * Mon Jan 04 2020 huanghaitao - 1:12.18.4-2 - Make AARCH64 compile on 64KB physical pages to fix build error -- Gitee