Merge pull request #6193 from esbena/esbena/mootools-xss

JS: add Mootools XSS sinks
This commit is contained in:
Esben Sparre Andreasen
2021-07-02 09:24:56 +02:00
committed by GitHub
7 changed files with 123 additions and 1 deletions

View File

@@ -103,6 +103,7 @@ import semmle.javascript.frameworks.Logging
import semmle.javascript.frameworks.HttpFrameworks
import semmle.javascript.frameworks.HttpProxy
import semmle.javascript.frameworks.Markdown
import semmle.javascript.frameworks.MooTools
import semmle.javascript.frameworks.Nest
import semmle.javascript.frameworks.Next
import semmle.javascript.frameworks.NoSQL

View File

@@ -0,0 +1,38 @@
/**
* Provides classes for working with MooTools code.
*/
import javascript
module MooTools {
private class Element extends DataFlow::NewNode {
Element() {
this = DataFlow::globalVarRef("Element").getAnInstantiation() and
// sharpen slightly to avoid spurious matches for the global variable
this.getNumArgument() = [1, 2]
}
DataFlow::Node getAnElementPropertyValue(string name) {
result = this.getOptionArgument(1, name)
or
exists(DataFlow::MethodCallNode mcn |
mcn = this.getAMethodCall(["set", "setProperty"]) and
mcn.getArgument(0).mayHaveStringValue(name) and
result = mcn.getArgument(1)
or
mcn = this.getAMethodCall(["set", "setProperties"]) and
result = mcn.getOptionArgument(0, name)
)
}
}
/**
* Holds if MooTools interprets `node` as HTML.
*/
predicate interpretsNodeAsHtml(DataFlow::Node node) {
exists(Element e |
node = e.getAnElementPropertyValue("html") or
node = e.getAMethodCall(["appendHtml"]).getArgument(0)
)
}
}

View File

@@ -192,6 +192,8 @@ module DomBasedXss {
this = instance.getArgument(0) and
instance.getOptionArgument(1, "runScripts").mayHaveStringValue("dangerously")
)
or
MooTools::interpretsNodeAsHtml(this)
}
}

View File

@@ -669,6 +669,21 @@ nodes
| tst.js:430:18:430:23 | target |
| tst.js:430:18:430:89 | target. ... data>') |
| tst.js:430:18:430:89 | target. ... data>') |
| tst.js:436:6:436:38 | source |
| tst.js:436:15:436:38 | documen ... .search |
| tst.js:436:15:436:38 | documen ... .search |
| tst.js:440:28:440:33 | source |
| tst.js:440:28:440:33 | source |
| tst.js:441:33:441:38 | source |
| tst.js:441:33:441:38 | source |
| tst.js:442:34:442:39 | source |
| tst.js:442:34:442:39 | source |
| tst.js:443:41:443:46 | source |
| tst.js:443:41:443:46 | source |
| tst.js:444:44:444:49 | source |
| tst.js:444:44:444:49 | source |
| tst.js:445:32:445:37 | source |
| tst.js:445:32:445:37 | source |
| typeahead.js:20:13:20:45 | target |
| typeahead.js:20:22:20:45 | documen ... .search |
| typeahead.js:20:22:20:45 | documen ... .search |
@@ -1312,6 +1327,20 @@ edges
| tst.js:428:16:428:39 | documen ... .search | tst.js:428:7:428:39 | target |
| tst.js:430:18:430:23 | target | tst.js:430:18:430:89 | target. ... data>') |
| tst.js:430:18:430:23 | target | tst.js:430:18:430:89 | target. ... data>') |
| tst.js:436:6:436:38 | source | tst.js:440:28:440:33 | source |
| tst.js:436:6:436:38 | source | tst.js:440:28:440:33 | source |
| tst.js:436:6:436:38 | source | tst.js:441:33:441:38 | source |
| tst.js:436:6:436:38 | source | tst.js:441:33:441:38 | source |
| tst.js:436:6:436:38 | source | tst.js:442:34:442:39 | source |
| tst.js:436:6:436:38 | source | tst.js:442:34:442:39 | source |
| tst.js:436:6:436:38 | source | tst.js:443:41:443:46 | source |
| tst.js:436:6:436:38 | source | tst.js:443:41:443:46 | source |
| tst.js:436:6:436:38 | source | tst.js:444:44:444:49 | source |
| tst.js:436:6:436:38 | source | tst.js:444:44:444:49 | source |
| tst.js:436:6:436:38 | source | tst.js:445:32:445:37 | source |
| tst.js:436:6:436:38 | source | tst.js:445:32:445:37 | source |
| tst.js:436:15:436:38 | documen ... .search | tst.js:436:6:436:38 | source |
| tst.js:436:15:436:38 | documen ... .search | tst.js:436:6:436:38 | source |
| typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target |
| typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:20:13:20:45 | target |
| typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:20:13:20:45 | target |
@@ -1531,6 +1560,12 @@ edges
| tst.js:421:20:421:27 | match[1] | tst.js:419:15:419:34 | window.location.hash | tst.js:421:20:421:27 | match[1] | Cross-site scripting vulnerability due to $@. | tst.js:419:15:419:34 | window.location.hash | user-provided value |
| tst.js:424:18:424:51 | window. ... '#')[1] | tst.js:424:18:424:37 | window.location.hash | tst.js:424:18:424:51 | window. ... '#')[1] | Cross-site scripting vulnerability due to $@. | tst.js:424:18:424:37 | window.location.hash | user-provided value |
| tst.js:430:18:430:89 | target. ... data>') | tst.js:428:16:428:39 | documen ... .search | tst.js:430:18:430:89 | target. ... data>') | Cross-site scripting vulnerability due to $@. | tst.js:428:16:428:39 | documen ... .search | user-provided value |
| tst.js:440:28:440:33 | source | tst.js:436:15:436:38 | documen ... .search | tst.js:440:28:440:33 | source | Cross-site scripting vulnerability due to $@. | tst.js:436:15:436:38 | documen ... .search | user-provided value |
| tst.js:441:33:441:38 | source | tst.js:436:15:436:38 | documen ... .search | tst.js:441:33:441:38 | source | Cross-site scripting vulnerability due to $@. | tst.js:436:15:436:38 | documen ... .search | user-provided value |
| tst.js:442:34:442:39 | source | tst.js:436:15:436:38 | documen ... .search | tst.js:442:34:442:39 | source | Cross-site scripting vulnerability due to $@. | tst.js:436:15:436:38 | documen ... .search | user-provided value |
| tst.js:443:41:443:46 | source | tst.js:436:15:436:38 | documen ... .search | tst.js:443:41:443:46 | source | Cross-site scripting vulnerability due to $@. | tst.js:436:15:436:38 | documen ... .search | user-provided value |
| tst.js:444:44:444:49 | source | tst.js:436:15:436:38 | documen ... .search | tst.js:444:44:444:49 | source | Cross-site scripting vulnerability due to $@. | tst.js:436:15:436:38 | documen ... .search | user-provided value |
| tst.js:445:32:445:37 | source | tst.js:436:15:436:38 | documen ... .search | tst.js:445:32:445:37 | source | Cross-site scripting vulnerability due to $@. | tst.js:436:15:436:38 | documen ... .search | user-provided value |
| typeahead.js:25:18:25:20 | val | typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:25:18:25:20 | val | Cross-site scripting vulnerability due to $@. | typeahead.js:20:22:20:45 | documen ... .search | user-provided value |
| v-html.vue:2:8:2:23 | v-html=tainted | v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted | Cross-site scripting vulnerability due to $@. | v-html.vue:6:42:6:58 | document.location | user-provided value |
| various-concat-obfuscations.js:4:4:4:31 | "<div>" ... </div>" | various-concat-obfuscations.js:2:16:2:39 | documen ... .search | various-concat-obfuscations.js:4:4:4:31 | "<div>" ... </div>" | Cross-site scripting vulnerability due to $@. | various-concat-obfuscations.js:2:16:2:39 | documen ... .search | user-provided value |

View File

@@ -676,6 +676,21 @@ nodes
| tst.js:430:18:430:23 | target |
| tst.js:430:18:430:89 | target. ... data>') |
| tst.js:430:18:430:89 | target. ... data>') |
| tst.js:436:6:436:38 | source |
| tst.js:436:15:436:38 | documen ... .search |
| tst.js:436:15:436:38 | documen ... .search |
| tst.js:440:28:440:33 | source |
| tst.js:440:28:440:33 | source |
| tst.js:441:33:441:38 | source |
| tst.js:441:33:441:38 | source |
| tst.js:442:34:442:39 | source |
| tst.js:442:34:442:39 | source |
| tst.js:443:41:443:46 | source |
| tst.js:443:41:443:46 | source |
| tst.js:444:44:444:49 | source |
| tst.js:444:44:444:49 | source |
| tst.js:445:32:445:37 | source |
| tst.js:445:32:445:37 | source |
| typeahead.js:9:28:9:30 | loc |
| typeahead.js:9:28:9:30 | loc |
| typeahead.js:10:16:10:18 | loc |
@@ -1336,6 +1351,20 @@ edges
| tst.js:428:16:428:39 | documen ... .search | tst.js:428:7:428:39 | target |
| tst.js:430:18:430:23 | target | tst.js:430:18:430:89 | target. ... data>') |
| tst.js:430:18:430:23 | target | tst.js:430:18:430:89 | target. ... data>') |
| tst.js:436:6:436:38 | source | tst.js:440:28:440:33 | source |
| tst.js:436:6:436:38 | source | tst.js:440:28:440:33 | source |
| tst.js:436:6:436:38 | source | tst.js:441:33:441:38 | source |
| tst.js:436:6:436:38 | source | tst.js:441:33:441:38 | source |
| tst.js:436:6:436:38 | source | tst.js:442:34:442:39 | source |
| tst.js:436:6:436:38 | source | tst.js:442:34:442:39 | source |
| tst.js:436:6:436:38 | source | tst.js:443:41:443:46 | source |
| tst.js:436:6:436:38 | source | tst.js:443:41:443:46 | source |
| tst.js:436:6:436:38 | source | tst.js:444:44:444:49 | source |
| tst.js:436:6:436:38 | source | tst.js:444:44:444:49 | source |
| tst.js:436:6:436:38 | source | tst.js:445:32:445:37 | source |
| tst.js:436:6:436:38 | source | tst.js:445:32:445:37 | source |
| tst.js:436:15:436:38 | documen ... .search | tst.js:436:6:436:38 | source |
| tst.js:436:15:436:38 | documen ... .search | tst.js:436:6:436:38 | source |
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |

View File

@@ -430,4 +430,17 @@ function nonGlobalSanitizer() {
$("#foo").html(target.replace(/<metadata>[\s\S]*<\/metadata>/, '<metadata></metadata>')); // NOT OK
$("#foo").html(target.replace(/<|>/g, '')); // OK
}
}
function mootools(){
var source = document.location.search;
new Element("div"); // OK
new Element("div", {text: source}); // OK
new Element("div", {html: source}); // NOT OK
new Element("div").set("html", source); // NOT OK
new Element("div").set({"html": source}); // NOT OK
new Element("div").setProperty("html", source); // NOT OK
new Element("div").setProperties({"html": source}); // NOT OK
new Element("div").appendHtml(source); // NOT OK
}