mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
JS: Port UnsafeDynamicMethodAccess
This commit is contained in:
@@ -20,7 +20,66 @@ private class ConcreteUnsafeFunction extends UnsafeFunction {
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about unsafe dynamic method access.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
module UnsafeDynamicMethodAccessConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = DataFlow::FlowLabel;
|
||||
|
||||
predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
|
||||
source.(Source).getFlowLabel() = label
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
|
||||
sink.(Sink).getFlowLabel() = label
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node instanceof Sanitizer
|
||||
or
|
||||
exists(StringConcatenation::getOperand(node, _)) and
|
||||
not StringConcatenation::isCoercion(node)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, DataFlow::FlowLabel label) {
|
||||
TaintTracking::defaultSanitizer(node) and
|
||||
label.isTaint()
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, DataFlow::FlowLabel srclabel, DataFlow::Node dst,
|
||||
DataFlow::FlowLabel dstlabel
|
||||
) {
|
||||
// Reading a property of the global object or of a function
|
||||
exists(DataFlow::PropRead read |
|
||||
PropertyInjection::hasUnsafeMethods(read.getBase().getALocalSource()) and
|
||||
src = read.getPropertyNameExpr().flow() and
|
||||
dst = read and
|
||||
srclabel.isTaint() and
|
||||
dstlabel = unsafeFunction()
|
||||
)
|
||||
or
|
||||
// Reading a chain of properties from any object with a prototype can lead to Function
|
||||
exists(PropertyProjection proj |
|
||||
not PropertyInjection::isPrototypeLessObject(proj.getObject().getALocalSource()) and
|
||||
src = proj.getASelector() and
|
||||
dst = proj and
|
||||
srclabel.isTaint() and
|
||||
dstlabel = unsafeFunction()
|
||||
)
|
||||
or
|
||||
srclabel.isTaint() and
|
||||
TaintTracking::defaultTaintStep(src, dst) and
|
||||
srclabel = dstlabel
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint-tracking for reasoning about unsafe dynamic method access.
|
||||
*/
|
||||
module UnsafeDynamicMethodAccessFlow = DataFlow::GlobalWithState<UnsafeDynamicMethodAccessConfig>;
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use the `UnsafeDynamicMethodAccessFlow` module instead.
|
||||
*/
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "UnsafeDynamicMethodAccess" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.UnsafeDynamicMethodAccessQuery
|
||||
import DataFlow::PathGraph
|
||||
import UnsafeDynamicMethodAccessFlow::PathGraph
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink)
|
||||
from UnsafeDynamicMethodAccessFlow::PathNode source, UnsafeDynamicMethodAccessFlow::PathNode sink
|
||||
where UnsafeDynamicMethodAccessFlow::flowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"This method is invoked using a $@, which may allow remote code execution.", source.getNode(),
|
||||
"user-controlled value"
|
||||
|
||||
@@ -1,53 +1,12 @@
|
||||
nodes
|
||||
| example.js:9:37:9:38 | ev |
|
||||
| example.js:9:37:9:38 | ev |
|
||||
| example.js:10:9:10:37 | message |
|
||||
| example.js:10:19:10:37 | JSON.parse(ev.data) |
|
||||
| example.js:10:30:10:31 | ev |
|
||||
| example.js:10:30:10:36 | ev.data |
|
||||
| example.js:13:5:13:24 | window[message.name] |
|
||||
| example.js:13:5:13:24 | window[message.name] |
|
||||
| example.js:13:12:13:18 | message |
|
||||
| example.js:13:12:13:23 | message.name |
|
||||
| tst.js:3:37:3:38 | ev |
|
||||
| tst.js:3:37:3:38 | ev |
|
||||
| tst.js:4:9:4:37 | message |
|
||||
| tst.js:4:19:4:37 | JSON.parse(ev.data) |
|
||||
| tst.js:4:30:4:31 | ev |
|
||||
| tst.js:4:30:4:36 | ev.data |
|
||||
| tst.js:5:5:5:24 | window[message.name] |
|
||||
| tst.js:5:5:5:24 | window[message.name] |
|
||||
| tst.js:5:12:5:18 | message |
|
||||
| tst.js:5:12:5:23 | message.name |
|
||||
| tst.js:6:9:6:28 | window[message.name] |
|
||||
| tst.js:6:9:6:28 | window[message.name] |
|
||||
| tst.js:6:16:6:22 | message |
|
||||
| tst.js:6:16:6:27 | message.name |
|
||||
| tst.js:11:5:11:19 | f[message.name] |
|
||||
| tst.js:11:5:11:19 | f[message.name] |
|
||||
| tst.js:11:7:11:13 | message |
|
||||
| tst.js:11:7:11:18 | message.name |
|
||||
| tst.js:15:5:15:14 | window[ev] |
|
||||
| tst.js:15:5:15:14 | window[ev] |
|
||||
| tst.js:15:12:15:13 | ev |
|
||||
| tst.js:21:5:21:29 | window[ ... e.name] |
|
||||
| tst.js:21:5:21:29 | window[ ... e.name] |
|
||||
| tst.js:21:12:21:28 | '' + message.name |
|
||||
| tst.js:21:17:21:23 | message |
|
||||
| tst.js:21:17:21:28 | message.name |
|
||||
edges
|
||||
| example.js:9:37:9:38 | ev | example.js:10:30:10:31 | ev |
|
||||
| example.js:9:37:9:38 | ev | example.js:10:30:10:31 | ev |
|
||||
| example.js:10:9:10:37 | message | example.js:13:12:13:18 | message |
|
||||
| example.js:10:19:10:37 | JSON.parse(ev.data) | example.js:10:9:10:37 | message |
|
||||
| example.js:10:30:10:31 | ev | example.js:10:30:10:36 | ev.data |
|
||||
| example.js:10:30:10:36 | ev.data | example.js:10:19:10:37 | JSON.parse(ev.data) |
|
||||
| example.js:13:12:13:18 | message | example.js:13:12:13:23 | message.name |
|
||||
| example.js:13:12:13:23 | message.name | example.js:13:5:13:24 | window[message.name] |
|
||||
| example.js:13:12:13:23 | message.name | example.js:13:5:13:24 | window[message.name] |
|
||||
| tst.js:3:37:3:38 | ev | tst.js:4:30:4:31 | ev |
|
||||
| tst.js:3:37:3:38 | ev | tst.js:4:30:4:31 | ev |
|
||||
| tst.js:3:37:3:38 | ev | tst.js:15:12:15:13 | ev |
|
||||
| tst.js:3:37:3:38 | ev | tst.js:15:12:15:13 | ev |
|
||||
| tst.js:4:9:4:37 | message | tst.js:5:12:5:18 | message |
|
||||
| tst.js:4:9:4:37 | message | tst.js:6:16:6:22 | message |
|
||||
@@ -58,19 +17,44 @@ edges
|
||||
| tst.js:4:30:4:36 | ev.data | tst.js:4:19:4:37 | JSON.parse(ev.data) |
|
||||
| tst.js:5:12:5:18 | message | tst.js:5:12:5:23 | message.name |
|
||||
| tst.js:5:12:5:23 | message.name | tst.js:5:5:5:24 | window[message.name] |
|
||||
| tst.js:5:12:5:23 | message.name | tst.js:5:5:5:24 | window[message.name] |
|
||||
| tst.js:6:16:6:22 | message | tst.js:6:16:6:27 | message.name |
|
||||
| tst.js:6:16:6:27 | message.name | tst.js:6:9:6:28 | window[message.name] |
|
||||
| tst.js:6:16:6:27 | message.name | tst.js:6:9:6:28 | window[message.name] |
|
||||
| tst.js:11:7:11:13 | message | tst.js:11:7:11:18 | message.name |
|
||||
| tst.js:11:7:11:18 | message.name | tst.js:11:5:11:19 | f[message.name] |
|
||||
| tst.js:11:7:11:18 | message.name | tst.js:11:5:11:19 | f[message.name] |
|
||||
| tst.js:15:12:15:13 | ev | tst.js:15:5:15:14 | window[ev] |
|
||||
| tst.js:15:12:15:13 | ev | tst.js:15:5:15:14 | window[ev] |
|
||||
| tst.js:21:12:21:28 | '' + message.name | tst.js:21:5:21:29 | window[ ... e.name] |
|
||||
| tst.js:21:12:21:28 | '' + message.name | tst.js:21:5:21:29 | window[ ... e.name] |
|
||||
| tst.js:21:17:21:23 | message | tst.js:21:17:21:28 | message.name |
|
||||
| tst.js:21:17:21:28 | message.name | tst.js:21:12:21:28 | '' + message.name |
|
||||
nodes
|
||||
| example.js:9:37:9:38 | ev | semmle.label | ev |
|
||||
| example.js:10:9:10:37 | message | semmle.label | message |
|
||||
| example.js:10:19:10:37 | JSON.parse(ev.data) | semmle.label | JSON.parse(ev.data) |
|
||||
| example.js:10:30:10:31 | ev | semmle.label | ev |
|
||||
| example.js:10:30:10:36 | ev.data | semmle.label | ev.data |
|
||||
| example.js:13:5:13:24 | window[message.name] | semmle.label | window[message.name] |
|
||||
| example.js:13:12:13:18 | message | semmle.label | message |
|
||||
| example.js:13:12:13:23 | message.name | semmle.label | message.name |
|
||||
| tst.js:3:37:3:38 | ev | semmle.label | ev |
|
||||
| tst.js:4:9:4:37 | message | semmle.label | message |
|
||||
| tst.js:4:19:4:37 | JSON.parse(ev.data) | semmle.label | JSON.parse(ev.data) |
|
||||
| tst.js:4:30:4:31 | ev | semmle.label | ev |
|
||||
| tst.js:4:30:4:36 | ev.data | semmle.label | ev.data |
|
||||
| tst.js:5:5:5:24 | window[message.name] | semmle.label | window[message.name] |
|
||||
| tst.js:5:12:5:18 | message | semmle.label | message |
|
||||
| tst.js:5:12:5:23 | message.name | semmle.label | message.name |
|
||||
| tst.js:6:9:6:28 | window[message.name] | semmle.label | window[message.name] |
|
||||
| tst.js:6:16:6:22 | message | semmle.label | message |
|
||||
| tst.js:6:16:6:27 | message.name | semmle.label | message.name |
|
||||
| tst.js:11:5:11:19 | f[message.name] | semmle.label | f[message.name] |
|
||||
| tst.js:11:7:11:13 | message | semmle.label | message |
|
||||
| tst.js:11:7:11:18 | message.name | semmle.label | message.name |
|
||||
| tst.js:15:5:15:14 | window[ev] | semmle.label | window[ev] |
|
||||
| tst.js:15:12:15:13 | ev | semmle.label | ev |
|
||||
| tst.js:21:5:21:29 | window[ ... e.name] | semmle.label | window[ ... e.name] |
|
||||
| tst.js:21:12:21:28 | '' + message.name | semmle.label | '' + message.name |
|
||||
| tst.js:21:17:21:23 | message | semmle.label | message |
|
||||
| tst.js:21:17:21:28 | message.name | semmle.label | message.name |
|
||||
subpaths
|
||||
#select
|
||||
| example.js:13:5:13:24 | window[message.name] | example.js:9:37:9:38 | ev | example.js:13:5:13:24 | window[message.name] | This method is invoked using a $@, which may allow remote code execution. | example.js:9:37:9:38 | ev | user-controlled value |
|
||||
| tst.js:5:5:5:24 | window[message.name] | tst.js:3:37:3:38 | ev | tst.js:5:5:5:24 | window[message.name] | This method is invoked using a $@, which may allow remote code execution. | tst.js:3:37:3:38 | ev | user-controlled value |
|
||||
|
||||
Reference in New Issue
Block a user