Skip to content

Commit 9533c92

Browse files
committed
Python: Clean up tests and add comment
2 parents 311149a + 1670fa0 commit 9533c92

File tree

4 files changed

+19
-48
lines changed

4 files changed

+19
-48
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
lgtm,codescanning
2-
* Changed the query that detects insecure protocol creation from default values (`py/insecure-default-protocol`) to use the new API graphs. Modern versions of Python include fluent APIs that change default values after construction, so the query now reports results only in versions of Python where fluent APIs are not available.
2+
* Changed the query that detects insecure SSL/TLS protocol creation from default values (`py/insecure-default-protocol`) to use the new API graphs. Python 3.4 introduced new ways to specify protocol version (through modifying the `options` field), which means that using the default value _can_ be secure (and if the usage is not secure, this should be reported by the `py/insecure-protocol` query). This query now reports results only in versions of Python prior to 3.4.

python/ql/src/Security/CWE-327/InsecureDefaultProtocol.ql

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
* external/cwe/cwe-327
1111
*/
1212

13+
// This query is based on the premise that default constructors are always a security concern.
14+
// This has become untrue since Python 3.4 where flags such as `OP_NO_TLSv1_1` were introduced
15+
// on the `options` field to modify contexts created with default values. These flags are now,
16+
// since OpenSSL1.1.0, themselves deprecated in favor of the `minimum_version` field (and its
17+
// counterpart `maximum_version`).
18+
//
19+
// Detecting that a connection is created with a context that has not been suitably modified is
20+
// handled by the data-flow query py/insecure-protocol, while the present query is restricted
21+
// to alerting on default constructors when the Python version is earlier than 3.4.
1322
import python
1423
import semmle.python.ApiGraphs
1524

@@ -23,7 +32,11 @@ CallNode unsafe_call(string method_name) {
2332
not exists(result.getArg(0)) and
2433
method_name = "ssl.SSLContext" and
2534
// in version 3.4, flags were introduced to modify contexts created with default values
26-
(major_version() < 3 or minor_version() < 4)
35+
(
36+
major_version() = 2
37+
or
38+
major_version() = 3 and minor_version() < 4
39+
)
2740
}
2841

2942
from CallNode call, string method_name
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
| InsecureProtocol.py:41:1:41:17 | ControlFlowNode for Attribute() | Call to deprecated method ssl.wrap_socket does not specify a protocol, which may result in an insecure default being used. |
2-
| InsecureProtocol.py:42:11:42:22 | ControlFlowNode for SSLContext() | Call to ssl.SSLContext does not specify a protocol, which may result in an insecure default being used. |
1+
| InsecureProtocol.py:9:1:9:17 | ControlFlowNode for Attribute() | Call to deprecated method ssl.wrap_socket does not specify a protocol, which may result in an insecure default being used. |
2+
| InsecureProtocol.py:10:11:10:22 | ControlFlowNode for SSLContext() | Call to ssl.SSLContext does not specify a protocol, which may result in an insecure default being used. |
Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,10 @@
11
import ssl
2-
from pyOpenSSL import SSL
32
from ssl import SSLContext
43

5-
# true positives
6-
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_SSLv2)
7-
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_SSLv3)
8-
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)
9-
10-
SSLContext(protocol=ssl.PROTOCOL_SSLv2)
11-
SSLContext(protocol=ssl.PROTOCOL_SSLv3)
12-
SSLContext(protocol=ssl.PROTOCOL_TLSv1)
13-
14-
SSL.Context(SSL.SSLv2_METHOD)
15-
SSL.Context(SSL.SSLv23_METHOD)
16-
SSL.Context(SSL.SSLv3_METHOD)
17-
SSL.Context(SSL.TLSv1_METHOD)
18-
19-
# not relevant
20-
wrap_socket(ssl_version=ssl.PROTOCOL_SSLv3)
21-
wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)
22-
wrap_socket(ssl_version=ssl.PROTOCOL_SSLv2)
23-
24-
Context(SSL.SSLv3_METHOD)
25-
Context(SSL.TLSv1_METHOD)
26-
Context(SSL.SSLv2_METHOD)
27-
Context(SSL.SSLv23_METHOD)
28-
29-
# true positive using flow
30-
31-
METHOD = SSL.SSLv2_METHOD
32-
SSL.Context(METHOD)
33-
344
# secure versions
35-
36-
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_1)
37-
SSLContext(protocol=ssl.PROTOCOL_TLSv1_1)
38-
SSL.Context(SSL.TLSv1_1_METHOD)
5+
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_2)
6+
SSLContext(protocol=ssl.PROTOCOL_TLSv1_2)
397

408
# possibly insecure default
419
ssl.wrap_socket()
4210
context = SSLContext()
43-
44-
# importing the protocol constant directly
45-
46-
from ssl import PROTOCOL_SSLv2
47-
48-
ssl.wrap_socket(ssl_version=PROTOCOL_SSLv2)
49-
SSLContext(protocol=PROTOCOL_SSLv2)
50-
51-
# FP for insecure default
52-
ssl.SSLContext(ssl.SSLv23_METHOD)

0 commit comments

Comments
 (0)