Skip to content

Commit 579de0c

Browse files
committed
Python: Remove getResponse and do manual taint steps
1 parent f8fc583 commit 579de0c

File tree

3 files changed

+40
-35
lines changed

3 files changed

+40
-35
lines changed

python/ql/lib/semmle/python/Concepts.qll

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -822,9 +822,6 @@ module HTTP {
822822
* extend `Request::Range` instead.
823823
*/
824824
class Request extends DataFlow::Node instanceof Request::Range {
825-
/** Gets a node that provides the response to this request. */
826-
DataFlow::Node getResponse() { result = super.getResponse() }
827-
828825
/**
829826
* Gets a node that contributes to the URL of the request.
830827
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
@@ -857,9 +854,6 @@ module HTTP {
857854
* extend `Request` instead.
858855
*/
859856
abstract class Range extends DataFlow::Node {
860-
/** Gets a node that provides the response to this request. */
861-
abstract DataFlow::Node getResponse();
862-
863857
/**
864858
* Gets a node that contributes to the URL of the request.
865859
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
@@ -881,18 +875,6 @@ module HTTP {
881875
);
882876
}
883877
}
884-
885-
/**
886-
* Additional taint step from a client request with user-controlled URL to the response.
887-
*/
888-
private class HttpClientRequestAdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
889-
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
890-
exists(Request req |
891-
nodeFrom = req.getAUrlPart() and
892-
nodeTo = req.getResponse()
893-
)
894-
}
895-
}
896878
// TODO: investigate whether we should treat responses to client requests as
897879
// remote-flow-sources in general.
898880
}

python/ql/lib/semmle/python/frameworks/Requests.qll

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ private import python
1010
private import semmle.python.Concepts
1111
private import semmle.python.ApiGraphs
1212
private import semmle.python.dataflow.new.DataFlow
13+
private import semmle.python.dataflow.new.TaintTracking
1314
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
1415
private import semmle.python.frameworks.Stdlib
1516

@@ -53,8 +54,6 @@ private module Requests {
5354
result = this.getArg(1)
5455
}
5556

56-
override DataFlow::Node getResponse() { result = this }
57-
5857
/** Gets the `verify` argument to this outgoing requests call. */
5958
DataFlow::Node getVerifyArg() { result = this.getArgByName("verify") }
6059

@@ -70,6 +69,16 @@ private module Requests {
7069
override string getFramework() { result = "requests" }
7170
}
7271

72+
/**
73+
* Extra taint propagation for outgoing requests calls,
74+
* to ensure that responses to user-controlled URL are tainted.
75+
*/
76+
private class OutgoingRequestCallTaintStep extends TaintTracking::AdditionalTaintStep {
77+
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
78+
nodeFrom = nodeTo.(OutgoingRequestCall).getAUrlPart()
79+
}
80+
}
81+
7382
/** Gets a back-reference to the verify argument `arg`. */
7483
private DataFlow::TypeTrackingNode verifyArgBacktracker(
7584
DataFlow::TypeBackTracker t, DataFlow::Node arg
@@ -120,7 +129,7 @@ private module Requests {
120129

121130
/** Return value from making a reuqest. */
122131
private class RequestReturnValue extends InstanceSource, DataFlow::Node {
123-
RequestReturnValue() { this = any(OutgoingRequestCall c).getResponse() }
132+
RequestReturnValue() { this = any(OutgoingRequestCall c) }
124133
}
125134

126135
/** Gets a reference to an instance of `requests.models.Response`. */

python/ql/lib/semmle/python/frameworks/Stdlib.qll

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,22 +2165,10 @@ private module StdlibPrivate {
21652165
private class RequestCall extends HTTP::Client::Request::Range, DataFlow::MethodCallNode {
21662166
RequestCall() { this.calls(instance(_), ["request", "_send_request", "putrequest"]) }
21672167

2168-
override DataFlow::Node getResponse() {
2169-
// TODO: this does not seem like the right abstraction, to allow for nice path-explanations
2170-
//
2171-
// For nice path-explanation, we would like either
2172-
// 1: tainting instance
2173-
// 1a. host on object creation -> obj
2174-
// 1b. url on request call -> obj
2175-
// 2. obj -> obj.getresponse()
2176-
//
2177-
// For now, that's really all we use the `getResponse` predicate for.
2178-
result.(HttpConnectionGetResponseCall).getObject().getALocalSource() =
2179-
this.getObject().getALocalSource()
2180-
}
2168+
DataFlow::Node getUrlArg() { result in [this.getArg(1), this.getArgByName("url")] }
21812169

21822170
override DataFlow::Node getAUrlPart() {
2183-
result in [this.getArg(1), this.getArgByName("url")]
2171+
result = this.getUrlArg()
21842172
or
21852173
this.getObject() = instance(result)
21862174
}
@@ -2202,6 +2190,32 @@ private module StdlibPrivate {
22022190
HTTPResponse::InstanceSource {
22032191
HttpConnectionGetResponseCall() { this.calls(instance(_), "getresponse") }
22042192
}
2193+
2194+
/**
2195+
* Extra taint propagation for `http.client.HTTPConnection`,
2196+
* to ensure that responses to user-controlled URL are tainted.
2197+
*/
2198+
private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
2199+
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
2200+
// constructor
2201+
exists(InstanceSource instanceSource |
2202+
nodeFrom = instanceSource.getHostArgument() and
2203+
nodeTo = instanceSource
2204+
)
2205+
or
2206+
// a request method
2207+
exists(RequestCall call |
2208+
nodeFrom = call.getUrlArg() and
2209+
nodeTo.(DataFlow::PostUpdateNode).getPreUpdateNode() = call.getObject()
2210+
)
2211+
or
2212+
// `getresponse` call
2213+
exists(HttpConnectionGetResponseCall call |
2214+
nodeFrom = call.getObject() and
2215+
nodeTo = call
2216+
)
2217+
}
2218+
}
22052219
}
22062220

22072221
/**

0 commit comments

Comments
 (0)