Python: Model os.path.join and add taint-step

This commit is contained in:
Rasmus Wriedt Larsen
2020-09-30 11:42:36 +02:00
parent efa2484718
commit 0542c3b91e
3 changed files with 51 additions and 2 deletions

View File

@@ -130,7 +130,6 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
// f-strings
nodeTo.asExpr().(Fstring).getAValue() = nodeFrom.asExpr()
// TODO: Handle encode/decode from base64/quopri
// TODO: Handle os.path.join
// TODO: Handle functions in https://docs.python.org/3/library/binascii.html
}

View File

@@ -5,9 +5,11 @@
private import python
private import experimental.dataflow.DataFlow
private import experimental.dataflow.TaintTracking
private import experimental.dataflow.RemoteFlowSources
private import experimental.semmle.python.Concepts
/** Provides models for the Python standard library. */
private module Stdlib {
/** Gets a reference to the `os` module. */
DataFlow::Node os(DataFlow::TypeTracker t) {
@@ -20,6 +22,7 @@ private module Stdlib {
/** Gets a reference to the `os` module. */
DataFlow::Node os() { result = os(DataFlow::TypeTracker::end()) }
/** Provides models for the `os` module. */
module os {
/** Gets a reference to the `os.system` function. */
DataFlow::Node system(DataFlow::TypeTracker t) {
@@ -48,6 +51,41 @@ private module Stdlib {
/** Gets a reference to the `os.popen` function. */
DataFlow::Node popen() { result = os::popen(DataFlow::TypeTracker::end()) }
/** Gets a reference to the `os.path` module. */
private DataFlow::Node path(DataFlow::TypeTracker t) {
t.start() and
(
result = DataFlow::importMember("os", "path")
or
result = DataFlow::importModule("os.path")
)
or
t.startInAttr("path") and
result = os()
or
exists(DataFlow::TypeTracker t2 | result = path(t2).track(t2, t))
}
/** Gets a reference to the `os.path` module. */
DataFlow::Node path() { result = path(DataFlow::TypeTracker::end()) }
/** Provides models for the `os.path` module */
module path {
/** Gets a reference to the `os.path.join` function. */
private DataFlow::Node join(DataFlow::TypeTracker t) {
t.start() and
result = DataFlow::importMember("os.path", "join")
or
t.startInAttr("join") and
result = os::path()
or
exists(DataFlow::TypeTracker t2 | result = join(t2).track(t2, t))
}
/** Gets a reference to the `os.join` module. */
DataFlow::Node join() { result = join(DataFlow::TypeTracker::end()) }
}
}
/**
@@ -73,4 +111,16 @@ private module Stdlib {
result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0)
}
}
/** An additional taint step for calls to `os.path.join` */
private class OsPathJoinCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
exists(CallNode call |
nodeTo.asCfgNode() = call and
call.getFunction() = os::path::join().asCfgNode() and
call.getAnArg() = nodeFrom.asCfgNode()
)
// TODO: Handle pathlib (like we do for os.path.join)
}
}
}