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>
This commit is contained in:
Matteo Collina 2018-09-10 12:57:07 +02:00 committed by Rod Vagg
parent ee618a7ab2
commit b77f699a84
2 changed files with 57 additions and 2 deletions

View File

@ -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.

View File

@ -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);
}