Skip to content

Commit d514fc5

Browse files
committed
Python: Add responses to bottle framework support.
1 parent 8d525e5 commit d514fc5

File tree

7 files changed

+103
-3
lines changed

7 files changed

+103
-3
lines changed

python/ql/src/semmle/python/web/HttpResponse.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ import semmle.python.web.flask.Response
33
import semmle.python.web.pyramid.Response
44
import semmle.python.web.tornado.Response
55
import semmle.python.web.twisted.Response
6+
import semmle.python.web.bottle.Response

python/ql/src/semmle/python/web/bottle/Request.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ class BottleFormsDict extends TaintKind {
4949
}
5050

5151
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
52-
/* Cannot use `getTaintOfAttribute()` as it doesn't bind name */
52+
/* Cannot use `getTaintOfAttribute(name)` as it wouldn't bind `name` */
5353
exists(string name |
54-
tonode = fromnode.(AttrNode).getObject(name) and
54+
fromnode = tonode.(AttrNode).getObject(name) and
5555
result instanceof UntrustedStringKind
5656
|
5757
name != "get" and name != "getunicode" and name != "getall"
@@ -108,7 +108,7 @@ class BottleRequestParameter extends TaintSource {
108108
}
109109

110110
override string toString() {
111-
result = "flask.request.args"
111+
result = "bottle handler function argument"
112112
}
113113

114114
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import python
2+
3+
import semmle.python.security.TaintTracking
4+
import semmle.python.security.strings.Untrusted
5+
import semmle.python.web.Http
6+
import semmle.python.web.bottle.General
7+
8+
9+
/** A django.http.response.Response object
10+
* This isn't really a "taint", but we use the value tracking machinery to
11+
* track the flow of response objects.
12+
*/
13+
class BottleResponse extends TaintKind {
14+
15+
BottleResponse() {
16+
this = "bottle.response"
17+
}
18+
19+
}
20+
21+
private Object theBottleResponseObject() {
22+
result = theBottleModule().getAttribute("request")
23+
}
24+
25+
class BottleResponseBodyAssignment extends TaintSink {
26+
27+
BottleResponseBodyAssignment() {
28+
exists(DefinitionNode lhs |
29+
lhs.getValue() = this and
30+
lhs.(AttrNode).getObject("body").refersTo(theBottleResponseObject())
31+
)
32+
}
33+
34+
override predicate sinks(TaintKind kind) {
35+
kind instanceof StringKind
36+
}
37+
38+
}
39+
40+
class BottleHandlerFunctionResult extends TaintSink {
41+
42+
BottleHandlerFunctionResult() {
43+
exists(BottleRoute route, Return ret |
44+
ret.getScope() = route.getFunction() and
45+
ret.getValue().getAFlowNode() = this
46+
)
47+
}
48+
49+
override predicate sinks(TaintKind kind) {
50+
kind instanceof UntrustedStringKind
51+
}
52+
53+
override string toString() {
54+
result = "bottle handler function result"
55+
}
56+
57+
}
58+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.py:9 | BinaryExpr | externally controlled string |
2+
| test.py:13 | BinaryExpr | externally controlled string |
3+
| test.py:19 | BinaryExpr | externally controlled string |
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
import python
3+
4+
import semmle.python.web.HttpRequest
5+
import semmle.python.web.HttpResponse
6+
import semmle.python.security.strings.Untrusted
7+
8+
from TaintSink sink, TaintKind kind
9+
where sink.sinks(kind)
10+
select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
| ../../../query-tests/Security/lib/bottle.py:64 | LocalRequest() | bottle.request |
2+
| ../../../query-tests/Security/lib/bottle.py:64 | request | bottle.request |
3+
| test.py:3 | ImportMember | bottle.request |
4+
| test.py:3 | request | bottle.request |
5+
| test.py:8 | name | externally controlled string |
6+
| test.py:9 | BinaryExpr | externally controlled string |
7+
| test.py:9 | name | externally controlled string |
8+
| test.py:12 | name | externally controlled string |
9+
| test.py:13 | BinaryExpr | externally controlled string |
10+
| test.py:13 | name | externally controlled string |
11+
| test.py:18 | Attribute | bottle.FormsDict |
12+
| test.py:18 | Attribute | externally controlled string |
13+
| test.py:18 | request | bottle.request |
14+
| test.py:19 | BinaryExpr | externally controlled string |
15+
| test.py:19 | name | externally controlled string |
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
import python
3+
4+
5+
import semmle.python.web.HttpRequest
6+
import semmle.python.web.HttpResponse
7+
import semmle.python.security.strings.Untrusted
8+
9+
10+
from TaintedNode node
11+
12+
select node.getLocation().toString(), node.getNode().getNode().toString(), node.getTaintKind()
13+

0 commit comments

Comments
 (0)