[CVE-2023-40217] Bypass TLS handshake on closed sockets
Description Instances of ssl.SSLSocket are vulnerable to a bypass of the TLS handshake and included protections (like certificate verification) and treating sent unencrypted data as if it were post-handshake TLS encrypted data if the socket is closed before initiating its own handshake.
This vulnerability is of severity: *HIGH*.
The vulnerability is caused when a socket is connected, data is sent by the malicious peer and stored in a buffer, and then the malicious peer closes the socket within a small timing window before the other peers’ TLS handshake can begin. After this sequence of events the closed socket will not immediately attempt a TLS handshake due to not being connected but will also allow the buffered data to be read as if a successful TLS handshake had occurred.
Affected usages
This vulnerability *primarily affects* HTTPS servers and other server-side protocols using TLS client authentication (such as mTLS) due to requiring reading data immediately after the handshake to be vulnerable. Operations which would fail on a closed socket (like sending data) immediately after the handshake are not affected by this vulnerability.
Because disconnecting the socket is a necessary step to trigger the vulnerability *there is no risk of data exfiltration or data leakage directly from the malicious TLS connection*, however the vulnerability *does* carry risk for modifying or deleting resources which are authenticated using only TLS client certificates.
This vulnerability *affects* clients who are reading and processing data from the server after a TLS handshake without sending any data first. Our team is unaware of a protocol that uses TLS that fits this usage pattern.
This vulnerability *does not affect* client-side HTTPS connections like pip or requests as an HTTP request must be sent before an HTTP response is read meaning the connection would already be closed by the time the client is sending an HTTP request, leading to an error.
This vulnerability *affects, but has no impact* on servers that aren’t using TLS client certificate authentication as traffic to a non-authenticating TLS server loses nothing from a bypassed handshake to inject a query and close the connection as the same action could be taken by a peer using a TLS connection with a proper handshake.
Affected versions
- Python 3.12.0a1 to 3.12.0rc1 *
- Python 3.11.0 to 3.11.4
- Python 3.10.0 to 3.10.12
- Python 3.9.0 to 3.9.17
- Python 3.8.0 to 3.8.17
- Python 3.7.17 and earlier **
- Note that Python 3.12.0rc2 will not be published for a few weeks. *Pre-release versions of Python are not recommended for production use.*
** *Note that Python 3.7.17 and earlier will not be receiving an upstream security fix due to being end-of-life <https://devguide.python.org/versions/#versions>,* contact your distributor of Python for additional guidance.
Remediation and work-arounds
- Upgrade to Python 3.11.5, 3.10.13, 3.9.18, or 3.8.18.
- Apply a patch for your corresponding version of Python.
- Add a call to SSLSocket.getpeername() after calling SSLSocket.wrap_socket() before any calls to SSLSocket.recv(). This call to getpeername() will raise an OSError if the socket isn’t connected thus mitigating the vulnerability.
Patches are available for all affected feature, bugfix, and security branches of Python:
main: 0cb0c238d520a8718e313b52cffc356a5a7561bf <https://github.com/python/cpython/commit/0cb0c238d520a8718e313b52cffc356a5a7561bf>
3.12: 256586ab8776e4526ca594b4866b9a3492e628f1 <https://github.com/python/cpython/commit/256586ab8776e4526ca594b4866b9a3492e628f1>
3.11: 75a875e0df0530b75b1470d797942f90f4a718d3 <https://github.com/python/cpython/commit/75a875e0df0530b75b1470d797942f90f4a718d3>
3.10: 37d7180cb647f0bed0c1caab0037f3bc82e2af96 <https://github.com/python/cpython/commit/37d7180cb647f0bed0c1caab0037f3bc82e2af96>
3.9: 264b1dacc67346efa0933d1e63f622676e0ed96b <https://github.com/python/cpython/commit/264b1dacc67346efa0933d1e63f622676e0ed96b>
3.8: b4bcc06a9cfe13d96d5270809d963f8ba278f89b <https://github.com/python/cpython/commit/b4bcc06a9cfe13d96d5270809d963f8ba278f89b>
Additional patches to stabilize the test suite may also be applied to all versions:
- 64f99350351bc46e016b2286f36ba7cd669b79e3 <https://github.com/python/cpython/commit/64f99350351bc46e016b2286f36ba7cd669b79e3>
- 592bacb6fc0833336c0453e818e9b95016e9fd47 <https://github.com/python/cpython/commit/592bacb6fc0833336c0453e818e9b95016e9fd47>
References
https://github.com/python/cpython/issues/108310
https://github.com/python/cpython/pull/108315
Credits
- Reporter: Aapo Oksman
- Remediation Developer: Gregory P. Smith
- Remediation Reviewer: Thomas Wouters
- Coordinator: Seth Michael Larson
Timeline
- August 8,2023: Reported by Aapo Oksman to security@python.org.
- August 8, 2023: Acknowledged the report.
- August 9, 2023: Acknowledgement of the vulnerability, sent CVE ID request to MITRE.
- August 10, 2023: CVE-2023-40217 assigned by MITRE.
- August 15, 2023: Patch authored by Gregory P Smith, reviewed by Thomas Wouters.
- August 22, 2023: Patch applied to feature and security branches by Łukasz Langa.
- August 24, 2023: Python 3.11.5, 3.10.13, 3.9.18, 3.8.18 are published containing the fix for CVE-2023-40217.
- August 24, 2023: Advisory published.
participants (1)
-
Seth Larson