Files
nodejs4/CVE-2018-12116.patch
Adam Majer 3f386ef218 Backport security fixes from NodeJS 6.x:
* debugger: prevent the debugger from listening on 0.0.0.0.
    It now defaults to 127.0.0.1.
    CVE-2018-12120.patch - (CVE-2018-12120, bsc#1117625)
  * http:
    + Two-byte characters are now strictly disallowed for the path
      option in HTTP client requests. Paths containing characters
      outside of the range \u0021 - \u00ff will now be rejected
      with a TypeError. This behavior can be reverted if necessary
      by supplying the --security-revert=CVE-2018-12116 command
      line argument (this is not recommended).
      CVE-2018-12116.patch - (CVE-2018-12116, bsc#1117630)
  * util: Fix a bug that would allow a hostname being spoofed when
    parsing URLs with url.parse() with the 'javascript:' protocol.
    CVE-2018-12123.patch - (CVE-2018-12123, bnc#1117629)

OBS-URL: https://build.opensuse.org/package/show/devel:languages:nodejs/nodejs4?expand=0&rev=99
2019-01-08 16:04:58 +00:00

336 lines
11 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Ported from following patches,
http: disallow two-byte characters in URL path
CVE-2018-12116
Backport of b961d9f to 6.x
Original commit:
This commit changes node's handling of two-byte characters in
the path component of an http URL. Previously, node would just
strip the higher byte when generating the request. So this code:
```
http.request({host: "example.com", port: "80", "/"})
```
would request `http://example.com/.`
(`.` is the character for the byte `0x2e`).
This is not useful and can in some cases lead to filter evasion.
With this change, the code generates `ERR_UNESCAPED_CHARACTERS`,
just like space and control characters already did.
PR-URL: #16237
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
PR-URL: nodejs-private/node-private#146
Fixes: nodejs-private/security#207
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
From 35344e87bfc7c01079502850ce023e781a85db2d Mon Sep 17 00:00:00 2001
From: James M Snell <jasnell@gmail.com>
Date: Wed, 16 Aug 2017 09:34:37 -0700
Subject: [PATCH] src: minor cleanup for node_revert
Make the revert related functions inline to eliminate the need
for node_revert.cc, prefitx the constants and the def, other misc
cleanup
PR-URL: https://github.com/nodejs/node/pull/14864
Reviewed-By: Anna Henningsen <anna@addaleax.net>
From dd20c0186fab9dd92b42f280b8d2b6f980f6b406 Mon Sep 17 00:00:00 2001
From: Matteo Collina <hello@matteocollina.com>
Date: Thu, 20 Sep 2018 15:02:26 +0200
Subject: [PATCH] http: add --security-revert for CVE-2018-12116
PR-URL: https://github.com/nodejs-private/node-private/pull/146
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Index: node-v4.9.1/lib/_http_client.js
===================================================================
--- node-v4.9.1.orig/lib/_http_client.js
+++ node-v4.9.1/lib/_http_client.js
@@ -14,6 +14,10 @@ const OutgoingMessage = require('_http_o
const Agent = require('_http_agent');
const Buffer = require('buffer').Buffer;
+const REVERT_CVE_2018_12116 = process.REVERT_CVE_2018_12116;
+
+const INVALID_PATH_REGEX = /[^\u0021-\u00ff]/;
+
function ClientRequest(options, cb) {
var self = this;
@@ -40,15 +44,21 @@ function ClientRequest(options, cb) {
if (self.agent && self.agent.protocol)
expectedProtocol = self.agent.protocol;
- if (options.path && /[\u0000-\u0020]/.test(options.path)) {
- // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
- // with an additional rule for ignoring percentage-escaped characters
- // but that's a) hard to capture in a regular expression that performs
- // well, and b) possibly too restrictive for real-world usage. That's
- // why it only scans for spaces because those are guaranteed to create
- // an invalid request.
- throw new TypeError('Request path contains unescaped characters.');
- } else if (protocol !== expectedProtocol) {
+ var path;
+ if (options.path) {
+ path = String(options.path);
+ var invalidPath;
+ if (REVERT_CVE_2018_12116) {
+ invalidPath = /[\u0000-\u0020]/.test(path);
+ } else {
+ invalidPath = INVALID_PATH_REGEX.test(path);
+ }
+
+ if (invalidPath)
+ throw new TypeError('Request path contains unescaped characters');
+ }
+
+ if (protocol !== expectedProtocol) {
throw new Error('Protocol "' + protocol + '" not supported. ' +
'Expected "' + expectedProtocol + '".');
}
Index: node-v4.9.1/test/parallel/test-http-client-invalid-path.js
===================================================================
--- /dev/null
+++ node-v4.9.1/test/parallel/test-http-client-invalid-path.js
@@ -0,0 +1,13 @@
+'use strict';
+
+require('../common');
+
+const http = require('http');
+const assert = require('assert');
+
+assert.throws(() => {
+ http.request({
+ path: '/thisisinvalid\uffe2'
+ }).end();
+}, /Request path contains unescaped characters/);
+
Index: node-v4.9.1/node.gyp
===================================================================
--- node-v4.9.1.orig/node.gyp
+++ node-v4.9.1/node.gyp
@@ -152,7 +152,6 @@
'src/node_javascript.cc',
'src/node_main.cc',
'src/node_os.cc',
- 'src/node_revert.cc',
'src/node_util.cc',
'src/node_v8.cc',
'src/node_stat_watcher.cc',
Index: node-v4.9.1/src/node.cc
===================================================================
--- node-v4.9.1.orig/src/node.cc
+++ node-v4.9.1/src/node.cc
@@ -153,6 +153,9 @@ static node_module* modlist_builtin;
static node_module* modlist_linked;
static node_module* modlist_addon;
+// Bit flag used to track security reverts (see node_revert.h)
+unsigned int reverted = 0;
+
#if defined(NODE_HAVE_I18N_SUPPORT)
// Path to ICU data (for i18n / Intl)
static const char* icu_data_dir = nullptr;
@@ -3126,11 +3129,11 @@ void SetupProcessObject(Environment* env
// --security-revert flags
#define V(code, _, __) \
do { \
- if (IsReverted(REVERT_ ## code)) { \
+ if (IsReverted(SECURITY_REVERT_ ## code)) { \
READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate())); \
} \
} while (0);
- REVERSIONS(V)
+ SECURITY_REVERSIONS(V)
#undef V
size_t exec_path_len = 2 * PATH_MAX;
Index: node-v4.9.1/src/node_revert.cc
===================================================================
--- node-v4.9.1.orig/src/node_revert.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "node_revert.h"
-#include <stdio.h>
-#include <string.h>
-
-namespace node {
-
-unsigned int reverted = 0;
-
-const char* RevertMessage(const unsigned int cve) {
-#define V(code, label, msg) case REVERT_ ## code: return label ": " msg;
- switch (cve) {
- REVERSIONS(V)
- default:
- return "Unknown";
- }
-#undef V
-}
-
-void Revert(const unsigned int cve) {
- reverted |= 1 << cve;
- printf("SECURITY WARNING: Reverting %s\n", RevertMessage(cve));
-}
-
-void Revert(const char* cve) {
-#define V(code, label, _) \
- do { \
- if (strcmp(cve, label) == 0) { \
- Revert(static_cast<unsigned int>(REVERT_ ## code)); \
- return; \
- } \
- } while (0);
- REVERSIONS(V)
-#undef V
- printf("Error: Attempt to revert an unknown CVE [%s]\n", cve);
- exit(12);
-}
-
-bool IsReverted(const unsigned int cve) {
- return reverted & (1 << cve);
-}
-
-bool IsReverted(const char * cve) {
-#define V(code, label, _) \
- do { \
- if (strcmp(cve, label) == 0) \
- return IsReverted(static_cast<unsigned int>(REVERT_ ## code)); \
- } while (0);
- REVERSIONS(V)
- return false;
-#undef V
-}
-
-} // namespace node
Index: node-v4.9.1/src/node_revert.h
===================================================================
--- node-v4.9.1.orig/src/node_revert.h
+++ node-v4.9.1/src/node_revert.h
@@ -2,6 +2,7 @@
#define SRC_NODE_REVERT_H_
#include "node.h"
+#include <string.h>
/**
* Note that it is expected for this list to vary across specific LTS and
@@ -10,33 +11,56 @@
* consensus.
*
* For *master* this list should always be empty!
- *
**/
-#define REVERSIONS(XX) \
- XX(CVE_2016_2216, "CVE-2016-2216", "Strict HTTP Header Parsing")
-
namespace node {
-typedef enum {
-#define V(code, _, __) REVERT_ ## code,
- REVERSIONS(V)
+#define SECURITY_REVERSIONS(XX) \
+ XX(CVE_2016_2216, "CVE-2016-2216", "Strict HTTP Header Parsing") \
+ XX(CVE_2018_12116, "CVE-2018-12116", "HTTP request splitting")
+
+enum reversion {
+#define V(code, ...) SECURITY_REVERT_##code,
+ SECURITY_REVERSIONS(V)
#undef V
-} reversions_t;
+};
-/* A bit field for tracking the active reverts */
extern unsigned int reverted;
-/* Revert the given CVE (see reversions_t enum) */
-void Revert(const unsigned int cve);
-
-/* Revert the given CVE by label */
-void Revert(const char* cve);
-
-/* true if the CVE has been reverted **/
-bool IsReverted(const unsigned int cve);
+inline const char* RevertMessage(const reversion cve) {
+#define V(code, label, msg) case SECURITY_REVERT_##code: return label ": " msg;
+ switch (cve) {
+ SECURITY_REVERSIONS(V)
+ default:
+ return "Unknown";
+ }
+#undef V
+}
-/* true if the CVE has been reverted **/
-bool IsReverted(const char * cve);
+inline void Revert(const reversion cve) {
+ reverted |= 1 << cve;
+ printf("SECURITY WARNING: Reverting %s\n", RevertMessage(cve));
+}
+
+inline void Revert(const char* cve) {
+#define V(code, label, _) \
+ if (strcmp(cve, label) == 0) return Revert(SECURITY_REVERT_##code);
+ SECURITY_REVERSIONS(V)
+#undef V
+ printf("Error: Attempt to revert an unknown CVE [%s]\n", cve);
+ exit(12);
+}
+
+inline bool IsReverted(const reversion cve) {
+ return reverted & (1 << cve);
+}
+
+inline bool IsReverted(const char* cve) {
+#define V(code, label, _) \
+ if (strcmp(cve, label) == 0) return IsReverted(SECURITY_REVERT_##code);
+ SECURITY_REVERSIONS(V)
+ return false;
+#undef V
+}
} // namespace node
Index: node-v4.9.1/src/node_http_parser.cc
===================================================================
--- node-v4.9.1.orig/src/node_http_parser.cc
+++ node-v4.9.1/src/node_http_parser.cc
@@ -679,7 +679,7 @@ class Parser : public AsyncWrap {
void Init(enum http_parser_type type) {
http_parser_init(&parser_, type);
/* Allow the strict http header parsing to be reverted */
- parser_.lenient_http_headers = IsReverted(REVERT_CVE_2016_2216) ? 1 : 0;
+ parser_.lenient_http_headers = IsReverted(SECURITY_REVERT_CVE_2016_2216) ? 1 : 0;
url_.Reset();
status_message_.Reset();
num_fields_ = 0;