Skip to content

Commit e2dd126

Browse files
author
Porcupiney Hairs
committed
Python: Pycurl SSL Disabled
1 parent ffab199 commit e2dd126

File tree

1 file changed

+43
-2
lines changed

1 file changed

+43
-2
lines changed

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

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ module Pycurl {
3737
/** Gets a reference to an instance of `pycurl.Curl`. */
3838
private API::Node instance() { result = classRef().getReturn() }
3939

40+
/** Gets a reference to an instance of `pycurl.Curl.setopt`. */
41+
private API::Node setopt() { result = instance().getMember("setopt") }
42+
43+
/** Gets a reference to an instance of `pycurl.Curl.SSL_VERIFYPEER`. */
44+
private API::Node sslverifypeer() {
45+
result = API::moduleImport("pycurl").getMember("SSL_VERIFYPEER") or
46+
result = instance().getMember("SSL_VERIFYPEER")
47+
}
48+
4049
/**
4150
* When the first parameter value of the `setopt` function is set to `pycurl.URL`,
4251
* the second parameter value is the request resource link.
@@ -45,7 +54,7 @@ module Pycurl {
4554
*/
4655
private class OutgoingRequestCall extends Http::Client::Request::Range, DataFlow::CallCfgNode {
4756
OutgoingRequestCall() {
48-
this = instance().getMember("setopt").getACall() and
57+
this = setopt().getACall() and
4958
this.getArg(0).asCfgNode().(AttrNode).getName() = "URL"
5059
}
5160

@@ -58,9 +67,41 @@ module Pycurl {
5867
override predicate disablesCertificateValidation(
5968
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
6069
) {
61-
// TODO: Look into disabling certificate validation
6270
none()
6371
}
6472
}
73+
74+
/**
75+
* When the first parameter value of the `setopt` function is set to `SSL_VERIFYPEER` or `SSL_VERIFYHOST`,
76+
* the second parameter value disables or enable SSL certifiacte verification.
77+
*
78+
* See http://pycurl.io/docs/latest/curlobject.html#pycurl.Curl.setopt.
79+
*/
80+
private class CurlSslCall extends Http::Client::Request::Range, DataFlow::CallCfgNode {
81+
CurlSslCall() {
82+
this = setopt().getACall() and
83+
this.getArg(0).asCfgNode().(AttrNode).getName() = ["SSL_VERIFYPEER", "SSL_VERIFYHOST"]
84+
}
85+
86+
override DataFlow::Node getAUrlPart() { none() }
87+
88+
override string getFramework() { result = "pycurl.Curl" }
89+
90+
override predicate disablesCertificateValidation(
91+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
92+
) {
93+
exists(API::CallNode c |
94+
c = setopt().getACall() and
95+
sslverifypeer().getAValueReachableFromSource() = c.getArg(0) and
96+
(
97+
exists(IntegerLiteral i | i.getValue() = 0 and c.getArg(1).asExpr() = i)
98+
or
99+
exists(BooleanLiteral b | b.booleanValue() = false)
100+
)
101+
|
102+
disablingNode = c and argumentOrigin = c.getArg(1)
103+
)
104+
}
105+
}
65106
}
66107
}

0 commit comments

Comments
 (0)