mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #3313 from esbena/js/typical-bad-sanitizer
New query: Incomplete HTML attribute sanitization
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
| tst.js:206:2:206:24 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:206:2:206:24 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:207:2:207:26 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:208:2:208:26 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:209:2:209:40 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:209:2:209:40 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:210:2:210:58 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:211:2:211:58 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:212:2:212:58 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:215:6:215:24 | s.replace(/>/g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:215:6:215:24 | s.replace(/>/g, '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:217:2:217:93 | s().rep ... '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:243:9:243:31 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:243:9:243:31 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:244:9:244:33 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:245:9:245:33 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:249:9:249:33 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:251:9:251:33 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:253:21:253:45 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:254:32:254:56 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:255:26:255:50 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:256:15:256:39 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:261:10:261:81 | value.r ... '>') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:270:61:270:85 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:272:28:272:50 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:272:28:272:50 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:274:12:274:94 | s().val ... g , '') | This HTML sanitizer does not sanitize ampersands |
|
||||
| tst.js:274:12:274:94 | s().val ... g , '') | This HTML sanitizer does not sanitize quotes |
|
||||
| tst.js:277:9:277:29 | arr2.re ... "/g,"") | This HTML sanitizer does not sanitize ampersands |
|
||||
@@ -0,0 +1,7 @@
|
||||
import javascript
|
||||
import semmle.javascript.security.IncompleteBlacklistSanitizer
|
||||
|
||||
from IncompleteBlacklistSanitizer sanitizer
|
||||
select sanitizer,
|
||||
"This " + sanitizer.getKind() + " sanitizer does not sanitize " +
|
||||
describeCharacters(sanitizer.getAnUnsanitizedCharacter())
|
||||
@@ -0,0 +1,45 @@
|
||||
nodes
|
||||
| tst.js:243:9:243:31 | s().rep ... ]/g,'') |
|
||||
| tst.js:243:9:243:31 | s().rep ... ]/g,'') |
|
||||
| tst.js:243:9:243:31 | s().rep ... ]/g,'') |
|
||||
| tst.js:244:9:244:33 | s().rep ... /g, '') |
|
||||
| tst.js:244:9:244:33 | s().rep ... /g, '') |
|
||||
| tst.js:244:9:244:33 | s().rep ... /g, '') |
|
||||
| tst.js:249:9:249:33 | s().rep ... ]/g,'') |
|
||||
| tst.js:249:9:249:33 | s().rep ... ]/g,'') |
|
||||
| tst.js:249:9:249:33 | s().rep ... ]/g,'') |
|
||||
| tst.js:253:21:253:45 | s().rep ... /g, '') |
|
||||
| tst.js:253:21:253:45 | s().rep ... /g, '') |
|
||||
| tst.js:253:21:253:45 | s().rep ... /g, '') |
|
||||
| tst.js:254:32:254:56 | s().rep ... /g, '') |
|
||||
| tst.js:254:32:254:56 | s().rep ... /g, '') |
|
||||
| tst.js:254:32:254:56 | s().rep ... /g, '') |
|
||||
| tst.js:270:61:270:85 | s().rep ... /g, '') |
|
||||
| tst.js:270:61:270:85 | s().rep ... /g, '') |
|
||||
| tst.js:270:61:270:85 | s().rep ... /g, '') |
|
||||
| tst.js:274:6:274:94 | arr |
|
||||
| tst.js:274:12:274:94 | s().val ... g , '') |
|
||||
| tst.js:274:12:274:94 | s().val ... g , '') |
|
||||
| tst.js:275:9:275:11 | arr |
|
||||
| tst.js:275:9:275:21 | arr.join(" ") |
|
||||
| tst.js:275:9:275:21 | arr.join(" ") |
|
||||
edges
|
||||
| tst.js:243:9:243:31 | s().rep ... ]/g,'') | tst.js:243:9:243:31 | s().rep ... ]/g,'') |
|
||||
| tst.js:244:9:244:33 | s().rep ... /g, '') | tst.js:244:9:244:33 | s().rep ... /g, '') |
|
||||
| tst.js:249:9:249:33 | s().rep ... ]/g,'') | tst.js:249:9:249:33 | s().rep ... ]/g,'') |
|
||||
| tst.js:253:21:253:45 | s().rep ... /g, '') | tst.js:253:21:253:45 | s().rep ... /g, '') |
|
||||
| tst.js:254:32:254:56 | s().rep ... /g, '') | tst.js:254:32:254:56 | s().rep ... /g, '') |
|
||||
| tst.js:270:61:270:85 | s().rep ... /g, '') | tst.js:270:61:270:85 | s().rep ... /g, '') |
|
||||
| tst.js:274:6:274:94 | arr | tst.js:275:9:275:11 | arr |
|
||||
| tst.js:274:12:274:94 | s().val ... g , '') | tst.js:274:6:274:94 | arr |
|
||||
| tst.js:274:12:274:94 | s().val ... g , '') | tst.js:274:6:274:94 | arr |
|
||||
| tst.js:275:9:275:11 | arr | tst.js:275:9:275:21 | arr.join(" ") |
|
||||
| tst.js:275:9:275:11 | arr | tst.js:275:9:275:21 | arr.join(" ") |
|
||||
#select
|
||||
| tst.js:243:9:243:31 | s().rep ... ]/g,'') | tst.js:243:9:243:31 | s().rep ... ]/g,'') | tst.js:243:9:243:31 | s().rep ... ]/g,'') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:243:9:243:31 | s().rep ... ]/g,'') | this final HTML sanitizer step |
|
||||
| tst.js:244:9:244:33 | s().rep ... /g, '') | tst.js:244:9:244:33 | s().rep ... /g, '') | tst.js:244:9:244:33 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:244:9:244:33 | s().rep ... /g, '') | this final HTML sanitizer step |
|
||||
| tst.js:249:9:249:33 | s().rep ... ]/g,'') | tst.js:249:9:249:33 | s().rep ... ]/g,'') | tst.js:249:9:249:33 | s().rep ... ]/g,'') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:249:9:249:33 | s().rep ... ]/g,'') | this final HTML sanitizer step |
|
||||
| tst.js:253:21:253:45 | s().rep ... /g, '') | tst.js:253:21:253:45 | s().rep ... /g, '') | tst.js:253:21:253:45 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain ampersands or quotes when it reaches this attribute definition. | tst.js:253:21:253:45 | s().rep ... /g, '') | this final HTML sanitizer step |
|
||||
| tst.js:254:32:254:56 | s().rep ... /g, '') | tst.js:254:32:254:56 | s().rep ... /g, '') | tst.js:254:32:254:56 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain ampersands or quotes when it reaches this attribute definition. | tst.js:254:32:254:56 | s().rep ... /g, '') | this final HTML sanitizer step |
|
||||
| tst.js:270:61:270:85 | s().rep ... /g, '') | tst.js:270:61:270:85 | s().rep ... /g, '') | tst.js:270:61:270:85 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain ampersands or quotes when it reaches this attribute definition. | tst.js:270:61:270:85 | s().rep ... /g, '') | this final HTML sanitizer step |
|
||||
| tst.js:275:9:275:21 | arr.join(" ") | tst.js:274:12:274:94 | s().val ... g , '') | tst.js:275:9:275:21 | arr.join(" ") | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:274:12:274:94 | s().val ... g , '') | this final HTML sanitizer step |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE-116/IncompleteHtmlAttributeSanitization.ql
|
||||
@@ -201,3 +201,97 @@ app.get('/some/path', function(req, res) {
|
||||
function bad18(p) {
|
||||
return p.replace("/../", ""); // NOT OK
|
||||
}
|
||||
|
||||
function typicalBadHtmlSanitizers(s) {
|
||||
s().replace(/[<>]/g,''); // NOT OK
|
||||
s().replace(/[<>&]/g, ''); // NOT OK
|
||||
s().replace(/[<>"]/g, ''); // NOT OK
|
||||
s().replace(/</g, '').replace(/>/g, ''); // NOT OK
|
||||
s().replace(/</g, '').replace(/>/g, '').replace(/&/g, ''); // NOT OK
|
||||
s().replace(/</g, '').replace(/&/g, '').replace(/>/g, ''); // NOT OK
|
||||
s().replace(/&/g, '').replace(/>/g, '').replace(/</g, ''); // NOT OK
|
||||
|
||||
var s = s().replace(/</g, '');
|
||||
s = s.replace(/>/g, ''); // NOT OK
|
||||
s().replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&').replace(/"/g, '"'); // OK
|
||||
s().replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&').replace(/'/g, '''); // NOT OK
|
||||
|
||||
s().replace(/</g, '<').replace(/>/g, '>').replace(RE, function(match) {/* ... */ }); // OK (probably)
|
||||
|
||||
s().replace(/[<>'"&]/g,''); // OK
|
||||
|
||||
s().replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/&(?![\w\#]+;)/g, '&'); // OK
|
||||
|
||||
s().replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, '''); // OK (and not recognized due to the ternary)
|
||||
|
||||
s().replace(/[\\/:\*\?"<>\|]/g, ''); // OK
|
||||
|
||||
s().replace(/[<>]/g,'_'); // OK (but probably unsafe)
|
||||
|
||||
s().replace(/&/g, ">"); // OK
|
||||
|
||||
s().replace(/[\#\%4\/\-\~\>8\_\@0\!\&3\[651d\=e7fA2D\(aFBb]/g, ""); // OK
|
||||
|
||||
s().replace(/[<>]/g,'').replace(/[^a-z]/g, ''); // OK
|
||||
|
||||
s().replace(/[<>]/g,'').replace(/[^abc]/g, ''); // OK
|
||||
|
||||
s().replace(/[<>]/g,'').replace(/[ -~]/g, ''); // OK
|
||||
}
|
||||
|
||||
function incompleteHtmlAttributeSanitization() {
|
||||
'="' + s().replace(/[<>]/g,'') + '"'; // NOT OK
|
||||
'="' + s().replace(/[<>&]/g, '') + '"'; // NOT OK
|
||||
'="' + s().replace(/[<>"]/g, '') + '"'; // OK (maybe, since the attribute name is unknown)
|
||||
'="' + s().replace(/[<>&"]/g,'') + '"'; // OK
|
||||
'="' + s().replace(/[&"]/g,'') + '"'; // OK
|
||||
|
||||
'="' + s().replace(/[<>&']/g,'') + '"'; // NOT OK
|
||||
"='" + s().replace(/[<>&"]/g,'') + "'"; // OK (but given the context, it is probably not fine)
|
||||
"='" + s().replace(/[<>&']/g,'') + "'"; // NOT OK (but given the context, it is probably fine)
|
||||
|
||||
'onFunkyEvent="' + s().replace(/[<>"]/g, '') + '"'; // NOT OK
|
||||
'<div noise onFunkyEvent="' + s().replace(/[<>"]/g, '') + '"'; // NOT OK
|
||||
'<div noise monday="' + s().replace(/[<>"]/g, '') + '"'; // OK
|
||||
'monday="' + s().replace(/[<>"]/g, '') + '"'; // OK
|
||||
}
|
||||
|
||||
function multiStepSanitization() {
|
||||
function escapeHTML(value) {
|
||||
return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
}
|
||||
function attr_str(a) {
|
||||
return ' ' + a.name + '="' + escapeHTML(a.value).replace(/"/g, '"') + '"'; // OK
|
||||
}
|
||||
result += '<' + tag(node) + [].map.call(x, attr_str).join('') + '>';
|
||||
}
|
||||
|
||||
function moreIncompleteHtmlAttributeSanitization() {
|
||||
'<a' + noise + 'onclick="javascript:document.foo.bar(\'' + s().replace(/[<>"]/g, '') + '\'); return false;">'; // NOT OK
|
||||
'="' + s().replace(/[<>]/g,'').replace(/[^\w ]+/g, '') + '"'; // OK
|
||||
'="' + encodeURIComponent(s().replace(/[<>]/g,'')) + '"'; // OK
|
||||
|
||||
var arr = s().val().trim().replace(/^,|,$/g , '').replace(/^;|;$/g , '').replace(/<|>/g , '');
|
||||
'="' + arr.join(" ") + '"'; // NOT OK
|
||||
var arr2 = s().val().trim().replace(/^,|,$/g , '').replace(/^;|;$/g , '').replace(/<|>/g , '')
|
||||
arr2 = arr2.replace(/"/g,"");
|
||||
'="' + arr2.join(" ") + '"'; // OK
|
||||
|
||||
var x;
|
||||
x = x.replace(/&/g, '&');
|
||||
x = x.replace(/</g, '<').replace(/>/g, '>');
|
||||
'onclick="' + x + '"'; // NOT OK - but not flagged since the `x` replace chain is extended below
|
||||
x = x.replace(/"/g, '"');
|
||||
'onclick="' + x + '"'; // OK
|
||||
|
||||
var y;
|
||||
if (escapeAmpersand) {
|
||||
y = y.replace(/&/g, '&');
|
||||
}
|
||||
y = y.replace(/</g, '<').replace(/>/g, '>');
|
||||
'onclick="' + y + '"'; // NOT OK - but not flagged since the `x` replace chain is extended below
|
||||
if (escapeQuotes) {
|
||||
y = y.replace(/"/g, '"');
|
||||
}
|
||||
'onclick="' + y + '"'; // OK
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user