Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0a839f8

Browse files
committed
Python: Check for insecure versions of SSL and TLS.
1 parent 6f82714 commit 0a839f8

10 files changed

Lines changed: 144 additions & 0 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @name Default version of SSL/TLS may be insecure
3+
* @description No SSL/TLS version has been specified in a call to 'ssl.wrap_socket'.
4+
* This may result in an insecure protocol being used.
5+
* @id py/insecure-default-protocol
6+
* @kind problem
7+
* @problem.severity warning
8+
* @precision high
9+
* @tags security
10+
* external/cwe/cwe-327
11+
*/
12+
13+
import python
14+
15+
FunctionObject ssl_wrap_socket() {
16+
result = any(ModuleObject ssl | ssl.getName() = "ssl").getAttribute("wrap_socket")
17+
}
18+
19+
from CallNode call
20+
where
21+
call = ssl_wrap_socket().getACall() and
22+
not exists(call.getArgByName("ssl_version"))
23+
select call, "Call to ssl.wrap_socket does not specify a protocol, which may result in an insecure default being used."
24+
25+
26+
27+
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* @name Use of insecure SSL/TLS version
3+
* @description An insecure version of SSL/TLS has been specified. This may
4+
* leave the connection open to attacks.
5+
* @id py/insecure-protocol
6+
* @kind problem
7+
* @problem.severity warning
8+
* @precision high
9+
* @tags security
10+
* external/cwe/cwe-327
11+
*/
12+
13+
import python
14+
15+
FunctionObject ssl_wrap_socket() {
16+
result = any(ModuleObject ssl | ssl.getName() = "ssl").getAttribute("wrap_socket")
17+
}
18+
19+
string insecure_version_name() {
20+
// For the `ssl` module
21+
result = "SSLv2_METHOD" or
22+
result = "SSLv23_METHOD" or
23+
result = "SSLv3_METHOD" or
24+
result = "TLSv1_METHOD" or
25+
// For `pyOpenSSL.SSL`
26+
result = "PROTOCOL_SSLv2" or
27+
result = "PROTOCOL_SSLv3" or
28+
result = "PROTOCOL_TLSv1"
29+
}
30+
31+
private ModuleObject the_ssl_module() {
32+
result = any(ModuleObject m | m.getName() = "ssl")
33+
}
34+
35+
private ModuleObject the_pyOpenSSL_module() {
36+
result = any(ModuleObject m | m.getName() = "pyOpenSSL").getAttribute("SSL")
37+
}
38+
39+
predicate unsafe_ssl_wrap_method_call(CallNode call) {
40+
call = ssl_wrap_socket().getACall() and
41+
exists(ControlFlowNode arg | arg = call.getArgByName("ssl_version") |
42+
arg.(AttrNode).getObject(insecure_version_name()).refersTo(the_ssl_module())
43+
)
44+
}
45+
46+
ClassObject the_pyOpenSSL_Context_class() {
47+
result = any(ModuleObject m | m.getName() = "pyOpenSSL.SSL").getAttribute("Context")
48+
}
49+
50+
predicate unsafe_pyOpenSSL_Context_call(CallNode call) {
51+
call = the_pyOpenSSL_Context_class().getACall() and
52+
call.getArgByName("method").refersTo(the_pyOpenSSL_module().getAttribute(insecure_version_name()))
53+
}
54+
55+
from CallNode call, string method_name
56+
where
57+
unsafe_ssl_wrap_method_call(call) and method_name = "ssl.wrap_socket"
58+
or
59+
unsafe_pyOpenSSL_Context_call(call) and method_name = "pyOpenSSL.SSL.Context"
60+
select call, "Insecure SSL/TLS protocol version specified in call to " + method_name + "."
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| InsecureProtocol.py:35:1:35:17 | ControlFlowNode for Attribute() | Call to ssl.wrap_socket does not specify a protocol, which may result in an insecure default being used. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE-327/InsecureDefaultProtocol.ql
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
| InsecureProtocol.py:5:1:5:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version specified in call to ssl.wrap_socket. |
2+
| InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version specified in call to ssl.wrap_socket. |
3+
| InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version specified in call to ssl.wrap_socket. |
4+
| InsecureProtocol.py:9:1:9:36 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version specified in call to pyOpenSSL.SSL.Context. |
5+
| InsecureProtocol.py:10:1:10:37 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version specified in call to pyOpenSSL.SSL.Context. |
6+
| InsecureProtocol.py:11:1:11:36 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version specified in call to pyOpenSSL.SSL.Context. |
7+
| InsecureProtocol.py:12:1:12:36 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version specified in call to pyOpenSSL.SSL.Context. |
8+
| InsecureProtocol.py:27:1:27:26 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version specified in call to pyOpenSSL.SSL.Context. |
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import ssl
2+
from pyOpenSSL import SSL
3+
4+
# true positives
5+
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_SSLv2)
6+
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_SSLv3)
7+
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)
8+
9+
SSL.Context(method=SSL.SSLv2_METHOD)
10+
SSL.Context(method=SSL.SSLv23_METHOD)
11+
SSL.Context(method=SSL.SSLv3_METHOD)
12+
SSL.Context(method=SSL.TLSv1_METHOD)
13+
14+
# not relevant
15+
wrap_socket(ssl_version=ssl.PROTOCOL_SSLv3)
16+
wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)
17+
wrap_socket(ssl_version=ssl.PROTOCOL_SSLv2)
18+
19+
Context(method=SSL.SSLv3_METHOD)
20+
Context(method=SSL.TLSv1_METHOD)
21+
Context(method=SSL.SSLv2_METHOD)
22+
Context(method=SSL.SSLv23_METHOD)
23+
24+
# true positive using flow
25+
26+
METHOD = SSL.SSLv2_METHOD
27+
SSL.Context(method=METHOD)
28+
29+
# secure versions
30+
31+
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_1)
32+
SSL.Context(method=SSL.TLSv1_1_METHOD)
33+
34+
# possibly insecure default
35+
ssl.wrap_socket()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE-327/InsecureProtocol.ql
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
semmle-extractor-options: -p ../lib/ --max-import-depth=3
2+
optimize: true
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
SSLv2_METHOD = 1
2+
SSLv3_METHOD = 2
3+
SSLv23_METHOD = 3
4+
TLSv1_METHOD = 4
5+
TLSv1_1_METHOD = 5
6+
TLSv1_2_METHOD = 6
7+
8+
class Context(object):
9+
def __init__(self, *args, **kwargs):
10+
pass

python/ql/test/query-tests/Security/lib/pyOpenSSL/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)