[XSS] Precomputed invalid identifier chars regular expression.

This commit is contained in:
hackademix 2021-12-27 20:01:35 +01:00
parent 7abdd20155
commit 2cdbbe2d57
2 changed files with 35 additions and 37 deletions

View File

@ -33,4 +33,37 @@ if (UA.isMozilla) {
() => y("https://vulnerabledoma.in/xss_link?url=javascript:\\u{%0A6e}ame"), () => y("https://vulnerabledoma.in/xss_link?url=javascript:\\u{%0A6e}ame"),
].map(t => Test.run(t)) ].map(t => Test.run(t))
).then(() => Test.report()); ).then(() => Test.report());
let invalidCharsTest = async () => {
await include("xss/InjectionChecker.js");
let IC = await XSS.InjectionChecker;
let rx = new IC().invalidCharsRx;
let x = n => '\\u' + ("0000" + n.toString(16)).slice(-4);
function check(ch) {
eval(`{let _${ch}_}`);
}
let cur = 0x7e;
let fail = false;
while (cur++ < 0xffff) {
let ch = String.fromCharCode(cur);
try {
check(ch);
if (tx.test(ch)) {
console.error(x(cur) + " should not test invalid!");
fail = true;
}
} catch (e) {
if (!/illegal char/.test(e.message)) continue;
if (!rx.test(ch)) {
console.error(x(cur) + " must test invalid!");
fail = true;
}
}
}
return !fail;
};
Test.run(invalidCharsTest, "InjectionChecker.invalidCharsRx").then(Test.report());
} }

View File

@ -492,43 +492,8 @@ XSS.InjectionChecker = (async () => {
return ret; return ret;
}, },
_createInvalidRanges: function() { // see https://mathiasbynens.be/notes/javascript-identifiers-es6#acceptable-unicode-symbols
function x(n) { invalidCharsRx: /^[^"'`/<>]*[^$_\p{ID_Start}\p{ID_Continue}\u200c\u200d]/u,
return '\\u' + ("0000" + n.toString(16)).slice(-4);
}
let chunks = [];
let first = -1;
let last = -1;
let cur = 0x7e;
while (cur++ <= 0xffff) {
try {
Function("let _" + String.fromCharCode(cur));
} catch (e) {
if (!/illegal char/.test(e.message)) continue;
if (first == -1) {
first = last = cur;
chunks.push(x(cur));
continue;
}
if (cur - last == 1) {
last = cur;
continue;
}
if (last != first) chunks.push(`-${x(last)}`);
chunks.push(x(cur));
last = first = cur;
}
}
return chunks.join('');
},
get invalidCharsRx() {
let value = new RegExp("^[^\"'`/<>]*[" + this._createInvalidRanges() + "]");
Object.defineProperty(Object.getPrototypeOf(this), 'invalidCharsRx', {value});
return value;
},
async checkJSBreak(s) { async checkJSBreak(s) {
// Direct script injection breaking JS string literals or comments // Direct script injection breaking JS string literals or comments