JS: query to find dynamic creations of DOM elements that use untrusted sources

This commit is contained in:
Stephan Brandauer
2022-02-14 20:07:57 +01:00
parent b35c70994f
commit 8d397fea09
5 changed files with 114 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
/**
* @name Dynamic creation of untrusted source use
* @description Finds dynamically created DOM elements that may use
* behaviour from http-URLs without integrity checks.
* @kind path-problem
* @problem.severity error
* @tags security
* @id js/dynamic-creation-of-untrusted-source-use
*/
import javascript
import DataFlow::PathGraph
predicate isCreateElementNode(DataFlow::CallNode call, string name) {
call = DataFlow::globalVarRef("document").getAMethodCall("createElement") and
call.getArgument(0).getStringValue().toLowerCase() = name
}
predicate isCreateScriptNodeWoIntegrityCheck(DataFlow::CallNode call) {
isCreateElementNode(call, "script") and
not exists(DataFlow::Node rhs | isScriptPropWrite(call, "integrity", rhs))
}
predicate isScriptPropWrite(
DataFlow::CallNode createElementCall, string propName, DataFlow::Node rhs
) {
exists(DataFlow::PropWrite assignment |
isCreateElementNode(createElementCall, "script") and
assignment.writes(createElementCall.getALocalUse(), propName, rhs)
)
}
class DynamicCreationOfUntrustedSourceUseCfg extends TaintTracking::Configuration {
DynamicCreationOfUntrustedSourceUseCfg() { this = "DynamicCreationOfUntrustedSourceUseCfg" }
override predicate isSource(DataFlow::Node source) {
exists(StringLiteral s | source = s.flow() |
s.getValue() = ["http:", "//"] + any(string rest) // TODO match HTTP HtTp etc
)
}
override predicate isSink(DataFlow::Node sink) {
exists(DataFlow::CallNode createElementCall |
isScriptPropWrite(createElementCall, "src", sink) and
isCreateScriptNodeWoIntegrityCheck(createElementCall)
or
exists(DataFlow::CallNode iframeCreateCall, DataFlow::PropWrite srcWrite |
isCreateElementNode(iframeCreateCall, "iframe") and
srcWrite.getRhs() = sink and
srcWrite.getBase() = iframeCreateCall.getALocalUse()
)
)
}
}
from DynamicCreationOfUntrustedSourceUseCfg cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Illegal flow from $@.", source.getNode(), "here"

View File

@@ -0,0 +1,6 @@
---
category: newQuery
---
* A new query, `js/dynamic-creation-of-untrusted-source-use`, has been added to the query suite. It finds code
that creates HTML elements that load functionality from untrusted sources, like a `script`- or `iframe`-element using http-links.
The query is run by default.

View File

@@ -0,0 +1,20 @@
nodes
| dynamic.html:8:27:8:97 | ('https ... //www') |
| dynamic.html:8:27:8:118 | ('https ... /ga.js' |
| dynamic.html:8:27:8:118 | ('https ... /ga.js' |
| dynamic.html:8:28:8:96 | 'https: ... ://www' |
| dynamic.html:8:85:8:96 | 'http://www' |
| dynamic.html:8:85:8:96 | 'http://www' |
| dynamic.html:18:26:18:50 | 'http:/ ... e.com/' |
| dynamic.html:18:26:18:50 | 'http:/ ... e.com/' |
| dynamic.html:18:26:18:50 | 'http:/ ... e.com/' |
edges
| dynamic.html:8:27:8:97 | ('https ... //www') | dynamic.html:8:27:8:118 | ('https ... /ga.js' |
| dynamic.html:8:27:8:97 | ('https ... //www') | dynamic.html:8:27:8:118 | ('https ... /ga.js' |
| dynamic.html:8:28:8:96 | 'https: ... ://www' | dynamic.html:8:27:8:97 | ('https ... //www') |
| dynamic.html:8:85:8:96 | 'http://www' | dynamic.html:8:28:8:96 | 'https: ... ://www' |
| dynamic.html:8:85:8:96 | 'http://www' | dynamic.html:8:28:8:96 | 'https: ... ://www' |
| dynamic.html:18:26:18:50 | 'http:/ ... e.com/' | dynamic.html:18:26:18:50 | 'http:/ ... e.com/' |
#select
| dynamic.html:8:27:8:118 | ('https ... /ga.js' | dynamic.html:8:85:8:96 | 'http://www' | dynamic.html:8:27:8:118 | ('https ... /ga.js' | Illegal flow from $@. | dynamic.html:8:85:8:96 | 'http://www' | here |
| dynamic.html:18:26:18:50 | 'http:/ ... e.com/' | dynamic.html:18:26:18:50 | 'http:/ ... e.com/' | dynamic.html:18:26:18:50 | 'http:/ ... e.com/' | Illegal flow from $@. | dynamic.html:18:26:18:50 | 'http:/ ... e.com/' | here |

View File

@@ -0,0 +1 @@
Security/CWE-830/DynamicCreationOfUntrustedSourceUse.ql

View File

@@ -0,0 +1,29 @@
<html>
<head>
<script type="text/javascript">
(function() {
// NOT OK (no integrity attribute)
var scrpt = document.createElement('script');
scrpt.type = 'text/javascript';
scrpt.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.cdn.local/ga.js';
// OK (integrity digest present)
var scrpt2 = document.createElement('script');
scrpt2.type = 'text/javascript';
scrpt2.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.cdn.local/ga.js';
scrpt2.integrity = 'sha256-h0UuK3mE9taiYlB5u9vT9A0s/XDgkfVd+F4VhN/sky=';
// NOT OK (http URL)
var ifrm = document.createElement('iframe');
ifrm.src = 'http://www.example.com/';
// OK (https URL)
var ifrm2 = document.createElement('iframe');
ifrm2.src = 'https://www.example.com/';
})();
</script>
</head>
<body>
hello
</body>
</html>