Skip to content

Commit 38748f9

Browse files
committed
Python: restrict attention to ss.wrap_socket
1 parent 8b68912 commit 38748f9

File tree

5 files changed

+15
-23
lines changed

5 files changed

+15
-23
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 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.
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.2 introduced so-called contexts to create connections from. These come with 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 for the deprecated way of creating connections without a context.

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<qhelp>
55
<overview>
66
<p>
7-
In version of Python before 3.4, the <code>ssl</code> library defaults
7+
The <code>ssl</code> library defaults
88
to an insecure version of SSL/TLS when no specific protocol version is
99
specified. This may leave the connection vulnerable to attack.
1010
</p>
@@ -37,6 +37,13 @@
3737
instead, for instance by specifying
3838
<code>ssl_version=PROTOCOL_TLSv1_2</code> as a keyword argument.
3939
</p>
40+
<p>
41+
The latter example can also be made secure by modifying the created
42+
context before it is used to create a connection and so will not be
43+
flagged by this query. However, if a connection is created before
44+
the context has been secured (e.g. by setting the value of <code>minimum_version</code>),
45+
then the code should be flagged by the query <code>py/insecure-protocol</code>.
46+
</p>
4047
<p>
4148
Note that <code>ssl.wrap_socket</code> has been deprecated in
4249
Python 3.7. The recommended alternatives are:

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

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,21 @@
1111
*/
1212

1313
// 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`).
14+
// This has become untrue since Python 3.2 where the `SSLContext` was introduced. Such contexts
15+
// are designed to later be modified by flags such as `OP_NO_TLSv1_1`, and so the default values
16+
// are not necessarity problematic.
1817
//
1918
// Detecting that a connection is created with a context that has not been suitably modified is
2019
// 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.
20+
// to alerting on the one deprecated default constructor whch does not refer to a contex, namely
21+
// `ssl.wrap_socket`.
2222
import python
2323
import semmle.python.ApiGraphs
2424

2525
CallNode unsafe_call(string method_name) {
2626
result = API::moduleImport("ssl").getMember("wrap_socket").getACall().asCfgNode() and
2727
not exists(result.getArgByName("ssl_version")) and
2828
method_name = "deprecated method ssl.wrap_socket"
29-
or
30-
result = API::moduleImport("ssl").getMember("SSLContext").getACall().asCfgNode() and
31-
not exists(result.getArgByName("protocol")) and
32-
not exists(result.getArg(0)) and
33-
method_name = "ssl.SSLContext" and
34-
// in version 3.4, flags were introduced to modify contexts created with default values
35-
(
36-
major_version() = 2
37-
or
38-
major_version() = 3 and minor_version() < 4
39-
)
4029
}
4130

4231
from CallNode call, string method_name
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
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. |
1+
| InsecureProtocol.py:7:1:7: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. |
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import ssl
2-
from ssl import SSLContext
32

43
# secure versions
54
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_2)
6-
SSLContext(protocol=ssl.PROTOCOL_TLSv1_2)
75

86
# possibly insecure default
97
ssl.wrap_socket()
10-
context = SSLContext()

0 commit comments

Comments
 (0)