mirror of
https://github.com/github/codeql.git
synced 2026-05-04 13:15:21 +02:00
Python: Add modeling of http.client.HTTPResponse
This commit is contained in:
@@ -2091,6 +2091,187 @@ private module StdlibPrivate {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// http.client (Python 3)
|
||||
// httplib (Python 2)
|
||||
// ---------------------------------------------------------------------------
|
||||
/**
|
||||
* Provides models for the `http.client.HTTPConnection` and `HTTPSConnection` classes
|
||||
*
|
||||
* See
|
||||
* - https://docs.python.org/3.10/library/http.client.html#http.client.HTTPConnection
|
||||
* - https://docs.python.org/3.10/library/http.client.html#http.client.HTTPSConnection
|
||||
* - https://docs.python.org/2.7/library/httplib.html#httplib.HTTPConnection
|
||||
* - https://docs.python.org/2.7/library/httplib.html#httplib.HTTPSConnection
|
||||
*/
|
||||
module HTTPConnection {
|
||||
/** Gets a reference to the `http.client.HTTPConnection` class. */
|
||||
private API::Node classRef() {
|
||||
exists(string className | className in ["HTTPConnection", "HTTPSConnection"] |
|
||||
// Python 3
|
||||
result = API::moduleImport("http").getMember("client").getMember(className)
|
||||
or
|
||||
// Python 2
|
||||
result = API::moduleImport("httplib").getMember(className)
|
||||
or
|
||||
result =
|
||||
API::moduleImport("six").getMember("moves").getMember("http_client").getMember(className)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A source of instances of `http.client.HTTPConnection`, 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 `HTTPConnection::instance()` to get references to instances of `http.client.HTTPConnection`.
|
||||
*/
|
||||
abstract class InstanceSource extends DataFlow::LocalSourceNode {
|
||||
/** Gets the argument that specified the host, if any. */
|
||||
abstract DataFlow::Node getHostArgument();
|
||||
}
|
||||
|
||||
/** A direct instantiation of `http.client.HTTPConnection`. */
|
||||
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
|
||||
ClassInstantiation() { this = classRef().getACall() }
|
||||
|
||||
override DataFlow::Node getHostArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("host")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to an instance of `http.client.HTTPConnection`,
|
||||
* that was instantiated with host argument `hostArg`.
|
||||
*/
|
||||
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t, DataFlow::Node hostArg) {
|
||||
t.start() and
|
||||
hostArg = result.(InstanceSource).getHostArgument()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = instance(t2, hostArg).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to an instance of `http.client.HTTPConnection`,
|
||||
* that was instantiated with host argument `hostArg`.
|
||||
*/
|
||||
DataFlow::Node instance(DataFlow::Node hostArg) {
|
||||
instance(DataFlow::TypeTracker::end(), hostArg).flowsTo(result)
|
||||
}
|
||||
|
||||
/** A method call on a HTTPConnection that sends off a request */
|
||||
private class RequestCall extends HTTP::Client::Request::Range, DataFlow::MethodCallNode {
|
||||
RequestCall() { this.calls(instance(_), ["request", "_send_request", "putrequest"]) }
|
||||
|
||||
override DataFlow::Node getResponse() {
|
||||
// TODO: this does not seem like the right abstraction, to allow for nice path-explanations
|
||||
//
|
||||
// For nice path-explanation, we would like either
|
||||
// 1: tainting instance
|
||||
// 1a. host on object creation -> obj
|
||||
// 1b. url on request call -> obj
|
||||
// 2. obj -> obj.getresponse()
|
||||
//
|
||||
// For now, that's really all we use the `getResponse` predicate for.
|
||||
result.(HttpConnectionGetResponseCall).getObject().getALocalSource() =
|
||||
this.getObject().getALocalSource()
|
||||
}
|
||||
|
||||
override DataFlow::Node getUrl() {
|
||||
result in [this.getArg(1), this.getArgByName("url")]
|
||||
or
|
||||
this.getObject() = instance(result)
|
||||
}
|
||||
|
||||
override string getFramework() { result = "http.client.HTTP[S]Connection" }
|
||||
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
// TODO: Proper alerting of insecure verification settings on SSLContext.
|
||||
// Because that is not restricted to HTTP[S]Connection usage, we need something
|
||||
// more general, and I would like to tackle that in future PR.
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to the `getresponse` method. */
|
||||
private class HttpConnectionGetResponseCall extends DataFlow::MethodCallNode,
|
||||
HTTPResponse::InstanceSource {
|
||||
HttpConnectionGetResponseCall() { this.calls(instance(_), "getresponse") }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides models for the `http.client.HTTPResponse` class
|
||||
*
|
||||
* See
|
||||
* - https://docs.python.org/3.10/library/http.client.html#httpresponse-objects
|
||||
* - https://docs.python.org/3/library/http.client.html#http.client.HTTPResponse.
|
||||
*/
|
||||
module HTTPResponse {
|
||||
/** Gets a reference to the `http.client.HTTPResponse` class. */
|
||||
private API::Node classRef() {
|
||||
result = API::moduleImport("http").getMember("client").getMember("HTTPResponse")
|
||||
}
|
||||
|
||||
/**
|
||||
* A source of instances of `http.client.HTTPResponse`, extend this class to model new instances.
|
||||
*
|
||||
* A `http.client.HTTPResponse` is itself a file-like object.
|
||||
*
|
||||
* 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 `HTTPResponse::instance()` to get references to instances of `http.client.HTTPResponse`.
|
||||
*/
|
||||
abstract class InstanceSource extends Stdlib::FileLikeObject::InstanceSource,
|
||||
DataFlow::LocalSourceNode { }
|
||||
|
||||
/** A direct instantiation of `http.client.HTTPResponse`. */
|
||||
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
|
||||
ClassInstantiation() { this = classRef().getACall() }
|
||||
}
|
||||
|
||||
/** Gets a reference to an instance of `http.client.HTTPResponse`. */
|
||||
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 `http.client.HTTPResponse`. */
|
||||
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
|
||||
/**
|
||||
* Taint propagation for `http.client.HTTPResponse`.
|
||||
*/
|
||||
private class InstanceTaintSteps extends InstanceTaintStepsHelper {
|
||||
InstanceTaintSteps() { this = "http.client.HTTPResponse" }
|
||||
|
||||
override DataFlow::Node getInstance() { result = instance() }
|
||||
|
||||
override string getAttributeName() { result in ["headers", "msg", "reason", "url"] }
|
||||
|
||||
override string getMethodName() { result in ["getheader", "getheaders", "info", "geturl",] }
|
||||
|
||||
override string getAsyncMethodName() { none() }
|
||||
}
|
||||
|
||||
/** An attribute read that is a HTTPMessage instance. */
|
||||
private class HTTPMessageInstances extends Stdlib::HTTPMessage::InstanceSource {
|
||||
HTTPMessageInstances() {
|
||||
this.(DataFlow::AttrRead).accesses(instance(), ["headers", "msg"])
|
||||
or
|
||||
this.(DataFlow::MethodCallNode).calls(instance(), "info")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// sqlite3
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user