Merge branch 'main' of github.com:hackademix/noscript into ctx

This commit is contained in:
hackademix 2022-02-04 23:40:34 +01:00
commit 62aac29750
7 changed files with 50 additions and 21 deletions

View File

@ -315,6 +315,16 @@
include("/test/run.js");
},
async testIC(callbackOrUrl) {
await include("xss/InjectionChecker.js");
let IC = await XSS.InjectionChecker;
let ic = new IC();
ic.logEnabled = true;
return (typeof callbackOrUrl === "function")
? await callbackOrUrl(ic)
: ic.checkUrl(callbackOrUrl);
},
async savePolicy() {
if (this.policy) {
await Storage.set("sync", {

View File

@ -86,14 +86,18 @@
debug("Fetching policy for actual URL %s (was %s)", url, document.URL);
}
debug(`Synchronously fetching policy for ${url}.`);
if (this.syncFetchPolicy) {
// extra hops to ensure that scripts don't run when CSP has not been set through HTTP headers
this.syncFetchPolicy();
} else {
this.setup(
browser.runtime.sendSyncMessage({id: "fetchPolicy", url})
);
let msg = {id: "fetchPolicy", url};
if (document.readyState === "complete") {
// no point fetching synchronously, since the document is already loaded (hot extension update?)
(async () => this.setup(await browser.runtime.sendMessage(msg)))();
} else {
debug(`Synchronously fetching policy for ${url}.`);
this.setup(browser.runtime.sendSyncMessage(msg));
}
}
},

View File

@ -8,7 +8,7 @@
"strict_min_version": "59.0"
}
},
"version": "11.2.16rc3",
"version": "11.2.19",
"description": "__MSG_Description__",
"incognito": "spanning",
@ -51,7 +51,6 @@
"/nscl/common/Permissions.js",
"/nscl/common/Policy.js",
"/nscl/common/locale.js",
"/nscl/common/SyntaxChecker.js",
"/nscl/common/Storage.js",
"/nscl/common/include.js",
"/nscl/service/DocStartInjection.js",

@ -1 +1 @@
Subproject commit f04ec6afe193f59ce540f5de9e0d184bf7d8a231
Subproject commit fa49ecb52140aa80db30a7fa834f6358acc94a13

View File

@ -21,7 +21,7 @@
if (UA.isMozilla) {
let y = async (url, originUrl = '') => await XSS.test({originUrl, url, method: "GET"});
let n = async (...args) => !await y(...args);
Promise.all([
let xssTest = Promise.all([
() => y("https://noscript.net/<script"),
() => n("https://noscript.net/<script", "https://noscript.net/"),
() => y("https://vulnerabledoma.in/char_test?body=%80%3Cscript%3Ealert(1)%3C/script%3E"),
@ -32,25 +32,25 @@ if (UA.isMozilla) {
() => y("https://vulnerabledoma.in/xss_link?url=javascript%26colo%00n%3Balert%u00281%29"),
() => y("https://vulnerabledoma.in/xss_link?url=javascript:\\u{%0A6e}ame"),
].map(t => Test.run(t))
).then(() => Test.report());
);
let invalidCharsTest = async () => {
await include("xss/InjectionChecker.js");
let IC = await XSS.InjectionChecker;
let rx = new IC().invalidCharsRx;
console.log("Testing invalidCharsRx", rx);
let x = n => '\\u' + ("0000" + n.toString(16)).slice(-4);
function check(ch) {
eval(`{let _${ch}_}`);
Function(`let _${ch}_`);
}
let cur = 0x7e;
let fail = false;
while (cur++ < 0xffff) {
while (cur++ < 0xffff && !fail) {
let ch = String.fromCharCode(cur);
try {
check(ch);
if (tx.test(ch)) {
if (rx.test(ch)) {
console.error(x(cur) + " should not test invalid!");
fail = true;
}
@ -64,6 +64,10 @@ if (UA.isMozilla) {
}
return !fail;
};
Test.run(invalidCharsTest, "InjectionChecker.invalidCharsRx").then(Test.report());
(async () => {
await xssTest;
Test.report();
await Test.run(invalidCharsTest, "InjectionChecker.invalidCharsRx");
Test.report();
})();
}

View File

@ -526,7 +526,15 @@ XSS.InjectionChecker = (async () => {
},
get invalidCharsRx() {
let value = new RegExp("^[^\"'`/<>]*[" + this._createInvalidRanges() + "]");
let preamble = "^[^\"'`/<>]*";
let value;
try {
// see https://mathiasbynens.be/notes/javascript-identifiers-es6#acceptable-unicode-symbols
value = new RegExp(preamble + "[^$_\\p{ID_Start}\\p{ID_Continue}\\u200c\\u200d\\u2028\\u2029]", "u");
} catch (e) {
// Unicode entities are not supported in Gecko <= 77
value = new RegExp(preamble + `[${this._createInvalidRanges()}]`, "u");
}
Object.defineProperty(Object.getPrototypeOf(this), 'invalidCharsRx', {value});
return value;
},
@ -886,7 +894,7 @@ XSS.InjectionChecker = (async () => {
l = l.replace(/[^=]*=\s*/i, '').replace(/[\u0000-\u001f]/g, '');
l = /^["']/.test(l) ? l.replace(/^(['"])([^]*?)\1[^]*/g, '$2') : l.replace(/[\s>][^]*/, '');
if (/^(?:javascript|data):|\[[^]+\]/i.test(l) || /[<'"(]/.test(unescape(l)) && await this.checkUrl(l)) return true;
if (/^(?:javascript|data):/i.test(l) || /[<'"([]/.test(unescape(l)) && await this.checkUrl(l)) return true;
}
}
return this._rxCheck("HTML", s) || this._rxCheck("Globals", s);

View File

@ -117,10 +117,14 @@ var XSS = (() => {
if (reasons.protectName) {
await include("/nscl/service/ContentScriptOnce.js");
await ContentScriptOnce.execute(request, {
js: [{file: "/xss/sanitizeName.js"}],
});
if (!block) return ALLOW;
try {
await ContentScriptOnce.execute(request, {
js: [{file: "/xss/sanitizeName.js"}],
});
if (!block) return ALLOW;
} catch (e) {
error(e, "Sanitizing name in request", request.url);
}
}
if (reasons.urlInjection) data.push(`(URL) ${unescapedDest}`);
if (reasons.postInjection) data.push(`(POST) ${reasons.postInjection}`);