Python: Model certificate disabling in urllib3

This commit is contained in:
Rasmus Wriedt Larsen
2022-06-08 17:33:05 +02:00
parent 0d02ca07d7
commit 5b2d799fde
2 changed files with 49 additions and 7 deletions

View File

@@ -42,9 +42,6 @@ private module Urllib3 {
.getASubclass+()
}
/** Gets a reference to an instance of a `urllib3.request.RequestMethods` subclass. */
private API::Node instance() { result = classRef().getReturn() }
/**
* A call to a method making an outgoing request.
*
@@ -52,10 +49,11 @@ private module Urllib3 {
* - https://urllib3.readthedocs.io/en/stable/reference/urllib3.request.html#urllib3.request.RequestMethods
* - https://urllib3.readthedocs.io/en/stable/reference/urllib3.connectionpool.html#urllib3.HTTPConnectionPool.urlopen
*/
private class RequestCall extends HTTP::Client::Request::Range, DataFlow::CallCfgNode {
private class RequestCall extends HTTP::Client::Request::Range, API::CallNode {
RequestCall() {
this =
instance()
classRef()
.getReturn()
.getMember(["request", "request_encode_url", "request_encode_body", "urlopen"])
.getACall()
}
@@ -67,8 +65,22 @@ private module Urllib3 {
override predicate disablesCertificateValidation(
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
) {
// TODO: Look into disabling certificate validation
none()
exists(API::CallNode constructor |
constructor = classRef().getACall() and
this = constructor.getReturn().getAMember().getACall()
|
// cert_reqs
// see https://urllib3.readthedocs.io/en/stable/user-guide.html?highlight=cert_reqs#certificate-verification
disablingNode = constructor.getKeywordParameter("cert_reqs").getARhs() and
argumentOrigin = constructor.getKeywordParameter("cert_reqs").getAValueReachingRhs() and
argumentOrigin.asExpr().(StrConst).getText() = "CERT_NONE"
or
// assert_hostname
// see https://urllib3.readthedocs.io/en/stable/reference/urllib3.connectionpool.html?highlight=assert_hostname#urllib3.HTTPSConnectionPool
disablingNode = constructor.getKeywordParameter("assert_hostname").getARhs() and
argumentOrigin = constructor.getKeywordParameter("assert_hostname").getAValueReachingRhs() and
argumentOrigin.asExpr().(BooleanLiteral).booleanValue() = false
)
}
}
}

View File

@@ -27,3 +27,33 @@ resp = pool.request("method", "url") # $ clientRequestUrlPart="url"
resp = pool.request("method", url="url") # $ clientRequestUrlPart="url"
resp = pool.urlopen("method", "url") # $ clientRequestUrlPart="url"
resp = pool.urlopen("method", url="url") # $ clientRequestUrlPart="url"
# ==============================================================================
# Certificate validation disabled
# ==============================================================================
# see https://docs.python.org/3.10/library/ssl.html#ssl.CERT_NONE
pool = urllib3.HTTPSConnectionPool("host", cert_reqs='CERT_NONE')
resp = pool.request("method", "url") # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled
pool = urllib3.HTTPSConnectionPool("host", assert_hostname=False)
resp = pool.request("method", "url") # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled
pool = urllib3.HTTPSConnectionPool("host", cert_reqs='CERT_NONE', assert_hostname=False)
resp = pool.request("method", "url") # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled
# same with PoolManager
pool = urllib3.PoolManager(cert_reqs='CERT_NONE')
resp = pool.request("method", "url") # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled
pool = urllib3.PoolManager(assert_hostname=False)
resp = pool.request("method", "url") # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled
# and same with ProxyManager
pool = urllib3.ProxyManager("https://proxy", cert_reqs='CERT_NONE')
resp = pool.request("method", "url") # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled
pool = urllib3.ProxyManager("https://proxy", assert_hostname=False)
resp = pool.request("method", "url") # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled