Python: Port insecure default protocol

- use API graphs
- update .qlhelp-file
- limit to versions below 3.4
- move tests to its own directory to only test on old version
This commit is contained in:
Rasmus Lerchedahl Petersen
2021-02-23 19:41:36 +01:00
parent c5ae8d2c53
commit b28544da9c
6 changed files with 66 additions and 10 deletions

View File

@@ -13,7 +13,7 @@
<p>
Ensure that a modern, strong protocol is used. All versions of SSL,
and TLS 1.0 are known to be vulnerable to attacks. Using TLS 1.1 or
and TLS 1.0 and 1.1 are known to be vulnerable to attacks. Using TLS 1.2 or
above is strongly recommended. If no explicit
<code>ssl_version</code> is specified, the default
<code>PROTOCOL_TLS</code> is chosen. This protocol is insecure and
@@ -34,13 +34,15 @@
<p>
Both of the cases above should be updated to use a secure protocol
instead, for instance by specifying
<code>ssl_version=PROTOCOL_TLSv1_1</code> as a keyword argument.
<code>ssl_version=PROTOCOL_TLSv1_2</code> as a keyword argument.
</p>
<p>
Note that <code>ssl.wrap_socket</code> has been deprecated in
Python 3.7. A preferred alternative is to use
<code>ssl.SSLContext</code>, which is supported in Python 2.7.9 and
3.2 and later versions.
3.2 and later versions or the convenience function
<code>ssl.create_default_context</code>, which is supported in Python
3.4 and later versions.
</p>
</example>
@@ -48,6 +50,8 @@
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security"> Transport Layer Security</a>.</li>
<li>Python 3 documentation: <a href="https://docs.python.org/3/library/ssl.html#ssl.SSLContext"> class ssl.SSLContext</a>.</li>
<li>Python 3 documentation: <a href="https://docs.python.org/3/library/ssl.html#ssl.wrap_socket"> ssl.wrap_socket</a>.</li>
<li>Python 3 documentation: <a href="https://docs.python.org/3/library/ssl.html#functions-constants-and-exceptions"> notes on context creation</a>.</li>
<li>Python 3 documentation: <a href="https://docs.python.org/3/library/ssl.html#ssl-security"> notes on security considerations</a>.</li>
</references>
</qhelp>

View File

@@ -11,20 +11,19 @@
*/
import python
FunctionValue ssl_wrap_socket() { result = Value::named("ssl.wrap_socket") }
ClassValue ssl_Context_class() { result = Value::named("ssl.SSLContext") }
import semmle.python.ApiGraphs
CallNode unsafe_call(string method_name) {
result = ssl_wrap_socket().getACall() and
result = API::moduleImport("ssl").getMember("wrap_socket").getACall().asCfgNode() and
not exists(result.getArgByName("ssl_version")) and
method_name = "deprecated method ssl.wrap_socket"
or
result = ssl_Context_class().getACall() and
result = API::moduleImport("ssl").getMember("SSLContext").getACall().asCfgNode() and
not exists(result.getArgByName("protocol")) and
not exists(result.getArg(0)) and
method_name = "ssl.SSLContext"
method_name = "ssl.SSLContext" and
// in version 3.4, flags were introduced to modify cotexts created with default values
(major_version() < 3 or minor_version() < 4)
}
from CallNode call, string method_name

View File

@@ -0,0 +1,52 @@
import ssl
from pyOpenSSL import SSL
from ssl import SSLContext
# true positives
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_SSLv2)
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_SSLv3)
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)
SSLContext(protocol=ssl.PROTOCOL_SSLv2)
SSLContext(protocol=ssl.PROTOCOL_SSLv3)
SSLContext(protocol=ssl.PROTOCOL_TLSv1)
SSL.Context(SSL.SSLv2_METHOD)
SSL.Context(SSL.SSLv23_METHOD)
SSL.Context(SSL.SSLv3_METHOD)
SSL.Context(SSL.TLSv1_METHOD)
# not relevant
wrap_socket(ssl_version=ssl.PROTOCOL_SSLv3)
wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)
wrap_socket(ssl_version=ssl.PROTOCOL_SSLv2)
Context(SSL.SSLv3_METHOD)
Context(SSL.TLSv1_METHOD)
Context(SSL.SSLv2_METHOD)
Context(SSL.SSLv23_METHOD)
# true positive using flow
METHOD = SSL.SSLv2_METHOD
SSL.Context(METHOD)
# secure versions
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_1)
SSLContext(protocol=ssl.PROTOCOL_TLSv1_1)
SSL.Context(SSL.TLSv1_1_METHOD)
# possibly insecure default
ssl.wrap_socket()
context = SSLContext()
# importing the protocol constant directly
from ssl import PROTOCOL_SSLv2
ssl.wrap_socket(ssl_version=PROTOCOL_SSLv2)
SSLContext(protocol=PROTOCOL_SSLv2)
# FP for insecure default
ssl.SSLContext(ssl.SSLv23_METHOD)

View File

@@ -0,0 +1 @@
semmle-extractor-options: --lang=2 -p ../lib/ --max-import-depth=3