Python: asCfgNode cleanup

This commit is contained in:
Taus
2021-06-17 19:48:26 +00:00
committed by GitHub
parent c386f4a009
commit 9351688da8
11 changed files with 79 additions and 99 deletions

View File

@@ -13,12 +13,12 @@ class PyOpenSSLContextCreation extends ContextCreation, DataFlow::CallCfgNode {
}
override string getProtocol() {
exists(ControlFlowNode protocolArg, PyOpenSSL pyo |
protocolArg in [node.getArg(0), node.getArgByName("method")]
exists(DataFlow::Node protocolArg, PyOpenSSL pyo |
protocolArg in [this.getArg(0), this.getArgByName("method")]
|
protocolArg =
[pyo.specific_version(result).getAUse(), pyo.unspecific_version(result).getAUse()]
.asCfgNode()
protocolArg in [
pyo.specific_version(result).getAUse(), pyo.unspecific_version(result).getAUse()
]
)
}
}
@@ -29,7 +29,7 @@ class ConnectionCall extends ConnectionCreation, DataFlow::CallCfgNode {
}
override DataFlow::CfgNode getContext() {
result.getNode() in [node.getArg(0), node.getArgByName("context")]
result in [this.getArg(0), this.getArgByName("context")]
}
}
@@ -43,8 +43,8 @@ class SetOptionsCall extends ProtocolRestriction, DataFlow::CallCfgNode {
}
override ProtocolVersion getRestriction() {
API::moduleImport("OpenSSL").getMember("SSL").getMember("OP_NO_" + result).getAUse().asCfgNode() in [
node.getArg(0), node.getArgByName("options")
API::moduleImport("OpenSSL").getMember("SSL").getMember("OP_NO_" + result).getAUse() in [
this.getArg(0), this.getArgByName("options")
]
}
}

View File

@@ -11,15 +11,14 @@ class SSLContextCreation extends ContextCreation, DataFlow::CallCfgNode {
SSLContextCreation() { this = API::moduleImport("ssl").getMember("SSLContext").getACall() }
override string getProtocol() {
exists(ControlFlowNode protocolArg, Ssl ssl |
protocolArg in [node.getArg(0), node.getArgByName("protocol")]
exists(DataFlow::Node protocolArg, Ssl ssl |
protocolArg in [this.getArg(0), this.getArgByName("protocol")]
|
protocolArg =
[ssl.specific_version(result).getAUse(), ssl.unspecific_version(result).getAUse()]
.asCfgNode()
)
or
not exists(node.getAnArg()) and
not exists(this.getArg(_)) and
result = "TLS"
}
}
@@ -133,7 +132,7 @@ class ContextSetVersion extends ProtocolRestriction, ProtocolUnrestriction, Data
ContextSetVersion() {
exists(DataFlow::AttrWrite aw |
aw.getObject().asCfgNode() = node and
this = aw.getObject() and
aw.getAttributeName() = "minimum_version" and
aw.getValue() =
API::moduleImport("ssl").getMember("TLSVersion").getMember(restriction).getAUse()

View File

@@ -80,6 +80,6 @@ module ClickHouseDriver {
private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode {
ExecuteCall() { this.getFunction() = clickhouse_execute() }
override DataFlow::Node getSql() { result.asCfgNode() = node.getArg(0) }
override DataFlow::Node getSql() { result = this.getArg(0) }
}
}

View File

@@ -243,7 +243,7 @@ private module SensitiveDataModeling {
SensitiveDataClassification classification;
SensitiveGetCall() {
this.getFunction().asCfgNode().(AttrNode).getName() = "get" and
this.getFunction().(DataFlow::AttrRef).getAttributeName() = "get" and
this.getArg(0) = sensitiveLookupStringConst(classification)
}

View File

@@ -401,11 +401,11 @@ private module PrivateDjango {
* Gets an instance of the `django.db.models.expressions.RawSQL` class,
* that was initiated with the SQL represented by `sql`.
*/
private DataFlow::LocalSourceNode instance(DataFlow::TypeTracker t, ControlFlowNode sql) {
private DataFlow::LocalSourceNode instance(DataFlow::TypeTracker t, DataFlow::Node sql) {
t.start() and
exists(DataFlow::CallCfgNode c | result = c |
c = classRef().getACall() and
c.getArg(0).asCfgNode() = sql
c.getArg(0) = sql
)
or
exists(DataFlow::TypeTracker t2 | result = instance(t2, sql).track(t2, t))
@@ -415,7 +415,7 @@ private module PrivateDjango {
* Gets an instance of the `django.db.models.expressions.RawSQL` class,
* that was initiated with the SQL represented by `sql`.
*/
DataFlow::Node instance(ControlFlowNode sql) {
DataFlow::Node instance(DataFlow::Node sql) {
instance(DataFlow::TypeTracker::end(), sql).flowsTo(result)
}
}
@@ -431,7 +431,7 @@ private module PrivateDjango {
* See https://docs.djangoproject.com/en/3.1/ref/models/querysets/#annotate
*/
private class ObjectsAnnotate extends SqlExecution::Range, DataFlow::CallCfgNode {
ControlFlowNode sql;
DataFlow::Node sql;
ObjectsAnnotate() {
this = django::db::models::querySetReturningMethod("annotate").getACall() and
@@ -440,7 +440,7 @@ private module PrivateDjango {
]
}
override DataFlow::Node getSql() { result.asCfgNode() = sql }
override DataFlow::Node getSql() { result = sql }
}
/**
@@ -449,7 +449,7 @@ private module PrivateDjango {
* See https://docs.djangoproject.com/en/3.2/ref/models/querysets/#alias
*/
private class ObjectsAlias extends SqlExecution::Range, DataFlow::CallCfgNode {
ControlFlowNode sql;
DataFlow::Node sql;
ObjectsAlias() {
this = django::db::models::querySetReturningMethod("alias").getACall() and
@@ -458,7 +458,7 @@ private module PrivateDjango {
]
}
override DataFlow::Node getSql() { result.asCfgNode() = sql }
override DataFlow::Node getSql() { result = sql }
}
/**
@@ -631,12 +631,12 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("content")]
result in [this.getArg(0), this.getArgByName("content")]
}
// How to support the `headers` argument here?
override DataFlow::Node getMimetypeOrContentTypeArg() {
result.asCfgNode() in [node.getArg(1), node.getArgByName("content_type")]
result in [this.getArg(1), this.getArgByName("content_type")]
}
override string getMimetypeDefault() { result = "text/html" }
@@ -695,11 +695,11 @@ private module PrivateDjango {
// note that even though browsers like Chrome usually doesn't fetch the
// content of a redirect, it is possible to observe the body (for example,
// with cURL).
result.asCfgNode() in [node.getArg(1), node.getArgByName("content")]
result in [this.getArg(1), this.getArgByName("content")]
}
override DataFlow::Node getRedirectLocation() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("redirect_to")]
result in [this.getArg(0), this.getArgByName("redirect_to")]
}
// How to support the `headers` argument here?
@@ -757,11 +757,11 @@ private module PrivateDjango {
// note that even though browsers like Chrome usually doesn't fetch the
// content of a redirect, it is possible to observe the body (for example,
// with cURL).
result.asCfgNode() in [node.getArg(1), node.getArgByName("content")]
result in [this.getArg(1), this.getArgByName("content")]
}
override DataFlow::Node getRedirectLocation() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("redirect_to")]
result in [this.getArg(0), this.getArgByName("redirect_to")]
}
// How to support the `headers` argument here?
@@ -868,7 +868,7 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("content")]
result in [this.getArg(0), this.getArgByName("content")]
}
// How to support the `headers` argument here?
@@ -922,7 +922,7 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("content")]
result in [this.getArg(0), this.getArgByName("content")]
}
// How to support the `headers` argument here?
@@ -976,7 +976,7 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("content")]
result in [this.getArg(0), this.getArgByName("content")]
}
// How to support the `headers` argument here?
@@ -1031,7 +1031,7 @@ private module PrivateDjango {
override DataFlow::Node getBody() {
// First argument is permitted methods
result.asCfgNode() in [node.getArg(1), node.getArgByName("content")]
result in [this.getArg(1), this.getArgByName("content")]
}
// How to support the `headers` argument here?
@@ -1085,7 +1085,7 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("content")]
result in [this.getArg(0), this.getArgByName("content")]
}
// How to support the `headers` argument here?
@@ -1139,7 +1139,7 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("content")]
result in [this.getArg(0), this.getArgByName("content")]
}
// How to support the `headers` argument here?
@@ -1193,7 +1193,7 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("data")]
result in [this.getArg(0), this.getArgByName("data")]
}
// How to support the `headers` argument here?
@@ -1250,7 +1250,7 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("streaming_content")]
result in [this.getArg(0), this.getArgByName("streaming_content")]
}
// How to support the `headers` argument here?
@@ -1304,7 +1304,7 @@ private module PrivateDjango {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("streaming_content")]
result in [this.getArg(0), this.getArgByName("streaming_content")]
}
// How to support the `headers` argument here?
@@ -1349,14 +1349,13 @@ private module PrivateDjango {
*
* See https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.HttpResponse.write
*/
class HttpResponseWriteCall extends HTTP::Server::HttpResponse::Range, DataFlow::CfgNode {
override CallNode node;
class HttpResponseWriteCall extends HTTP::Server::HttpResponse::Range, DataFlow::CallCfgNode {
HTTP::Server::HttpResponse::Range instance;
HttpResponseWriteCall() { node.getFunction() = write(instance).asCfgNode() }
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("content")]
result in [this.getArg(0), this.getArgByName("content")]
}
override DataFlow::Node getMimetypeOrContentTypeArg() {
@@ -1639,12 +1638,10 @@ private module PrivateDjango {
DjangoUrlsPathCall() { this = django::urls::path().getACall() }
override DataFlow::Node getUrlPatternArg() {
result.asCfgNode() = [node.getArg(0), node.getArgByName("route")]
result in [this.getArg(0), this.getArgByName("route")]
}
override DataFlow::Node getViewArg() {
result.asCfgNode() in [node.getArg(1), node.getArgByName("view")]
}
override DataFlow::Node getViewArg() { result in [this.getArg(1), this.getArgByName("view")] }
override Parameter getARoutedParameter() {
// If we don't know the URL pattern, we simply mark all parameters as a routed
@@ -1739,12 +1736,10 @@ private module PrivateDjango {
}
override DataFlow::Node getUrlPatternArg() {
result.asCfgNode() = [node.getArg(0), node.getArgByName("route")]
result in [this.getArg(0), this.getArgByName("route")]
}
override DataFlow::Node getViewArg() {
result.asCfgNode() in [node.getArg(1), node.getArgByName("view")]
}
override DataFlow::Node getViewArg() { result in [this.getArg(1), this.getArgByName("view")] }
}
/**
@@ -1756,12 +1751,10 @@ private module PrivateDjango {
DjangoConfUrlsUrlCall() { this = django::conf::conf_urls::url().getACall() }
override DataFlow::Node getUrlPatternArg() {
result.asCfgNode() = [node.getArg(0), node.getArgByName("regex")]
result in [this.getArg(0), this.getArgByName("regex")]
}
override DataFlow::Node getViewArg() {
result.asCfgNode() in [node.getArg(1), node.getArgByName("view")]
}
override DataFlow::Node getViewArg() { result in [this.getArg(1), this.getArgByName("view")] }
}
// ---------------------------------------------------------------------------
@@ -1872,7 +1865,7 @@ private module PrivateDjango {
* a string identifying a view, or a Django model.
*/
override DataFlow::Node getRedirectLocation() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("to")]
result in [this.getArg(0), this.getArgByName("to")]
}
override DataFlow::Node getBody() { none() }

View File

@@ -48,7 +48,7 @@ private module FabricV1 {
FabricApiLocalRunSudoCall() { this = api().getMember(["local", "run", "sudo"]).getACall() }
override DataFlow::Node getCommand() {
result.asCfgNode() = [node.getArg(0), node.getArgByName("command")]
result = [this.getArg(0), this.getArgByName("command")]
}
}
}
@@ -159,7 +159,7 @@ private module FabricV2 {
}
override DataFlow::Node getCommand() {
result.asCfgNode() = [node.getArg(0), node.getArgByName("command")]
result = [this.getArg(0), this.getArgByName("command")]
}
}
@@ -239,7 +239,7 @@ private module FabricV2 {
FabricGroupRunCall() { this = fabric::group::Group::subclassInstanceRunMethod().getACall() }
override DataFlow::Node getCommand() {
result.asCfgNode() = [node.getArg(0), node.getArgByName("command")]
result = [this.getArg(0), this.getArgByName("command")]
}
}

View File

@@ -81,7 +81,7 @@ private module Invoke {
}
override DataFlow::Node getCommand() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("command")]
result in [this.getArg(0), this.getArgByName("command")]
}
}
}

View File

@@ -123,6 +123,6 @@ private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode {
ExecuteCall() { this.getFunction() = execute() }
override DataFlow::Node getSql() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("sql")]
result in [this.getArg(0), this.getArgByName("sql")]
}
}

View File

@@ -38,9 +38,7 @@ private module Stdlib {
private class OsPathNormpathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
OsPathNormpathCall() { this = os::path().getMember("normpath").getACall() }
DataFlow::Node getPathArg() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("path")]
}
DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
}
/** An additional taint step for calls to `os.path.normpath` */
@@ -60,9 +58,7 @@ private module Stdlib {
private class OsPathAbspathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
OsPathAbspathCall() { this = os::path().getMember("abspath").getACall() }
DataFlow::Node getPathArg() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("path")]
}
DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
}
/** An additional taint step for calls to `os.path.abspath` */
@@ -82,9 +78,7 @@ private module Stdlib {
private class OsPathRealpathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
OsPathRealpathCall() { this = os::path().getMember("realpath").getACall() }
DataFlow::Node getPathArg() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("path")]
}
DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
}
/** An additional taint step for calls to `os.path.realpath` */
@@ -104,7 +98,7 @@ private module Stdlib {
private class OsSystemCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
OsSystemCall() { this = os().getMember("system").getACall() }
override DataFlow::Node getCommand() { result.asCfgNode() = node.getArg(0) }
override DataFlow::Node getCommand() { result = this.getArg(0) }
}
/**
@@ -124,10 +118,10 @@ private module Stdlib {
}
override DataFlow::Node getCommand() {
result.asCfgNode() = node.getArg(0)
result = this.getArg(0)
or
not name = "popen" and
result.asCfgNode() = node.getArgByName("cmd")
result = this.getArgByName("cmd")
}
}
@@ -143,7 +137,7 @@ private module Stdlib {
)
}
override DataFlow::Node getCommand() { result.asCfgNode() = node.getArg(0) }
override DataFlow::Node getCommand() { result = this.getArg(0) }
}
/**
@@ -160,7 +154,7 @@ private module Stdlib {
)
}
override DataFlow::Node getCommand() { result.asCfgNode() = node.getArg(1) }
override DataFlow::Node getCommand() { result = this.getArg(1) }
}
/**
@@ -170,7 +164,7 @@ private module Stdlib {
private class OsPosixSpawnCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
OsPosixSpawnCall() { this = os().getMember(["posix_spawn", "posix_spawnp"]).getACall() }
override DataFlow::Node getCommand() { result.asCfgNode() = node.getArg(0) }
override DataFlow::Node getCommand() { result = this.getArg(0) }
}
/** An additional taint step for calls to `os.path.join` */
@@ -204,22 +198,22 @@ private module Stdlib {
}
/** Gets the ControlFlowNode for the `args` argument, if any. */
private ControlFlowNode get_args_arg() { result in [node.getArg(0), node.getArgByName("args")] }
private DataFlow::Node get_args_arg() { result in [this.getArg(0), this.getArgByName("args")] }
/** Gets the ControlFlowNode for the `shell` argument, if any. */
private ControlFlowNode get_shell_arg() {
result in [node.getArg(8), node.getArgByName("shell")]
private DataFlow::Node get_shell_arg() {
result in [this.getArg(8), this.getArgByName("shell")]
}
private boolean get_shell_arg_value() {
not exists(this.get_shell_arg()) and
result = false
or
exists(ControlFlowNode shell_arg | shell_arg = this.get_shell_arg() |
result = shell_arg.getNode().(ImmutableLiteral).booleanValue()
exists(DataFlow::Node shell_arg | shell_arg = this.get_shell_arg() |
result = shell_arg.asCfgNode().getNode().(ImmutableLiteral).booleanValue()
or
// TODO: Track the "shell" argument to determine possible values
not shell_arg.getNode() instanceof ImmutableLiteral and
not shell_arg.asCfgNode().getNode() instanceof ImmutableLiteral and
(
result = true
or
@@ -229,16 +223,16 @@ private module Stdlib {
}
/** Gets the ControlFlowNode for the `executable` argument, if any. */
private ControlFlowNode get_executable_arg() {
result in [node.getArg(2), node.getArgByName("executable")]
private DataFlow::Node get_executable_arg() {
result in [this.getArg(2), this.getArgByName("executable")]
}
override DataFlow::Node getCommand() {
// TODO: Track arguments ("args" and "shell")
// TODO: Handle using `args=["sh", "-c", <user-input>]`
result.asCfgNode() = this.get_executable_arg()
result = this.get_executable_arg()
or
exists(ControlFlowNode arg_args, boolean shell |
exists(DataFlow::Node arg_args, boolean shell |
arg_args = get_args_arg() and
shell = get_shell_arg_value()
|
@@ -254,14 +248,14 @@ private module Stdlib {
// run, so if we're able to, we only mark the first element as the command
// (and not the arguments to the command).
//
result.asCfgNode() = arg_args.(SequenceNode).getElement(0)
result.asCfgNode() = arg_args.asCfgNode().(SequenceNode).getElement(0)
or
// Either the "args" argument is not a sequence (which is valid) or we where
// just not able to figure it out. Simply mark the "args" argument as the
// command.
//
not arg_args instanceof SequenceNode and
result.asCfgNode() = arg_args
not arg_args.asCfgNode() instanceof SequenceNode and
result = arg_args
)
)
}
@@ -334,9 +328,7 @@ private module Stdlib {
)
}
override DataFlow::Node getCommand() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("cmd")]
}
override DataFlow::Node getCommand() { result in [this.getArg(0), this.getArgByName("cmd")] }
}
// ---------------------------------------------------------------------------
@@ -352,9 +344,7 @@ private module Stdlib {
private class PlatformPopenCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
PlatformPopenCall() { this = platform().getMember("popen").getACall() }
override DataFlow::Node getCommand() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("cmd")]
}
override DataFlow::Node getCommand() { result in [this.getArg(0), this.getArgByName("cmd")] }
}
// ---------------------------------------------------------------------------
@@ -442,7 +432,7 @@ private module Stdlib {
this = base64().getMember(name).getACall()
}
override DataFlow::Node getAnInput() { result.asCfgNode() = node.getArg(0) }
override DataFlow::Node getAnInput() { result = this.getArg(0) }
override DataFlow::Node getOutput() { result = this }
@@ -476,7 +466,7 @@ private module Stdlib {
override predicate mayExecuteInput() { none() }
override DataFlow::Node getAnInput() { result.asCfgNode() = node.getArg(0) }
override DataFlow::Node getAnInput() { result = this.getArg(0) }
override DataFlow::Node getOutput() { result = this }

View File

@@ -431,7 +431,7 @@ private module Tornado {
}
override DataFlow::Node getRedirectLocation() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("url")]
result in [this.getArg(0), this.getArgByName("url")]
}
override DataFlow::Node getBody() { none() }
@@ -452,9 +452,7 @@ private module Tornado {
this.getFunction() = tornado::web::RequestHandler::writeMethod()
}
override DataFlow::Node getBody() {
result.asCfgNode() in [node.getArg(0), node.getArgByName("chunk")]
}
override DataFlow::Node getBody() { result in [this.getArg(0), this.getArgByName("chunk")] }
override string getMimetypeDefault() { result = "text/html" }

View File

@@ -88,7 +88,7 @@ module Werkzeug {
or
// getlist -> getlist()
nodeFrom = werkzeug::datastructures::MultiDict::getlist() and
nodeTo.asCfgNode().(CallNode).getFunction() = nodeFrom.asCfgNode()
nodeTo.(DataFlow::CallCfgNode).getFunction() = nodeFrom
}
}