mirror of
https://github.com/github/codeql.git
synced 2026-04-25 00:35:20 +02:00
Python: Move PathInjection to new dataflow API
This commit is contained in:
@@ -13,6 +13,8 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import PathInjectionCustomizations::PathInjection
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `PathInjectionFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "path injection" vulnerabilities.
|
||||
*
|
||||
* This configuration uses two flow states, `NotNormalized` and `NormalizedUnchecked`,
|
||||
@@ -25,7 +27,7 @@ import PathInjectionCustomizations::PathInjection
|
||||
*
|
||||
* Such checks are ineffective in the `NotNormalized` state.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "PathInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
|
||||
@@ -74,3 +76,52 @@ class NotNormalized extends DataFlow::FlowState {
|
||||
class NormalizedUnchecked extends DataFlow::FlowState {
|
||||
NormalizedUnchecked() { this = "NormalizedUnchecked" }
|
||||
}
|
||||
|
||||
/**
|
||||
* This configuration uses two flow states, `NotNormalized` and `NormalizedUnchecked`,
|
||||
* to track the requirement that a file path must be first normalized and then checked
|
||||
* before it is safe to use.
|
||||
*
|
||||
* At sources, paths are assumed not normalized. At normalization points, they change
|
||||
* state to `NormalizedUnchecked` after which they can be made safe by an appropriate
|
||||
* check of the prefix.
|
||||
*
|
||||
* Such checks are ineffective in the `NotNormalized` state.
|
||||
*/
|
||||
private module PathInjectionConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = DataFlow::FlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source instanceof Source and state instanceof NotNormalized
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
sink instanceof Sink and
|
||||
(
|
||||
state instanceof NotNormalized or
|
||||
state instanceof NormalizedUnchecked
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) {
|
||||
// Block `NotNormalized` paths here, since they change state to `NormalizedUnchecked`
|
||||
node instanceof Path::PathNormalization and
|
||||
state instanceof NotNormalized
|
||||
or
|
||||
node instanceof Path::SafeAccessCheck and
|
||||
state instanceof NormalizedUnchecked
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
|
||||
) {
|
||||
nodeFrom = nodeTo.(Path::PathNormalization).getPathArg() and
|
||||
stateFrom instanceof NotNormalized and
|
||||
stateTo instanceof NormalizedUnchecked
|
||||
}
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "path injection" vulnerabilities. */
|
||||
module PathInjectionFlow = TaintTracking::GlobalWithState<PathInjectionConfig>;
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
import python
|
||||
import semmle.python.security.dataflow.PathInjectionQuery
|
||||
import DataFlow::PathGraph
|
||||
import PathInjectionFlow::PathGraph
|
||||
|
||||
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
from PathInjectionFlow::PathNode source, PathInjectionFlow::PathNode sink
|
||||
where PathInjectionFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This path depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
||||
|
||||
@@ -53,7 +53,8 @@ edges
|
||||
| path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:84:16:84:27 | ControlFlowNode for Attribute |
|
||||
| path_injection.py:84:16:84:27 | ControlFlowNode for Attribute | path_injection.py:84:16:84:47 | ControlFlowNode for Attribute() |
|
||||
| path_injection.py:84:16:84:47 | ControlFlowNode for Attribute() | path_injection.py:84:5:84:12 | SSA variable filename |
|
||||
| path_injection.py:85:5:85:24 | SSA variable possibly_unsafe_path | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path |
|
||||
| path_injection.py:85:5:85:24 | SSA variable possibly_unsafe_path | path_injection.py:86:24:86:43 | ControlFlowNode for possibly_unsafe_path |
|
||||
| path_injection.py:86:24:86:43 | ControlFlowNode for possibly_unsafe_path | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path |
|
||||
| path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:93:5:93:8 | SSA variable path |
|
||||
| path_injection.py:93:5:93:8 | SSA variable path | path_injection.py:94:14:94:17 | ControlFlowNode for path |
|
||||
| path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:101:5:101:8 | SSA variable path |
|
||||
@@ -78,7 +79,8 @@ edges
|
||||
| path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:138:16:138:27 | ControlFlowNode for Attribute |
|
||||
| path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | path_injection.py:138:16:138:47 | ControlFlowNode for Attribute() |
|
||||
| path_injection.py:138:16:138:47 | ControlFlowNode for Attribute() | path_injection.py:138:5:138:12 | SSA variable filename |
|
||||
| path_injection.py:139:5:139:8 | SSA variable path | path_injection.py:142:14:142:17 | ControlFlowNode for path |
|
||||
| path_injection.py:139:5:139:8 | SSA variable path | path_injection.py:140:47:140:50 | ControlFlowNode for path |
|
||||
| path_injection.py:140:47:140:50 | ControlFlowNode for path | path_injection.py:142:14:142:17 | ControlFlowNode for path |
|
||||
| path_injection.py:149:5:149:12 | SSA variable filename | path_injection.py:151:9:151:12 | SSA variable path |
|
||||
| path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute |
|
||||
| path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | path_injection.py:149:16:149:47 | ControlFlowNode for Attribute() |
|
||||
@@ -171,6 +173,7 @@ nodes
|
||||
| path_injection.py:84:16:84:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
|
||||
| path_injection.py:84:16:84:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| path_injection.py:85:5:85:24 | SSA variable possibly_unsafe_path | semmle.label | SSA variable possibly_unsafe_path |
|
||||
| path_injection.py:86:24:86:43 | ControlFlowNode for possibly_unsafe_path | semmle.label | ControlFlowNode for possibly_unsafe_path |
|
||||
| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | semmle.label | ControlFlowNode for possibly_unsafe_path |
|
||||
| path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | semmle.label | ControlFlowNode for foo_id |
|
||||
| path_injection.py:93:5:93:8 | SSA variable path | semmle.label | SSA variable path |
|
||||
@@ -202,6 +205,7 @@ nodes
|
||||
| path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
|
||||
| path_injection.py:138:16:138:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| path_injection.py:139:5:139:8 | SSA variable path | semmle.label | SSA variable path |
|
||||
| path_injection.py:140:47:140:50 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
|
||||
| path_injection.py:142:14:142:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
|
||||
| path_injection.py:149:5:149:12 | SSA variable filename | semmle.label | SSA variable filename |
|
||||
| path_injection.py:149:16:149:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
|
||||
|
||||
Reference in New Issue
Block a user