Python: Clean up tests and add comment

This commit is contained in:
Rasmus Lerchedahl Petersen
2021-02-26 19:28:44 +01:00
4 changed files with 19 additions and 48 deletions

View File

@@ -1,2 +1,2 @@
lgtm,codescanning
* 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.
* 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.

View File

@@ -10,6 +10,15 @@
* external/cwe/cwe-327
*/
// This query is based on the premise that default constructors are always a security concern.
// This has become untrue since Python 3.4 where flags such as `OP_NO_TLSv1_1` were introduced
// on the `options` field to modify contexts created with default values. These flags are now,
// since OpenSSL1.1.0, themselves deprecated in favor of the `minimum_version` field (and its
// counterpart `maximum_version`).
//
// Detecting that a connection is created with a context that has not been suitably modified is
// handled by the data-flow query py/insecure-protocol, while the present query is restricted
// to alerting on default constructors when the Python version is earlier than 3.4.
import python
import semmle.python.ApiGraphs
@@ -23,7 +32,11 @@ CallNode unsafe_call(string method_name) {
not exists(result.getArg(0)) and
method_name = "ssl.SSLContext" and
// in version 3.4, flags were introduced to modify contexts created with default values
(major_version() < 3 or minor_version() < 4)
(
major_version() = 2
or
major_version() = 3 and minor_version() < 4
)
}
from CallNode call, string method_name

View File

@@ -1,2 +1,2 @@
| 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. |
| 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. |
| 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. |
| 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. |

View File

@@ -1,52 +1,10 @@
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)
ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_2)
SSLContext(protocol=ssl.PROTOCOL_TLSv1_2)
# 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)