Merge pull request #2469 from RasmusWL/python-modernise-twisted-library

Python: modernise twisted library
This commit is contained in:
Taus
2019-12-18 13:55:50 +01:00
committed by GitHub
22 changed files with 225 additions and 76 deletions

View File

@@ -211,7 +211,7 @@ module Value {
}
/** Gets the `Value` for the integer constant `i`, if it exists.
* There will be no `Value` for most integers, but the following are
* There will be no `Value` for most integers, but the following are
* guaranteed to exist:
* * From zero to 511 inclusive.
* * All powers of 2 (up to 2**30)
@@ -486,6 +486,11 @@ class PythonFunctionValue extends FunctionValue {
)
}
/** Gets a control flow node corresponding to a return statement in this function */
ControlFlowNode getAReturnedNode() {
result = this.getScope().getAReturnValueFlowNode()
}
}
/** Class representing builtin functions, such as `len` or `print` */

View File

@@ -9,8 +9,8 @@ import semmle.python.web.flask.General
*/
class FlaskRoutedResponse extends HttpResponseTaintSink {
FlaskRoutedResponse() {
exists(PyFunctionObject response |
flask_routing(_, response.getFunction()) and
exists(PythonFunctionValue response |
flask_routing(_, response.getScope()) and
this = response.getAReturnedNode()
)
}

View File

@@ -11,8 +11,8 @@ private import semmle.python.web.Http
*/
class PyramidRoutedResponse extends HttpResponseTaintSink {
PyramidRoutedResponse() {
exists(PyFunctionObject view |
is_pyramid_view_function(view.getFunction()) and
exists(PythonFunctionValue view |
is_pyramid_view_function(view.getScope()) and
this = view.getAReturnedNode()
)
}

View File

@@ -1,53 +1,35 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.web.Http
import Twisted
/** A twisted.web.http.Request object */
class TwistedRequest extends TaintKind {
TwistedRequest() {
this = "twisted.request.http.Request"
}
TwistedRequest() { this = "twisted.request.http.Request" }
override TaintKind getTaintOfAttribute(string name) {
result instanceof ExternalStringSequenceDictKind and
(
name = "args"
)
name = "args"
or
result instanceof ExternalStringKind and
(
name = "uri"
)
name = "uri"
}
override TaintKind getTaintOfMethodResult(string name) {
(
name = "getHeader" or
name = "getCookie" or
name = "getUser" or
name = "getPassword"
) and
result instanceof ExternalStringKind
(
name = "getHeader" or
name = "getCookie" or
name = "getUser" or
name = "getPassword"
) and
result instanceof ExternalStringKind
}
}
class TwistedRequestSource extends TaintSource {
TwistedRequestSource() { isTwistedRequestInstance(this) }
TwistedRequestSource() {
isTwistedRequestInstance(this)
}
override string toString() {
result = "Twisted request source"
}
override predicate isSourceOf(TaintKind kind) {
kind instanceof TwistedRequest
}
override string toString() { result = "Twisted request source" }
override predicate isSourceOf(TaintKind kind) { kind instanceof TwistedRequest }
}

View File

@@ -1,5 +1,4 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.web.Http
import semmle.python.security.strings.Basic
@@ -8,7 +7,7 @@ import Request
class TwistedResponse extends TaintSink {
TwistedResponse() {
exists(PyFunctionObject func, string name |
exists(PythonFunctionValue func, string name, Return ret |
isKnownRequestHandlerMethodName(name) and
name = func.getName() and
func = getTwistedRequestHandlerMethod(name) and
@@ -16,13 +15,9 @@ class TwistedResponse extends TaintSink {
)
}
override predicate sinks(TaintKind kind) {
kind instanceof ExternalStringKind
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() {
result = "Twisted response"
}
override string toString() { result = "Twisted response" }
}
/**
@@ -30,7 +25,7 @@ class TwistedResponse extends TaintSink {
* object, which affects the properties of the subsequent response sent to this
* request.
*/
class TwistedRequestSetter extends HttpResponseTaintSink {
class TwistedRequestSetter extends HttpResponseTaintSink {
TwistedRequestSetter() {
exists(CallNode call, ControlFlowNode node, string name |
(
@@ -44,11 +39,7 @@ class TwistedResponse extends TaintSink {
)
}
override predicate sinks(TaintKind kind) {
kind instanceof ExternalStringKind
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() {
result = "Twisted request setter"
}
}
override string toString() { result = "Twisted request setter" }
}

View File

@@ -1,20 +1,17 @@
import python
import semmle.python.security.TaintTracking
private ClassObject theTwistedHttpRequestClass() {
result = ModuleObject::named("twisted.web.http").attr("Request")
private ClassValue theTwistedHttpRequestClass() {
result = Value::named("twisted.web.http.Request")
}
private ClassObject theTwistedHttpResourceClass() {
result = ModuleObject::named("twisted.web.resource").attr("Resource")
private ClassValue theTwistedHttpResourceClass() {
result = Value::named("twisted.web.resource.Resource")
}
ClassObject aTwistedRequestHandlerClass() {
result.getASuperType() = theTwistedHttpResourceClass()
}
ClassValue aTwistedRequestHandlerClass() { result.getABaseType+() = theTwistedHttpResourceClass() }
FunctionObject getTwistedRequestHandlerMethod(string name) {
FunctionValue getTwistedRequestHandlerMethod(string name) {
result = aTwistedRequestHandlerClass().declaredAttribute(name)
}
@@ -24,29 +21,30 @@ predicate isKnownRequestHandlerMethodName(string name) {
name.matches("render_%")
}
/** Holds if `node` is likely to refer to an instance of the twisted
/**
* Holds if `node` is likely to refer to an instance of the twisted
* `Request` class.
*/
predicate isTwistedRequestInstance(NameNode node) {
node.refersTo(_, theTwistedHttpRequestClass(), _)
node.pointsTo().getClass() = theTwistedHttpRequestClass()
or
/* In points-to analysis cannot infer that a given object is an instance of
/*
* In points-to analysis cannot infer that a given object is an instance of
* the `twisted.web.http.Request` class, we also include any parameter
* called `request` that appears inside a subclass of a request handler
* class, and the appropriate arguments of known request handler methods.
*/
exists(Function func | func = node.getScope() |
func.getEnclosingScope().(Class).getClassObject() = aTwistedRequestHandlerClass()
) and
(
/* Any parameter called `request` */
node.getId() = "request" and
node.isParameter()
or
/* Any request parameter of a known request handler method */
exists(FunctionObject func | node.getScope() = func.getFunction() |
exists(Function func |
func = node.getScope() and
func.getEnclosingScope() = aTwistedRequestHandlerClass().getScope()
|
/* Any parameter called `request` */
node.getId() = "request" and
node.isParameter()
or
/* Any request parameter of a known request handler method */
isKnownRequestHandlerMethodName(func.getName()) and
node.getNode() = func.getFunction().getArg(1)
)
node.getNode() = func.getArg(1)
)
}

View File

@@ -0,0 +1,5 @@
| class MyRequestHandler1 | test.py:3 |
| class MyRequestHandler2 | test.py:23 |
| class MyRequestHandler3 | test.py:27 |
| class MyRequestHandler4 | test.py:38 |
| class MyRequestHandler5 | test.py:42 |

View File

@@ -0,0 +1,7 @@
import python
import semmle.python.TestUtils
import semmle.python.web.twisted.Twisted
from ClassValue cls
where cls = aTwistedRequestHandlerClass()
select cls.toString(), remove_library_prefix(cls.getScope().getLocation())

View File

@@ -0,0 +1,8 @@
| myrender | Function MyRequestHandler2.myrender | test.py:24 |
| render | Function MyRequestHandler1.render | test.py:4 |
| render | Function MyRequestHandler3.render | test.py:28 |
| render | Function MyRequestHandler4.render | test.py:39 |
| render | Function MyRequestHandler5.render | test.py:43 |
| render_GET | Function MyRequestHandler1.render_GET | test.py:9 |
| render_POST | Function MyRequestHandler1.render_POST | test.py:16 |
| render_POST | Function MyRequestHandler3.render_POST | test.py:31 |

View File

@@ -0,0 +1,7 @@
import python
import semmle.python.TestUtils
import semmle.python.web.twisted.Twisted
from FunctionValue func, string name
where func = getTwistedRequestHandlerMethod(name)
select name, func.toString(), remove_library_prefix(func.getScope().getLocation())

View File

@@ -0,0 +1,8 @@
| test.py:7 | response | externally controlled string |
| test.py:14 | response | externally controlled string |
| test.py:21 | response | externally controlled string |
| test.py:36 | do_stuff_with() | externally controlled string |
| test.py:40 | Str | externally controlled string |
| test.py:44 | Str | externally controlled string |
| test.py:45 | Str | externally controlled string |
| test.py:46 | Str | externally controlled string |

View File

@@ -0,0 +1,10 @@
import python
import semmle.python.web.HttpRequest
import semmle.python.web.HttpResponse
import semmle.python.security.strings.Untrusted
import semmle.python.TestUtils
from TaintSink sink, TaintKind kind
where sink.sinks(kind)
select remove_library_prefix(sink.getLocation()), sink.(ControlFlowNode).getNode().toString(), kind

View File

@@ -0,0 +1,8 @@
| test.py:4 | request | twisted.request.http.Request |
| test.py:9 | request | twisted.request.http.Request |
| test.py:16 | request | twisted.request.http.Request |
| test.py:24 | request | twisted.request.http.Request |
| test.py:28 | myrequest | twisted.request.http.Request |
| test.py:31 | postrequest | twisted.request.http.Request |
| test.py:39 | request | twisted.request.http.Request |
| test.py:43 | request | twisted.request.http.Request |

View File

@@ -0,0 +1,11 @@
import python
import semmle.python.TestUtils
import semmle.python.web.HttpRequest
import semmle.python.web.HttpResponse
import semmle.python.security.strings.Untrusted
from TaintSource src, TaintKind kind
where src.isSourceOf(kind)
select remove_library_prefix(src.getLocation()), src.(ControlFlowNode).getNode().toString(), kind

View File

@@ -0,0 +1,41 @@
| test.py:4 | request | twisted.request.http.Request |
| test.py:5 | Attribute | externally controlled string |
| test.py:5 | request | twisted.request.http.Request |
| test.py:6 | request | twisted.request.http.Request |
| test.py:9 | request | twisted.request.http.Request |
| test.py:10 | request | twisted.request.http.Request |
| test.py:11 | Attribute | externally controlled string |
| test.py:11 | x | twisted.request.http.Request |
| test.py:12 | request | twisted.request.http.Request |
| test.py:13 | request | twisted.request.http.Request |
| test.py:16 | request | twisted.request.http.Request |
| test.py:17 | Attribute | {[externally controlled string]} |
| test.py:17 | request | twisted.request.http.Request |
| test.py:18 | Attribute | {[externally controlled string]} |
| test.py:18 | Attribute() | [externally controlled string] |
| test.py:18 | request | twisted.request.http.Request |
| test.py:19 | Subscript | externally controlled string |
| test.py:19 | foo | [externally controlled string] |
| test.py:20 | quux | externally controlled string |
| test.py:24 | request | twisted.request.http.Request |
| test.py:25 | request | twisted.request.http.Request |
| test.py:28 | myrequest | twisted.request.http.Request |
| test.py:29 | myrequest | twisted.request.http.Request |
| test.py:31 | postrequest | twisted.request.http.Request |
| test.py:32 | Attribute() | externally controlled string |
| test.py:32 | postrequest | twisted.request.http.Request |
| test.py:33 | Attribute() | externally controlled string |
| test.py:33 | postrequest | twisted.request.http.Request |
| test.py:34 | Attribute() | externally controlled string |
| test.py:34 | postrequest | twisted.request.http.Request |
| test.py:35 | Attribute() | externally controlled string |
| test.py:35 | postrequest | twisted.request.http.Request |
| test.py:36 | w | externally controlled string |
| test.py:36 | x | externally controlled string |
| test.py:36 | y | externally controlled string |
| test.py:36 | z | externally controlled string |
| test.py:39 | request | twisted.request.http.Request |
| test.py:40 | request | twisted.request.http.Request |
| test.py:43 | request | twisted.request.http.Request |
| test.py:44 | request | twisted.request.http.Request |
| test.py:45 | request | twisted.request.http.Request |

View File

@@ -0,0 +1,11 @@
import python
import semmle.python.TestUtils
import semmle.python.web.HttpRequest
import semmle.python.web.HttpResponse
import semmle.python.security.strings.Untrusted
from TaintedNode node
select remove_library_prefix(node.getLocation()), node.getAstNode().toString(), node.getTaintKind()

View File

@@ -0,0 +1,2 @@
semmle-extractor-options: --max-import-depth=1 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -0,0 +1,51 @@
from twisted.web import resource
class MyRequestHandler1(resource.Resource):
def render(self, request):
foo(request.uri)
response = do_stuff_with(request)
return response
def render_GET(self, request):
x = request
bar(x.uri)
do_stuff_with(request)
response = do_stuff_with(request)
return response
def render_POST(self, request):
baz(request.args)
foo = request.args.get("baz")
quux = foo[5]
response = do_stuff_with(quux)
return response
class MyRequestHandler2(resource.Resource):
def myrender(self, request):
do_stuff_with(request)
class MyRequestHandler3(resource.Resource):
def render(self, myrequest):
do_stuff_with(myrequest)
def render_POST(self, postrequest):
x = postrequest.getHeader("someheader")
y = postrequest.getCookie("somecookie")
z = postrequest.getUser()
w = postrequest.getPassword()
return do_stuff_with(x,y,z,w)
class MyRequestHandler4(resource.Resource):
def render(self, request):
request.write("Foobar")
class MyRequestHandler5(resource.Resource):
def render(self, request):
request.setHeader("foo", "bar")
request.addCookie("key", "value")
return "This is my response."
class NotATwistedRequestHandler(object):
def render(self, request):
return do_stuff_with(request)

View File

@@ -0,0 +1,2 @@
class Request(object):
pass

View File

@@ -0,0 +1,2 @@
class Resource(object):
pass