Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f91e06b

Browse files
authored
Merge pull request #1002 from markshannon/python-cherrypy
Python: CherryPy support
2 parents b8b4216 + af26807 commit f91e06b

18 files changed

Lines changed: 300 additions & 2 deletions

File tree

change-notes/1.20/analysis-python.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ The API has been improved to declutter the global namespace and improve discover
4040

4141
* Added support for the `dill` pickle library.
4242
* Added support for the `bottle` web framework.
43+
* Added support for the `CherryPy` web framework.
4344
* Added support for the `falcon` web API framework.
4445
* Added support for the `turbogears` web framework.
4546

change-notes/1.20/support/python-frameworks.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Name, Category
22
Bottle, Web framework
3+
CherryPy, Web framework
34
Django, Web application framework
45
Falcon, Web API framework
56
Flask, Microframework

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,36 @@ class WsgiEnvironment extends TaintKind {
5656

5757
}
5858

59+
/** A standard morsel object from a HTTP request, a value in a cookie,
60+
* typically an instance of `http.cookies.Morsel` */
61+
class UntrustedMorsel extends TaintKind {
62+
63+
UntrustedMorsel() {
64+
this = "http.Morsel"
65+
}
66+
67+
68+
override TaintKind getTaintOfAttribute(string name) {
69+
result instanceof ExternalStringKind and
70+
(
71+
name = "value"
72+
)
73+
}
74+
75+
}
76+
77+
/** A standard cookie object from a HTTP request, typically an instance of `http.cookies.SimpleCookie` */
78+
class UntrustedCookie extends TaintKind {
79+
80+
UntrustedCookie() {
81+
this = "http.Cookie"
82+
}
83+
84+
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
85+
tonode.(SubscriptNode).getValue() = fromnode and
86+
result instanceof UntrustedMorsel
87+
}
88+
89+
}
90+
5991

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ import semmle.python.web.twisted.Request
66
import semmle.python.web.bottle.Request
77
import semmle.python.web.turbogears.Request
88
import semmle.python.web.falcon.Request
9+
import semmle.python.web.cherrypy.Request

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ import semmle.python.web.twisted.Response
66
import semmle.python.web.bottle.Response
77
import semmle.python.web.turbogears.Response
88
import semmle.python.web.falcon.Response
9+
import semmle.python.web.cherrypy.Response

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class BottleResponseBodyAssignment extends TaintSink {
3232
}
3333

3434
override predicate sinks(TaintKind kind) {
35-
kind instanceof UntrustedStringKind
35+
kind instanceof StringKind
3636
}
3737

3838
}
@@ -47,7 +47,7 @@ class BottleHandlerFunctionResult extends TaintSink {
4747
}
4848

4949
override predicate sinks(TaintKind kind) {
50-
kind instanceof UntrustedStringKind
50+
kind instanceof StringKind
5151
}
5252

5353
override string toString() {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import python
2+
import semmle.python.web.Http
3+
4+
module CherryPy {
5+
6+
FunctionObject expose() {
7+
result = ModuleObject::named("cherrypy").attr("expose")
8+
}
9+
10+
}
11+
12+
class CherryPyExposedFunction extends Function {
13+
14+
CherryPyExposedFunction() {
15+
this.getADecorator().refersTo(CherryPy::expose())
16+
or
17+
this.getADecorator().(Call).getFunc().refersTo(CherryPy::expose())
18+
}
19+
20+
}
21+
22+
class CherryPyRoute extends CallNode {
23+
24+
CherryPyRoute() {
25+
/* cherrypy.quickstart(root, script_name, config) */
26+
ModuleObject::named("cherrypy").attr("quickstart").(FunctionObject).getACall() = this
27+
or
28+
/* cherrypy.tree.mount(root, script_name, config) */
29+
this.getFunction().(AttrNode).getObject("mount").refersTo(ModuleObject::named("cherrypy").attr("tree"))
30+
}
31+
32+
ClassObject getAppClass() {
33+
this.getArg(0).refersTo(_, result, _)
34+
or
35+
this.getArgByName("root").refersTo(_, result, _)
36+
}
37+
38+
string getPath() {
39+
exists(StringObject path |
40+
result = path.getText()
41+
|
42+
this.getArg(1).refersTo(path)
43+
or
44+
this.getArgByName("script_name").refersTo(path)
45+
)
46+
}
47+
48+
Object getConfig() {
49+
this.getArg(2).refersTo(_, result, _)
50+
or
51+
this.getArgByName("config").refersTo(_, result, _)
52+
}
53+
54+
}
55+
56+
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import python
2+
3+
import semmle.python.security.TaintTracking
4+
import semmle.python.security.strings.Basic
5+
import semmle.python.web.Http
6+
import semmle.python.web.cherrypy.General
7+
8+
/** The cherrypy.request local-proxy object */
9+
class CherryPyRequest extends TaintKind {
10+
11+
CherryPyRequest() {
12+
this = "cherrypy.request"
13+
}
14+
15+
override TaintKind getTaintOfAttribute(string name) {
16+
name = "params" and result instanceof ExternalStringDictKind
17+
or
18+
name = "cookie" and result instanceof UntrustedCookie
19+
}
20+
21+
override TaintKind getTaintOfMethodResult(string name) {
22+
(
23+
name = "getHeader" or
24+
name = "getCookie" or
25+
name = "getUser" or
26+
name = "getPassword"
27+
) and
28+
result instanceof ExternalStringKind
29+
}
30+
31+
}
32+
33+
34+
class CherryPyExposedFunctionParameter extends TaintSource {
35+
36+
CherryPyExposedFunctionParameter() {
37+
exists(Parameter p |
38+
p = any(CherryPyExposedFunction f).getAnArg() and
39+
not p.isSelf() and
40+
p.asName().getAFlowNode() = this
41+
)
42+
}
43+
44+
override string toString() {
45+
result = "CherryPy handler function parameter"
46+
}
47+
48+
override predicate isSourceOf(TaintKind kind) {
49+
kind instanceof ExternalStringKind
50+
}
51+
52+
}
53+
54+
class CherryPyRequestSource extends TaintSource {
55+
56+
CherryPyRequestSource() {
57+
this.(ControlFlowNode).refersTo(ModuleObject::named("cherrypy").attr("request"))
58+
}
59+
60+
override predicate isSourceOf(TaintKind kind) {
61+
kind instanceof CherryPyRequest
62+
}
63+
64+
}
65+
66+
67+
68+
69+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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.cherrypy.General
7+
8+
9+
10+
class CherryPyExposedFunctionResult extends TaintSink {
11+
12+
CherryPyExposedFunctionResult() {
13+
exists(Return ret |
14+
ret.getScope() instanceof CherryPyExposedFunction and
15+
ret.getValue().getAFlowNode() = this
16+
)
17+
}
18+
19+
override predicate sinks(TaintKind kind) {
20+
kind instanceof StringKind
21+
}
22+
23+
override string toString() {
24+
result = "cherrypy handler function result"
25+
}
26+
27+
}
28+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| red.py:8 | Str | externally controlled string |
2+
| test.py:11 | BinaryExpr | externally controlled string |
3+
| test.py:17 | BinaryExpr | externally controlled string |

0 commit comments

Comments
 (0)