Skip to content

Commit b1a49dd

Browse files
committed
Ruby: configsig rb/code-injection
1 parent 6fa267a commit b1a49dd

2 files changed

Lines changed: 40 additions & 10 deletions

File tree

ruby/ql/lib/codeql/ruby/security/CodeInjectionQuery.qll

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/**
22
* Provides a taint-tracking configuration for detecting "Code injection" vulnerabilities.
33
*
4-
* Note, for performance reasons: only import this file if `Configuration` is needed,
5-
* otherwise `CodeInjectionCustomizations` should be imported instead.
4+
* Note, for performance reasons: only import this file if
5+
* `CodeInjectionFlow` is needed, otherwise
6+
* `CodeInjectionCustomizations` should be imported instead.
67
*/
78

89
import codeql.ruby.DataFlow
@@ -12,8 +13,9 @@ import codeql.ruby.dataflow.BarrierGuards
1213

1314
/**
1415
* A taint-tracking configuration for detecting "Code injection" vulnerabilities.
16+
* DEPRECATED: Use `CodeInjectionFlow` instead
1517
*/
16-
class Configuration extends TaintTracking::Configuration {
18+
deprecated class Configuration extends TaintTracking::Configuration {
1719
Configuration() { this = "CodeInjection" }
1820

1921
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
@@ -40,3 +42,30 @@ class Configuration extends TaintTracking::Configuration {
4042
guard instanceof SanitizerGuard
4143
}
4244
}
45+
46+
private module Config implements DataFlow::StateConfigSig {
47+
class FlowState = DataFlow::FlowState;
48+
49+
predicate isSource(DataFlow::Node source, FlowState state) {
50+
state = source.(Source).getAFlowState()
51+
}
52+
53+
predicate isSink(DataFlow::Node sink, FlowState state) { state = sink.(Sink).getAFlowState() }
54+
55+
predicate isBarrier(DataFlow::Node node) {
56+
node instanceof Sanitizer and not exists(node.(Sanitizer).getAFlowState())
57+
or
58+
node instanceof StringConstCompareBarrier
59+
or
60+
node instanceof StringConstArrayInclusionCallBarrier
61+
}
62+
63+
predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
64+
node.(Sanitizer).getAFlowState() = state
65+
}
66+
}
67+
68+
/**
69+
* Taint-tracking for detecting "Code injection" vulnerabilities.
70+
*/
71+
module CodeInjectionFlow = TaintTracking::GlobalWithState<Config>;

ruby/ql/src/queries/security/cwe-094/CodeInjection.ql

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,19 @@
1414
* external/cwe/cwe-116
1515
*/
1616

17-
import codeql.ruby.AST
18-
import codeql.ruby.security.CodeInjectionQuery
19-
import DataFlow::PathGraph
17+
private import codeql.ruby.AST
18+
private import codeql.ruby.security.CodeInjectionQuery
19+
private import CodeInjectionFlow::PathGraph
2020

21-
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, Source sourceNode
21+
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, Source sourceNode
2222
where
23-
config.hasFlowPath(source, sink) and
23+
CodeInjectionFlow::flowPath(source, sink) and
2424
sourceNode = source.getNode() and
2525
// removing duplications of the same path, but different flow-labels.
2626
sink =
27-
min(DataFlow::PathNode otherSink |
28-
config.hasFlowPath(any(DataFlow::PathNode s | s.getNode() = sourceNode), otherSink) and
27+
min(CodeInjectionFlow::PathNode otherSink |
28+
CodeInjectionFlow::flowPath(any(CodeInjectionFlow::PathNode s | s.getNode() = sourceNode),
29+
otherSink) and
2930
otherSink.getNode() = sink.getNode()
3031
|
3132
otherSink order by otherSink.getState()

0 commit comments

Comments
 (0)