Merge pull request #1203 from markshannon/python-taint-tracking-configuration-2

Python: Use taint tracking configuration for queries.
This commit is contained in:
Taus
2019-04-09 10:01:35 +02:00
committed by GitHub
26 changed files with 118 additions and 44 deletions

View File

@@ -25,6 +25,17 @@ import semmle.python.web.HttpResponse
/* Flow */
import semmle.python.security.strings.Untrusted
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
class ReflectedXssConfiguration extends TaintTracking::Configuration {
ReflectedXssConfiguration() { this = "Reflected XSS configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSink(TaintTracking::Sink sink) { sink instanceof HttpResponseTaintSink }
}
from ReflectedXssConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "Cross-site scripting vulnerability due to $@.", src.getSource(), "user-provided value"

View File

@@ -22,7 +22,16 @@ import semmle.python.security.injection.Sql
import semmle.python.web.django.Db
import semmle.python.web.django.Model
class SQLInjectionConfiguration extends TaintTracking::Configuration {
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
SQLInjectionConfiguration() { this = "SQL injection configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSink(TaintTracking::Sink sink) { sink instanceof SqlInjectionSink }
}
from SQLInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "This SQL query depends on $@.", src.getSource(), "a user-provided value"

View File

@@ -23,7 +23,17 @@ import semmle.python.web.HttpRequest
/* Sinks */
import semmle.python.security.injection.Exec
class CodeInjectionConfiguration extends TaintTracking::Configuration {
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
CodeInjectionConfiguration() { this = "Code injection configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSink(TaintTracking::Sink sink) { sink instanceof StringEvaluationNode }
}
from CodeInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "$@ flows to here and is interpreted as code.", src.getSource(), "User-provided value"

View File

@@ -24,7 +24,16 @@ import semmle.python.security.injection.Pickle
import semmle.python.security.injection.Marshal
import semmle.python.security.injection.Yaml
class UnsafeDeserializationConfiguration extends TaintTracking::Configuration {
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
UnsafeDeserializationConfiguration() { this = "Unsafe deserialization configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSink(TaintTracking::Sink sink) { sink instanceof DeserializationSink }
}
from UnsafeDeserializationConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "Deserializing of $@.", src.getSource(), "untrusted input"

View File

@@ -0,0 +1,4 @@
import python
import semmle.python.security.TaintTracking
abstract class SqlInjectionSink extends TaintSink {}

View File

@@ -1668,3 +1668,4 @@ private predicate sequence_call(ControlFlowNode fromnode, CallNode tonode) {
cls.refersTo(theSetType())
)
}

View File

@@ -0,0 +1,14 @@
import python
import semmle.python.security.TaintTracking
/** `pickle.loads(untrusted)` vulnerability. */
abstract class DeserializationSink extends TaintSink {
bindingset[this]
DeserializationSink() {
this = this
}
}

View File

@@ -9,6 +9,7 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.injection.Deserialization
private FunctionObject marshalLoads() {
@@ -18,7 +19,7 @@ private FunctionObject marshalLoads() {
/** A taint sink that is potentially vulnerable to malicious marshaled objects.
* The `vuln` in `marshal.loads(vuln)`. */
class UnmarshalingNode extends TaintSink {
class UnmarshalingNode extends DeserializationSink {
override string toString() { result = "unmarshaling vulnerability" }

View File

@@ -9,6 +9,7 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.injection.Deserialization
private ModuleObject pickleModule() {
@@ -24,7 +25,7 @@ private FunctionObject pickleLoads() {
}
/** `pickle.loads(untrusted)` vulnerability. */
class UnpicklingNode extends TaintSink {
class UnpicklingNode extends DeserializationSink {
override string toString() { result = "unpickling untrusted data" }

View File

@@ -9,6 +9,7 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.SQL
private StringObject first_part(ControlFlowNode command) {
@@ -48,11 +49,10 @@ abstract class DbCursor extends TaintKind {
}
/** A part of a string that appears to be a SQL command and is thus
* vulnerable to malicious input.
*/
class SimpleSqlStringInjection extends TaintSink {
class SimpleSqlStringInjection extends SqlInjectionSink {
override string toString() { result = "simple SQL string injection" }
@@ -76,7 +76,7 @@ abstract class DbConnectionSource extends TaintSource {
/** A taint sink that is vulnerable to malicious SQL queries.
* The `vuln` in `db.connection.execute(vuln)` and similar.
*/
class DbConnectionExecuteArgument extends TaintSink {
class DbConnectionExecuteArgument extends SqlInjectionSink {
override string toString() { result = "db.connection.execute" }

View File

@@ -8,6 +8,7 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.injection.Deserialization
private ModuleObject xmlElementTreeModule() {
@@ -73,7 +74,7 @@ class ExternalXmlString extends ExternalStringKind {
/** A call to an XML library function that is potentially vulnerable to a
* specially crafted XML string.
*/
class XmlLoadNode extends TaintSink {
class XmlLoadNode extends DeserializationSink {
override string toString() { result = "xml.load vulnerability" }

View File

@@ -10,6 +10,7 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.injection.Deserialization
private FunctionObject yamlLoad() {
@@ -17,7 +18,7 @@ private FunctionObject yamlLoad() {
}
/** `yaml.load(untrusted)` vulnerability. */
class YamlLoadNode extends TaintSink {
class YamlLoadNode extends DeserializationSink {
override string toString() { result = "yaml.load vulnerability" }

View File

@@ -3,11 +3,7 @@ import semmle.python.security.TaintTracking
import semmle.python.security.strings.External
/** Generic taint source from a http request */
abstract class SimpleHttpRequestTaintSource extends TaintSource {
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExternalStringKind
}
abstract class HttpRequestTaintSource extends TaintSource {
}
@@ -89,3 +85,11 @@ class UntrustedCookie extends TaintKind {
}
/** Generic taint sink in a http response */
abstract class HttpResponseTaintSink extends TaintSink {
override predicate sinks(TaintKind kind) {
kind instanceof ExternalStringKind
}
}

View File

@@ -22,7 +22,7 @@ private Object theBottleResponseObject() {
result = theBottleModule().attr("response")
}
class BottleResponseBodyAssignment extends TaintSink {
class BottleResponseBodyAssignment extends HttpResponseTaintSink {
BottleResponseBodyAssignment() {
exists(DefinitionNode lhs |
@@ -37,7 +37,7 @@ class BottleResponseBodyAssignment extends TaintSink {
}
class BottleHandlerFunctionResult extends TaintSink {
class BottleHandlerFunctionResult extends HttpResponseTaintSink {
BottleHandlerFunctionResult() {
exists(BottleRoute route, Return ret |

View File

@@ -7,7 +7,7 @@ import semmle.python.web.cherrypy.General
class CherryPyExposedFunctionResult extends TaintSink {
class CherryPyExposedFunctionResult extends HttpResponseTaintSink {
CherryPyExposedFunctionResult() {
exists(Return ret |

View File

@@ -46,7 +46,7 @@ ClassObject theDjangoRawSqlClass() {
* allows arbitrary SQL statements to be executed, which is a security risk.
*/
class DjangoRawSqlSink extends TaintSink {
class DjangoRawSqlSink extends SqlInjectionSink {
DjangoRawSqlSink() {
exists(CallNode call |
call = theDjangoRawSqlClass().getACall() and

View File

@@ -3,6 +3,7 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.Http
import semmle.python.security.injection.Sql
/** A django model class */
class DjangoModel extends ClassObject {
@@ -68,7 +69,7 @@ class DjangoModelObjects extends TaintSource {
}
/** A write to a field of a django model, which is a vulnerable to external data. */
class DjangoModelFieldWrite extends TaintSink {
class DjangoModelFieldWrite extends SqlInjectionSink {
DjangoModelFieldWrite() {
exists(AttrNode attr, DjangoModel model |
@@ -111,7 +112,7 @@ class DjangoModelDirectObjectReference extends TaintSink {
* to be sent to the database, which is a security risk.
*/
class DjangoModelRawCall extends TaintSink {
class DjangoModelRawCall extends SqlInjectionSink {
DjangoModelRawCall() {
exists(CallNode raw_call, ControlFlowNode queryset |
@@ -136,7 +137,7 @@ class DjangoModelRawCall extends TaintSink {
*/
class DjangoModelExtraCall extends TaintSink {
class DjangoModelExtraCall extends SqlInjectionSink {
DjangoModelExtraCall() {
exists(CallNode extra_call, ControlFlowNode queryset |

View File

@@ -49,7 +49,7 @@ class DjangoQueryDict extends TaintKind {
}
abstract class DjangoRequestSource extends TaintSource {
abstract class DjangoRequestSource extends HttpRequestTaintSource {
override string toString() {
result = "Django request source"
@@ -144,7 +144,7 @@ class UrlRouting extends CallNode {
}
/** An argument specified in a url routing table */
class HttpRequestParameter extends TaintSource {
class HttpRequestParameter extends HttpRequestTaintSource {
HttpRequestParameter() {
exists(UrlRouting url |

View File

@@ -2,6 +2,7 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Basic
private import semmle.python.web.django.Shared
private import semmle.python.web.Http
/** A django.http.response.Response object
@@ -39,7 +40,7 @@ class DjangoResponseSource extends TaintSource {
}
/** A write to a django response, which is vulnerable to external data (xss) */
class DjangoResponseWrite extends TaintSink {
class DjangoResponseWrite extends HttpResponseTaintSink {
DjangoResponseWrite() {
exists(AttrNode meth, CallNode call |
@@ -60,7 +61,7 @@ class DjangoResponseWrite extends TaintSink {
}
/** An argument to initialization of a django response, which is vulnerable to external data (xss) */
class DjangoResponseContent extends TaintSink {
class DjangoResponseContent extends HttpResponseTaintSink {
DjangoResponseContent() {
exists(CallNode call, ClassObject cls |

View File

@@ -30,7 +30,7 @@ class FalconResponseParameter extends TaintSource {
}
class FalconResponseBodySink extends TaintSink {
class FalconResponseBodySink extends HttpResponseTaintSink {
FalconResponseBodySink() {
exists(AttrNode attr |

View File

@@ -16,7 +16,7 @@ private predicate flask_request_attr(AttrNode attr, string name) {
}
/** Source of external data from a flask request */
class FlaskRequestData extends SimpleHttpRequestTaintSource {
class FlaskRequestData extends HttpRequestTaintSource {
FlaskRequestData() {
not this instanceof FlaskRequestArgs and
@@ -27,6 +27,10 @@ class FlaskRequestData extends SimpleHttpRequestTaintSource {
)
}
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExternalStringKind
}
override string toString() {
result = "flask.request"
}
@@ -34,7 +38,7 @@ class FlaskRequestData extends SimpleHttpRequestTaintSource {
}
/** Source of dictionary whose values are externally controlled */
class FlaskRequestArgs extends TaintSource {
class FlaskRequestArgs extends HttpRequestTaintSource {
FlaskRequestArgs() {
exists(string attr |

View File

@@ -8,7 +8,7 @@ import semmle.python.web.flask.General
/** A flask response, which is vulnerable to any sort of
* http response malice. */
class FlaskRoutedResponse extends TaintSink {
class FlaskRoutedResponse extends HttpResponseTaintSink {
FlaskRoutedResponse() {
exists(PyFunctionObject response |
@@ -28,7 +28,7 @@ class FlaskRoutedResponse extends TaintSink {
}
class FlaskResponseArgument extends TaintSink {
class FlaskResponseArgument extends HttpResponseTaintSink {
FlaskResponseArgument() {
exists(CallNode call |

View File

@@ -5,10 +5,11 @@ import semmle.python.security.TaintTracking
import semmle.python.security.strings.Basic
private import semmle.python.web.pyramid.View
private import semmle.python.web.Http
/** A pyramid response, which is vulnerable to any sort of
* http response malice. */
class PyramidRoutedResponse extends TaintSink {
class PyramidRoutedResponse extends HttpResponseTaintSink {
PyramidRoutedResponse() {
exists(PyFunctionObject view |

View File

@@ -3,6 +3,7 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Basic
private import semmle.python.web.Http
import Tornado
@@ -30,7 +31,7 @@ class TornadoConnectionSource extends TaintSource {
}
class TornadoConnectionWrite extends TaintSink {
class TornadoConnectionWrite extends HttpResponseTaintSink {
override string toString() {
result = "tornado.connection.write"
@@ -52,7 +53,7 @@ class TornadoConnectionWrite extends TaintSink {
}
class TornadoHttpRequestHandlerWrite extends TaintSink {
class TornadoHttpRequestHandlerWrite extends HttpResponseTaintSink {
override string toString() {
result = "tornado.HttpRequesHandler.write"
@@ -72,7 +73,7 @@ class TornadoHttpRequestHandlerWrite extends TaintSink {
}
class TornadoHttpRequestHandlerRedirect extends TaintSink {
class TornadoHttpRequestHandlerRedirect extends HttpResponseTaintSink {
override string toString() {
result = "tornado.HttpRequesHandler.redirect"

View File

@@ -2,12 +2,12 @@ import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.Http
import TurboGears
class ControllerMethodReturnValue extends TaintSink {
class ControllerMethodReturnValue extends HttpResponseTaintSink {
ControllerMethodReturnValue() {
exists(TurboGearsControllerMethod m |
@@ -22,7 +22,7 @@ class ControllerMethodReturnValue extends TaintSink {
}
class ControllerMethodTemplatedReturnValue extends TaintSink {
class ControllerMethodTemplatedReturnValue extends HttpResponseTaintSink {
ControllerMethodTemplatedReturnValue() {
exists(TurboGearsControllerMethod m |

View File

@@ -30,7 +30,7 @@ class TwistedResponse extends TaintSink {
* object, which affects the properties of the subsequent response sent to this
* request.
*/
class TwistedRequestSetter extends TaintSink {
class TwistedRequestSetter extends HttpResponseTaintSink {
TwistedRequestSetter() {
exists(CallNode call, ControlFlowNode node, string name |
(