From ac43ca8f80c042f0256fb551ea5203863dec4481 Mon Sep 17 00:00:00 2001 From: Rodney Rehm Date: Sun, 11 Jul 2021 20:16:43 +0200 Subject: [PATCH] fix(parse): more backslash galore #410 issue reported privately by @ready-research via https://huntr.dev/ --- src/URI.js | 3 + test/urls.js | 343 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 346 insertions(+) diff --git a/src/URI.js b/src/URI.js index 0a5e77e..9a601a3 100644 --- a/src/URI.js +++ b/src/URI.js @@ -512,6 +512,9 @@ string = string.substring(0, pos); } + // slashes and backslashes have lost all meaning for the web protocols (https, http, wss, ws) + string = string.replace(/^(https?|ftp|wss?)?:[/\\]*/, '$1://'); + // extract protocol if (string.substring(0, 2) === '//') { // relative-scheme diff --git a/test/urls.js b/test/urls.js index 30547e6..efb192f 100644 --- a/test/urls.js +++ b/test/urls.js @@ -2131,6 +2131,349 @@ var urls = [{ idn: false, punycode: false } + }, { + name: 'backslashes protocol excessive', + url: 'https:/\/\/\attacker.com', + _url: 'https://attacker.com/', + parts: { + protocol: 'https', + username: null, + password: null, + hostname: 'attacker.com', + port: null, + path: '/', + query: null, + fragment: null + }, + accessors: { + protocol: 'https', + username: '', + password: '', + port: '', + path: '/', + query: '', + fragment: '', + resource: '/', + authority: 'attacker.com', + origin: 'https://attacker.com', + userinfo: '', + subdomain: '', + domain: 'attacker.com', + tld: 'com', + directory: '/', + filename: '', + suffix: '', + hash: '', + search: '', + host: 'attacker.com', + hostname: 'attacker.com' + }, + is: { + urn: false, + url: true, + relative: false, + name: true, + sld: false, + ip: false, + ip4: false, + ip6: false, + idn: false, + punycode: false + } + }, { + name: 'no slash protocol https', + url: 'https:attacker.com', + _url: 'https://attacker.com/', + parts: { + protocol: 'https', + username: null, + password: null, + hostname: 'attacker.com', + port: null, + path: '/', + query: null, + fragment: null + }, + accessors: { + protocol: 'https', + username: '', + password: '', + port: '', + path: '/', + query: '', + fragment: '', + resource: '/', + authority: 'attacker.com', + origin: 'https://attacker.com', + userinfo: '', + subdomain: '', + domain: 'attacker.com', + tld: 'com', + directory: '/', + filename: '', + suffix: '', + hash: '', + search: '', + host: 'attacker.com', + hostname: 'attacker.com' + }, + is: { + urn: false, + url: true, + relative: false, + name: true, + sld: false, + ip: false, + ip4: false, + ip6: false, + idn: false, + punycode: false + } + }, { + name: 'single slash protocol https', + url: 'https:/attacker.com', + _url: 'https://attacker.com/', + parts: { + protocol: 'https', + username: null, + password: null, + hostname: 'attacker.com', + port: null, + path: '/', + query: null, + fragment: null + }, + accessors: { + protocol: 'https', + username: '', + password: '', + port: '', + path: '/', + query: '', + fragment: '', + resource: '/', + authority: 'attacker.com', + origin: 'https://attacker.com', + userinfo: '', + subdomain: '', + domain: 'attacker.com', + tld: 'com', + directory: '/', + filename: '', + suffix: '', + hash: '', + search: '', + host: 'attacker.com', + hostname: 'attacker.com' + }, + is: { + urn: false, + url: true, + relative: false, + name: true, + sld: false, + ip: false, + ip4: false, + ip6: false, + idn: false, + punycode: false + } + }, { + name: 'excessive slash protocol https', + url: 'https://////attacker.com', + _url: 'https://attacker.com/', + parts: { + protocol: 'https', + username: null, + password: null, + hostname: 'attacker.com', + port: null, + path: '/', + query: null, + fragment: null + }, + accessors: { + protocol: 'https', + username: '', + password: '', + port: '', + path: '/', + query: '', + fragment: '', + resource: '/', + authority: 'attacker.com', + origin: 'https://attacker.com', + userinfo: '', + subdomain: '', + domain: 'attacker.com', + tld: 'com', + directory: '/', + filename: '', + suffix: '', + hash: '', + search: '', + host: 'attacker.com', + hostname: 'attacker.com' + }, + is: { + urn: false, + url: true, + relative: false, + name: true, + sld: false, + ip: false, + ip4: false, + ip6: false, + idn: false, + punycode: false + } + }, { + name: 'no slash protocol ftp', + url: 'ftp:attacker.com', + _url: 'ftp://attacker.com/', + parts: { + protocol: 'ftp', + username: null, + password: null, + hostname: 'attacker.com', + port: null, + path: '/', + query: null, + fragment: null + }, + accessors: { + protocol: 'ftp', + username: '', + password: '', + port: '', + path: '/', + query: '', + fragment: '', + resource: '/', + authority: 'attacker.com', + origin: 'ftp://attacker.com', + userinfo: '', + subdomain: '', + domain: 'attacker.com', + tld: 'com', + directory: '/', + filename: '', + suffix: '', + hash: '', + search: '', + host: 'attacker.com', + hostname: 'attacker.com' + }, + is: { + urn: false, + url: true, + relative: false, + name: true, + sld: false, + ip: false, + ip4: false, + ip6: false, + idn: false, + punycode: false + } + }, { + name: 'single slash protocol ftp', + url: 'ftp:/attacker.com', + _url: 'ftp://attacker.com/', + parts: { + protocol: 'ftp', + username: null, + password: null, + hostname: 'attacker.com', + port: null, + path: '/', + query: null, + fragment: null + }, + accessors: { + protocol: 'ftp', + username: '', + password: '', + port: '', + path: '/', + query: '', + fragment: '', + resource: '/', + authority: 'attacker.com', + origin: 'ftp://attacker.com', + userinfo: '', + subdomain: '', + domain: 'attacker.com', + tld: 'com', + directory: '/', + filename: '', + suffix: '', + hash: '', + search: '', + host: 'attacker.com', + hostname: 'attacker.com' + }, + is: { + urn: false, + url: true, + relative: false, + name: true, + sld: false, + ip: false, + ip4: false, + ip6: false, + idn: false, + punycode: false + } + }, { + name: 'excessive slash protocol ftp', + url: 'ftp://////attacker.com', + _url: 'ftp://attacker.com/', + parts: { + protocol: 'ftp', + username: null, + password: null, + hostname: 'attacker.com', + port: null, + path: '/', + query: null, + fragment: null + }, + accessors: { + protocol: 'ftp', + username: '', + password: '', + port: '', + path: '/', + query: '', + fragment: '', + resource: '/', + authority: 'attacker.com', + origin: 'ftp://attacker.com', + userinfo: '', + subdomain: '', + domain: 'attacker.com', + tld: 'com', + directory: '/', + filename: '', + suffix: '', + hash: '', + search: '', + host: 'attacker.com', + hostname: 'attacker.com' + }, + is: { + urn: false, + url: true, + relative: false, + name: true, + sld: false, + ip: false, + ip4: false, + ip6: false, + idn: false, + punycode: false + } }, { name: '__proto__ in query', url: 'http://www.example.org/?__proto__=hasOwnProperty&__proto__=eviltwin&uuid',