[XSS] Take in account the whole redirection chain (thanks NDevTK for reporting).
This commit is contained in:
parent
5f768bd416
commit
10e2c40c1c
|
@ -42,8 +42,9 @@ XSS.Exceptions = (() => {
|
||||||
function logEx(...args) {
|
function logEx(...args) {
|
||||||
debug("[XSS preprocessing] Ignoring %o", xssReq, ...args);
|
debug("[XSS preprocessing] Ignoring %o", xssReq, ...args);
|
||||||
}
|
}
|
||||||
|
log(`Processing exceptions for `, xssReq);
|
||||||
let {
|
let {
|
||||||
|
isCrossSite,
|
||||||
srcObj,
|
srcObj,
|
||||||
destObj,
|
destObj,
|
||||||
srcUrl,
|
srcUrl,
|
||||||
|
@ -55,8 +56,9 @@ XSS.Exceptions = (() => {
|
||||||
isPost
|
isPost
|
||||||
} = xssReq;
|
} = xssReq;
|
||||||
|
|
||||||
// same srcUrl
|
// let same-site requests alone
|
||||||
if (srcOrigin === destOrigin) {
|
if (!isCrossSite ||
|
||||||
|
/^https:/.test(srcOrigin) && xssReq.srcDomain === xssReq.destDomain) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@ var XSS = (() => {
|
||||||
|
|
||||||
let baseTTL = 20000; // timeout in milliseconds for each worker to perform
|
let baseTTL = 20000; // timeout in milliseconds for each worker to perform
|
||||||
|
|
||||||
|
const redirMap = new Map();
|
||||||
|
|
||||||
let workersMap = new Map();
|
let workersMap = new Map();
|
||||||
let promptsMap = new Map();
|
let promptsMap = new Map();
|
||||||
let blockedTabs = new Map();
|
let blockedTabs = new Map();
|
||||||
|
@ -67,6 +69,7 @@ var XSS = (() => {
|
||||||
|
|
||||||
function doneListener(request) {
|
function doneListener(request) {
|
||||||
let {requestId} = request;
|
let {requestId} = request;
|
||||||
|
redirMap.delete(requestId);
|
||||||
let worker = workersMap.get(requestId);
|
let worker = workersMap.get(requestId);
|
||||||
if (worker) {
|
if (worker) {
|
||||||
worker.terminate();
|
worker.terminate();
|
||||||
|
@ -233,10 +236,19 @@ var XSS = (() => {
|
||||||
|
|
||||||
parseRequest(request) {
|
parseRequest(request) {
|
||||||
let {
|
let {
|
||||||
|
requestId,
|
||||||
url: destUrl,
|
url: destUrl,
|
||||||
originUrl: srcUrl,
|
originUrl: srcUrl,
|
||||||
method
|
method
|
||||||
} = request;
|
} = request;
|
||||||
|
|
||||||
|
let redirects;
|
||||||
|
if (redirMap.has(requestId)) {
|
||||||
|
redirects = redirMap.get(requestId);
|
||||||
|
} else {
|
||||||
|
redirMap.set(requestId, redirects = []);
|
||||||
|
}
|
||||||
|
|
||||||
let destObj;
|
let destObj;
|
||||||
try {
|
try {
|
||||||
destObj = parseUrl(destUrl);
|
destObj = parseUrl(destUrl);
|
||||||
|
@ -253,16 +265,31 @@ var XSS = (() => {
|
||||||
srcUrl = "";
|
srcUrl = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
let unescapedDest = unescape(destUrl);
|
|
||||||
let srcOrigin = srcObj ? srcObj.origin : "";
|
let srcOrigin = srcObj ? srcObj.origin : "";
|
||||||
if (srcOrigin === "null") {
|
if (srcOrigin === "null") {
|
||||||
srcOrigin = srcObj.href.replace(/[\?#].*/, '');
|
srcOrigin = srcObj.href.replace(/[\?#].*/, '');
|
||||||
}
|
}
|
||||||
let destOrigin = destObj.origin;
|
let destOrigin = destObj.origin;
|
||||||
|
|
||||||
let isGet = method === "GET";
|
let isCrossSite = srcOrigin !== destOrigin;
|
||||||
return {
|
|
||||||
|
if (!isCrossSite) {
|
||||||
|
// check the whole redirection chain, if any
|
||||||
|
for (let r of redirects) {
|
||||||
|
if (r.destOrigin !== destOrigin) {
|
||||||
|
({destUrl: srcUrl, destObj: srcObj, destOrigin: srcOrigin} = r);
|
||||||
|
isCrossSite = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isGet = method === "GET";
|
||||||
|
|
||||||
|
const xssReq = {
|
||||||
request,
|
request,
|
||||||
|
redirects,
|
||||||
|
isCrossSite,
|
||||||
srcUrl,
|
srcUrl,
|
||||||
destUrl,
|
destUrl,
|
||||||
srcObj,
|
srcObj,
|
||||||
|
@ -272,12 +299,14 @@ var XSS = (() => {
|
||||||
srcDomain: srcObj && srcObj.hostname && tld.getDomain(srcObj.hostname) || "",
|
srcDomain: srcObj && srcObj.hostname && tld.getDomain(srcObj.hostname) || "",
|
||||||
destDomain: tld.getDomain(destObj.hostname),
|
destDomain: tld.getDomain(destObj.hostname),
|
||||||
originKey: `${srcOrigin}>${destOrigin}`,
|
originKey: `${srcOrigin}>${destOrigin}`,
|
||||||
unescapedDest,
|
unescapedDest: unescape(destUrl),
|
||||||
isGet,
|
isGet,
|
||||||
isPost: !isGet && method === "POST",
|
isPost: !isGet && method === "POST",
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
debugging: ns.local.debug,
|
debugging: ns.local.debug,
|
||||||
}
|
}
|
||||||
|
redirects.unshift(xssReq);
|
||||||
|
return xssReq;
|
||||||
},
|
},
|
||||||
|
|
||||||
async saveUserChoices(xssUserChoices = this._userChoices || {}) {
|
async saveUserChoices(xssUserChoices = this._userChoices || {}) {
|
||||||
|
|
Loading…
Reference in New Issue