Ruby: configsig rb/unsafe-code-construction

This commit is contained in:
Alex Ford
2023-09-01 17:27:33 +01:00
parent 3e23a6e021
commit 461bc0d359
2 changed files with 35 additions and 6 deletions

View File

@@ -2,8 +2,9 @@
* Provides a taint-tracking configuration for reasoning about code
* constructed from library input vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `UnsafeCodeConstructionCustomizations` should be imported instead.
* Note, for performance reasons: only import this file if
* `UnsafeCodeConstructionFlow` is needed, otherwise
* `UnsafeCodeConstructionCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
@@ -13,8 +14,9 @@ private import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting code constructed from library input vulnerabilities.
* DEPRECATED: Use `UnsafeCodeConstructionFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeShellCommandConstruction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,3 +39,28 @@ class Configuration extends TaintTracking::Configuration {
set.isElementOfTypeOrUnknown("int")
}
}
private module UnsafeCodeConstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) {
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier
}
// override to require the path doesn't have unmatched return steps
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet set) {
// allow implicit reads of array elements
isSink(node) and
set.isElementOfTypeOrUnknown("int")
}
}
/**
* Taint-tracking for detecting code constructed from library input vulnerabilities.
*/
module UnsafeCodeConstructionFlow = TaintTracking::Global<UnsafeCodeConstructionConfig>;

View File

@@ -14,10 +14,12 @@
*/
import codeql.ruby.security.UnsafeCodeConstructionQuery
import DataFlow::PathGraph
import UnsafeCodeConstructionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode()
from
UnsafeCodeConstructionFlow::PathNode source, UnsafeCodeConstructionFlow::PathNode sink,
Sink sinkNode
where UnsafeCodeConstructionFlow::flowPath(source, sink) and sinkNode = sink.getNode()
select sink.getNode(), source, sink,
"This " + sinkNode.getSinkType() + " which depends on $@ is later $@.", source.getNode(),
"library input", sinkNode.getCodeSink(), "interpreted as code"