Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions python/ql/src/Security/CWE-327/Ssl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ class SslDefaultContextCreation extends ContextCreation {
this = API::moduleImport("ssl").getMember("create_default_context").getACall()
}

// Allowed insecure versions are "TLSv1" and "TLSv1_1"
// Since Python 3.10, `ssl.create_default_context` returns a context whose
// `minimum_version` defaults to `TLSVersion.TLSv1_2`, so TLSv1 and TLSv1_1 are not allowed.
// (Earlier Python versions also allowed TLSv1 and TLSv1_1.)
// see https://docs.python.org/3/library/ssl.html#context-creation
override ProtocolVersion getProtocol() { result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] }
// and https://docs.python.org/3/whatsnew/3.10.html#ssl
override ProtocolVersion getProtocol() { result in ["TLSv1_2", "TLSv1_3"] }
}

/** Gets a reference to an `ssl.Context` instance. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `py/insecure-protocol` query no longer reports `ssl.create_default_context` as allowing TLS 1.0 or TLS 1.1. Since Python 3.10, the context returned by `ssl.create_default_context` has its `minimum_version` set to `TLSVersion.TLSv1_2` by default, so these protocol versions are not allowed and the previous alerts were false positives.
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,3 @@
| ssl_fluent.py:97:14:97:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:65:15:65:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
| ssl_fluent.py:146:14:146:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:142:15:142:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context |
| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context |
| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context |
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,14 @@ def test_fluent_explicitly_unsafe():
with socket.create_connection((hostname, 443)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock: # $ Alert
print(ssock.version())

# Since Python 3.10, `ssl.create_default_context` sets `minimum_version` to
# `TLSVersion.TLSv1_2`, so TLSv1 and TLSv1_1 are not allowed.
# see https://docs.python.org/3/library/ssl.html#context-creation
def test_fluent_default_context_safe():
hostname = 'www.python.org'
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)

with socket.create_connection((hostname, 443)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock: # No alert
print(ssock.version())
Loading