JS: add XSS vector for Vue's v-html

This commit is contained in:
Esben Sparre Andreasen
2019-01-29 16:12:23 +01:00
parent 4c5e48fbbc
commit 4ce7ec1661
6 changed files with 58 additions and 0 deletions

View File

@@ -198,6 +198,39 @@ module DomBasedXss {
}
}
/**
* A Vue `v-html` attribute, viewed as an XSS sink.
*/
class VHtmlSink extends DomBasedXss::Sink {
HTML::Attribute attr;
VHtmlSink() { this = DataFlow::THtmlAttributeNode(attr) and attr.getName() = "v-html" }
HTML::Attribute getAttr() {
result = attr
}
}
/**
* A taint propagating data flow edge through a string interpolation of a
* Vue instance property to a `v-html` attribute.
*/
class VHtmlSourceWrite extends TaintTracking::AdditionalTaintStep {
VHtmlSink attr;
VHtmlSourceWrite() {
exists(Vue::Instance instance, string expr |
attr.getAttr().getRoot() = instance.getTemplateElement().(Vue::Template::HtmlElement).getElement() and
expr = attr.getAttr().getValue() and
// only support for simple identifier expressions
expr.regexpMatch("(?i)[a-z0-9_]+") and
this = instance.getAPropertyValue(expr)
)
}
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
pred = this and succ = attr
}
}
/**
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
* XSS vulnerabilities.

View File

@@ -0,0 +1,2 @@
| single-component-file-1.vue:6:40:6:41 | 42 | single-component-file-1.vue:6:40:6:41 | 42 | single-component-file-1.vue:2:8:2:21 | v-html=dataA |
| single-file-component-3-script.js:4:37:4:38 | 42 | single-file-component-3-script.js:4:37:4:38 | 42 | single-file-component-3.vue:2:8:2:21 | v-html=dataA |

View File

@@ -0,0 +1,6 @@
import javascript
import semmle.javascript.security.dataflow.DomBasedXss
from DomBasedXss::VHtmlSourceWrite w, DataFlow::Node pred, DataFlow::Node succ
where w.step(pred, succ)
select w, pred, succ

View File

@@ -1,2 +1,5 @@
| single-component-file-1.vue:2:8:2:21 | v-html=dataA |
| single-file-component-2.vue:2:8:2:21 | v-html=dataA |
| single-file-component-3.vue:2:8:2:21 | v-html=dataA |
| tst.js:5:13:5:13 | a |
| tst.js:38:12:38:17 | danger |

View File

@@ -178,6 +178,8 @@ nodes
| tst.js:282:9:282:29 | tainted |
| tst.js:282:19:282:29 | window.name |
| tst.js:285:59:285:65 | tainted |
| v-html.vue:2:8:2:23 | v-html=tainted |
| v-html.vue:6:42:6:58 | document.location |
| winjs.js:2:7:2:53 | tainted |
| winjs.js:2:17:2:33 | document.location |
| winjs.js:2:17:2:40 | documen ... .search |
@@ -318,6 +320,7 @@ edges
| tst.js:272:16:272:32 | document.location | tst.js:272:9:272:32 | loc3 |
| tst.js:282:9:282:29 | tainted | tst.js:285:59:285:65 | tainted |
| tst.js:282:19:282:29 | window.name | tst.js:282:9:282:29 | tainted |
| v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted |
| winjs.js:2:7:2:53 | tainted | winjs.js:3:43:3:49 | tainted |
| winjs.js:2:7:2:53 | tainted | winjs.js:4:43:4:49 | tainted |
| winjs.js:2:17:2:33 | document.location | winjs.js:2:17:2:40 | documen ... .search |
@@ -394,5 +397,6 @@ edges
| tst.js:285:59:285:65 | tainted | tst.js:282:9:282:29 | tainted | tst.js:285:59:285:65 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:282:9:282:29 | tainted | user-provided value |
| tst.js:285:59:285:65 | tainted | tst.js:282:19:282:29 | window.name | tst.js:285:59:285:65 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:282:19:282:29 | window.name | user-provided value |
| tst.js:285:59:285:65 | tainted | tst.js:285:59:285:65 | tainted | tst.js:285:59:285:65 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:285:59:285:65 | tainted | 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 |
| winjs.js:3:43:3:49 | tainted | winjs.js:2:17:2:33 | document.location | winjs.js:3:43:3:49 | tainted | Cross-site scripting vulnerability due to $@. | winjs.js:2:17:2:33 | document.location | user-provided value |
| winjs.js:4:43:4:49 | tainted | winjs.js:2:17:2:33 | document.location | winjs.js:4:43:4:49 | tainted | Cross-site scripting vulnerability due to $@. | winjs.js:2:17:2:33 | document.location | user-provided value |

View File

@@ -0,0 +1,10 @@
<template>
<p v-html="tainted"/>
</template>
<script>
export default {
data: function() { return { tainted: document.location } }
}
</script>
<style>
</style>