diff options
author | Matteo Collina <hello@matteocollina.com> | 2018-09-10 12:57:07 +0200 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2018-11-28 11:36:34 +1100 |
commit | b77f699a84219702ccef6387882c0fdcb58529bb (patch) | |
tree | 184b40b30b832b5caf6fd28219144f1167b13b59 | |
parent | ee618a7ab239c98d945c723a4e225bc409151736 (diff) | |
download | android-node-v8-b77f699a84219702ccef6387882c0fdcb58529bb.tar.gz android-node-v8-b77f699a84219702ccef6387882c0fdcb58529bb.tar.bz2 android-node-v8-b77f699a84219702ccef6387882c0fdcb58529bb.zip |
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>
-rw-r--r-- | lib/url.js | 4 | ||||
-rw-r--r-- | 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 db7369fed0..dfdb565cec 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 f4e72ee5ef..b18a5fe585 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); +} |