add sanitizers from DOM and jQuery queries

This commit is contained in:
Erik Krogh Kristensen
2021-04-26 22:39:59 +02:00
parent 8ba5bddae8
commit 3815797dda
4 changed files with 30 additions and 3 deletions

View File

@@ -23,7 +23,13 @@ module UnsafeHtmlConstruction {
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) { super.isSanitizer(node) }
override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node)
or
node instanceof DomBasedXss::Sanitizer
or
node instanceof UnsafeJQueryPlugin::Sanitizer
}
override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) {
DomBasedXss::isOptionallySanitizedEdge(pred, succ)

View File

@@ -13,7 +13,6 @@ module UnsafeHtmlConstruction {
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations::DomBasedXss as DomBasedXss
private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQueryPlugin
private import semmle.javascript.PackageExports as Exports
private import semmle.javascript.security.dataflow.UnsafeJQueryPlugin::UnsafeJQueryPlugin as UnsafeJQueryPlugin
/**
* A source for unsafe HTML constructed from library input.

View File

@@ -33,6 +33,10 @@ nodes
| main.js:62:19:62:26 | settings |
| main.js:62:19:62:31 | settings.name |
| main.js:62:19:62:31 | settings.name |
| main.js:66:35:66:41 | attrVal |
| main.js:66:35:66:41 | attrVal |
| main.js:67:63:67:69 | attrVal |
| main.js:67:63:67:69 | attrVal |
| typed.ts:1:39:1:39 | s |
| typed.ts:1:39:1:39 | s |
| typed.ts:2:29:2:29 | s |
@@ -82,6 +86,10 @@ edges
| main.js:60:41:60:47 | options | main.js:60:22:60:48 | $.exten ... ptions) |
| main.js:62:19:62:26 | settings | main.js:62:19:62:31 | settings.name |
| main.js:62:19:62:26 | settings | main.js:62:19:62:31 | settings.name |
| main.js:66:35:66:41 | attrVal | main.js:67:63:67:69 | attrVal |
| main.js:66:35:66:41 | attrVal | main.js:67:63:67:69 | attrVal |
| main.js:66:35:66:41 | attrVal | main.js:67:63:67:69 | attrVal |
| main.js:66:35:66:41 | attrVal | main.js:67:63:67:69 | attrVal |
| typed.ts:1:39:1:39 | s | typed.ts:2:29:2:29 | s |
| typed.ts:1:39:1:39 | s | typed.ts:2:29:2:29 | s |
| typed.ts:1:39:1:39 | s | typed.ts:2:29:2:29 | s |
@@ -104,5 +112,6 @@ edges
| main.js:22:34:22:34 | s | main.js:21:47:21:47 | s | main.js:22:34:22:34 | s | $@ based on $@ might later cause $@. | main.js:22:34:22:34 | s | Markdown rendering | main.js:21:47:21:47 | s | library input | main.js:23:53:23:56 | html | cross-site scripting |
| main.js:47:65:47:73 | this.step | main.js:52:41:52:41 | s | main.js:47:65:47:73 | this.step | $@ based on $@ might later cause $@. | main.js:47:65:47:73 | this.step | HTML construction | main.js:52:41:52:41 | s | library input | main.js:47:54:47:85 | "<span> ... /span>" | cross-site scripting |
| main.js:62:19:62:31 | settings.name | main.js:56:28:56:34 | options | main.js:62:19:62:31 | settings.name | $@ based on $@ might later cause $@. | main.js:62:19:62:31 | settings.name | HTML construction | main.js:56:28:56:34 | options | library input | main.js:62:11:62:40 | "<b>" + ... "</b>" | cross-site scripting |
| main.js:67:63:67:69 | attrVal | main.js:66:35:66:41 | attrVal | main.js:67:63:67:69 | attrVal | $@ based on $@ might later cause $@. | main.js:67:63:67:69 | attrVal | HTML construction | main.js:66:35:66:41 | attrVal | library input | main.js:67:47:67:78 | "<img a ... "\\"/>" | cross-site scripting |
| typed.ts:2:29:2:29 | s | typed.ts:1:39:1:39 | s | typed.ts:2:29:2:29 | s | $@ based on $@ might later cause $@. | typed.ts:2:29:2:29 | s | HTML construction | typed.ts:1:39:1:39 | s | library input | typed.ts:3:31:3:34 | html | cross-site scripting |
| typed.ts:8:40:8:40 | s | typed.ts:6:43:6:43 | s | typed.ts:8:40:8:40 | s | $@ based on $@ might later cause $@. | typed.ts:8:40:8:40 | s | HTML construction | typed.ts:6:43:6:43 | s | library input | typed.ts:8:29:8:52 | "<span> ... /span>" | cross-site scripting |

View File

@@ -61,4 +61,17 @@ $.fn.xssPlugin = function (options) {
return this.each(function () {
$("<b>" + settings.name + "</b>").appendTo(this); // NOT OK
});
}
}
module.exports.guards = function (attrVal) {
document.querySelector("#id").innerHTML = "<img alt=\"" + attrVal + "\"/>"; // NOT OK
document.querySelector("#id").innerHTML = "<img alt=\"" + attrVal.replace(/"|'/g, "") + "\"/>"; // OK
if (attrVal.indexOf("\"") === -1 && attrVal.indexOf("'") === -1) {
document.querySelector("#id").innerHTML = "<img alt=\"" + attrVal + "\"/>"; // OK
}
}
module.exports.intentionalTemplate = function (obj) {
const html = "<span>" + obj.spanTemplate + "</span>"; // OK
document.querySelector("#template").innerHTML = html;
}