forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRequests.qll
More file actions
171 lines (149 loc) · 6.02 KB
/
Copy pathRequests.qll
File metadata and controls
171 lines (149 loc) · 6.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**
* Provides classes modeling security-relevant aspects of the `requests` PyPI package.
*
* See
* - https://pypi.org/project/requests/
* - https://docs.python-requests.org/en/latest/
*/
private import python
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
private import semmle.python.frameworks.Stdlib
/**
* INTERNAL: Do not use.
*
* Provides models for the `requests` PyPI package.
*
* See
* - https://pypi.org/project/requests/
* - https://docs.python-requests.org/en/latest/
*/
private module Requests {
private class OutgoingRequestCall extends HTTP::Client::Request::Range, DataFlow::CallCfgNode {
string methodName;
OutgoingRequestCall() {
methodName in [HTTP::httpVerbLower(), "request"] and
(
this = API::moduleImport("requests").getMember(methodName).getACall()
or
exists(API::Node moduleExporting, API::Node sessionInstance |
moduleExporting in [
API::moduleImport("requests"), //
API::moduleImport("requests").getMember("sessions")
] and
sessionInstance = moduleExporting.getMember(["Session", "session"]).getReturn()
|
this = sessionInstance.getMember(methodName).getACall()
)
)
}
override DataFlow::Node getAUrlPart() {
result = this.getArgByName("url")
or
not methodName = "request" and
result = this.getArg(0)
or
methodName = "request" and
result = this.getArg(1)
}
/** Gets the `verify` argument to this outgoing requests call. */
DataFlow::Node getVerifyArg() { result = this.getArgByName("verify") }
override predicate disablesCertificateValidation(
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
) {
disablingNode = this.getVerifyArg() and
argumentOrigin = verifyArgBacktracker(disablingNode) and
argumentOrigin.asExpr().(ImmutableLiteral).booleanValue() = false and
not argumentOrigin.asExpr() instanceof None
}
override string getFramework() { result = "requests" }
}
/**
* Extra taint propagation for outgoing requests calls,
* to ensure that responses to user-controlled URL are tainted.
*/
private class OutgoingRequestCallTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
nodeFrom = nodeTo.(OutgoingRequestCall).getAUrlPart()
}
}
/** Gets a back-reference to the verify argument `arg`. */
private DataFlow::TypeTrackingNode verifyArgBacktracker(
DataFlow::TypeBackTracker t, DataFlow::Node arg
) {
t.start() and
arg = any(OutgoingRequestCall c).getVerifyArg() and
result = arg.getALocalSource()
or
exists(DataFlow::TypeBackTracker t2 | result = verifyArgBacktracker(t2, arg).backtrack(t2, t))
}
/** Gets a back-reference to the verify argument `arg`. */
private DataFlow::LocalSourceNode verifyArgBacktracker(DataFlow::Node arg) {
result = verifyArgBacktracker(DataFlow::TypeBackTracker::end(), arg)
}
// ---------------------------------------------------------------------------
// Response
// ---------------------------------------------------------------------------
/**
* Provides models for the `requests.models.Response` class
*
* See https://docs.python-requests.org/en/latest/api/#requests.Response.
*/
module Response {
/** Gets a reference to the `requests.models.Response` class. */
private API::Node classRef() {
result = API::moduleImport("requests").getMember("models").getMember("Response")
or
result = API::moduleImport("requests").getMember("Response")
}
/**
* A source of instances of `requests.models.Response`, extend this class to model new instances.
*
* This can include instantiations of the class, return values from function
* calls, or a special parameter that will be set when functions are called by an external
* library.
*
* Use the predicate `Response::instance()` to get references to instances of `requests.models.Response`.
*/
abstract class InstanceSource extends DataFlow::LocalSourceNode { }
/** A direct instantiation of `requests.models.Response`. */
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
ClassInstantiation() { this = classRef().getACall() }
}
/** Return value from making a reuqest. */
private class RequestReturnValue extends InstanceSource, DataFlow::Node {
RequestReturnValue() { this = any(OutgoingRequestCall c) }
}
/** Gets a reference to an instance of `requests.models.Response`. */
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
t.start() and
result instanceof InstanceSource
or
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
}
/** Gets a reference to an instance of `requests.models.Response`. */
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
/**
* Taint propagation for `requests.models.Response`.
*/
private class InstanceTaintSteps extends InstanceTaintStepsHelper {
InstanceTaintSteps() { this = "requests.models.Response" }
override DataFlow::Node getInstance() { result = instance() }
override string getAttributeName() {
result in ["text", "content", "raw", "links", "cookies", "headers"]
}
override string getMethodName() { result in ["json", "iter_content", "iter_lines"] }
override string getAsyncMethodName() { none() }
}
/** An attribute read that is a file-like instance. */
private class FileLikeInstances extends Stdlib::FileLikeObject::InstanceSource {
FileLikeInstances() {
this.(DataFlow::AttrRead).getObject() = instance() and
this.(DataFlow::AttrRead).getAttributeName() = "raw"
}
}
}
}