From cbbc7b2bcd160bdfc268252644f35daf4c1bcfd9 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 3 Mar 2021 23:42:48 +0100 Subject: [PATCH] Python: support unrestrictions Also pyOpenSSL allows SSL 2 and SSL 3 on `SSLv23` --- .../src/Security/CWE-327/FluentApiModel.qll | 62 ++++++++-------- .../src/Security/CWE-327/InsecureProtocol.ql | 28 ++++++-- python/ql/src/Security/CWE-327/PyOpenSSL.qll | 18 +++-- python/ql/src/Security/CWE-327/Ssl.qll | 63 ++++++++++++---- .../src/Security/CWE-327/TlsLibraryModel.qll | 48 +++++++++++-- .../CWE-327/InsecureProtocol.expected | 72 ++++++++++--------- 6 files changed, 201 insertions(+), 90 deletions(-) diff --git a/python/ql/src/Security/CWE-327/FluentApiModel.qll b/python/ql/src/Security/CWE-327/FluentApiModel.qll index 23922a90595..d222af70499 100644 --- a/python/ql/src/Security/CWE-327/FluentApiModel.qll +++ b/python/ql/src/Security/CWE-327/FluentApiModel.qll @@ -8,40 +8,44 @@ import TlsLibraryModel */ class InsecureContextConfiguration extends DataFlow::Configuration { TlsLibrary library; + ProtocolVersion tracked_version; - InsecureContextConfiguration() { this = library + ["AllowsTLSv1", "AllowsTLSv1_1"] } + InsecureContextConfiguration() { + this = library + "Allows" + tracked_version and + tracked_version.isInsecure() + } + + ProtocolVersion getTrackedVersion() { result = tracked_version } override predicate isSource(DataFlow::Node source) { - source = library.unspecific_context_creation() + // source = library.unspecific_context_creation() + exists(ProtocolUnrestriction pu | + pu = library.protocol_unrestriction() and + pu.getUnrestriction() = tracked_version + | + source = pu.getContext() + ) } override predicate isSink(DataFlow::Node sink) { sink = library.connection_creation().getContext() } - abstract string flag(); - override predicate isBarrierOut(DataFlow::Node node) { exists(ProtocolRestriction r | r = library.protocol_restriction() and node = r.getContext() and - r.getRestriction() = flag() + r.getRestriction() = tracked_version ) } -} -/** Configuration to specifically track the insecure protocol TLS 1.0 */ -class AllowsTLSv1 extends InsecureContextConfiguration { - AllowsTLSv1() { this = library + "AllowsTLSv1" } - - override string flag() { result = "TLSv1" } -} - -/** Configuration to specifically track the insecure protocol TLS 1.1 */ -class AllowsTLSv1_1 extends InsecureContextConfiguration { - AllowsTLSv1_1() { this = library + "AllowsTLSv1_1" } - - override string flag() { result = "TLSv1_1" } + override predicate isBarrierIn(DataFlow::Node node) { + exists(ProtocolUnrestriction r | + r = library.protocol_unrestriction() and + node = r.getContext() and + r.getUnrestriction() = tracked_version + ) + } } /** @@ -49,22 +53,22 @@ class AllowsTLSv1_1 extends InsecureContextConfiguration { * and that protocol has not been restricted appropriately. */ predicate unsafe_connection_creation( - DataFlow::Node node, ProtocolVersion insecure_version, CallNode call + DataFlow::Node creation, ProtocolVersion insecure_version, DataFlow::Node source, boolean specific ) { - // Connection created from a context allowing TLS 1.0. - exists(AllowsTLSv1 c, ContextCreation cc | c.hasFlow(cc, node) | cc.getNode() = call) and - insecure_version = "TLSv1" + // Connection created from a context allowing `insecure_version`. + exists(InsecureContextConfiguration c, ProtocolUnrestriction cc | c.hasFlow(cc, creation) | + insecure_version = c.getTrackedVersion() and + source = cc and + specific = false + ) or - // Connection created from a context allowing TLS 1.1. - exists(AllowsTLSv1_1 c, ContextCreation cc | c.hasFlow(cc, node) | cc.getNode() = call) and - insecure_version = "TLSv1_1" - or - // Connection created from a context for an insecure protocol. + // Connection created from a context specifying `insecure_version`. exists(TlsLibrary l, DataFlow::CfgNode cc | cc = l.insecure_connection_creation(insecure_version) | - cc = node and - cc.getNode() = call + creation = cc and + source = cc and + specific = true ) } diff --git a/python/ql/src/Security/CWE-327/InsecureProtocol.ql b/python/ql/src/Security/CWE-327/InsecureProtocol.ql index 51247dbd75a..194cc1f5ec1 100644 --- a/python/ql/src/Security/CWE-327/InsecureProtocol.ql +++ b/python/ql/src/Security/CWE-327/InsecureProtocol.ql @@ -18,11 +18,25 @@ string callName(AstNode call) { exists(Attribute a | a = call | result = callName(a.getObject()) + "." + a.getName()) } -from DataFlow::Node node, string insecure_version, CallNode call -where - unsafe_connection_creation(node, insecure_version, call) +string sourceName(DataFlow::Node source) { + result = "call to " + callName(source.asCfgNode().(CallNode).getFunction().getNode()) or - unsafe_context_creation(node, insecure_version, call) -select node, "Insecure SSL/TLS protocol version " + insecure_version + " specified in $@ ", call, - "call to " + callName(call.getFunction().getNode()) -//+ " specified in call to " + method_name + "." + not source.asCfgNode() instanceof CallNode and + not source instanceof ContextCreation and + result = "context modification" +} + +string verb(boolean specific) { + specific = true and result = "specified" + or + specific = false and result = "allowed" +} + +from DataFlow::Node creation, string insecure_version, DataFlow::Node source, boolean specific +where + unsafe_connection_creation(creation, insecure_version, source, specific) + or + unsafe_context_creation(creation, insecure_version, source.asCfgNode()) and specific = true +select creation, + "Insecure SSL/TLS protocol version " + insecure_version + " " + verb(specific) + " by $@ ", + source, sourceName(source) diff --git a/python/ql/src/Security/CWE-327/PyOpenSSL.qll b/python/ql/src/Security/CWE-327/PyOpenSSL.qll index a89c7ff0886..3c36c568ef5 100644 --- a/python/ql/src/Security/CWE-327/PyOpenSSL.qll +++ b/python/ql/src/Security/CWE-327/PyOpenSSL.qll @@ -26,6 +26,8 @@ class ConnectionCall extends ConnectionCreation { } } +// This cannot be used to unrestrict, +// see https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_options class SetOptionsCall extends ProtocolRestriction { override CallNode node; @@ -42,6 +44,10 @@ class SetOptionsCall extends ProtocolRestriction { } } +class UnspecificPyOpenSSLContextCreation extends PyOpenSSLContextCreation, UnspecificContextCreation { + UnspecificPyOpenSSLContextCreation() { library = "pyOpenSSL" } +} + class PyOpenSSL extends TlsLibrary { PyOpenSSL() { this = "pyOpenSSL" } @@ -50,11 +56,9 @@ class PyOpenSSL extends TlsLibrary { result = version + "_METHOD" } - override string unspecific_version_name() { - result in [ - "TLS_METHOD", // This is not actually available in pyOpenSSL yet - "SSLv23_METHOD" // This is what can negotiate TLS 1.3 (indeed, I know, I did test that..) - ] + override string unspecific_version_name(ProtocolFamily family) { + // `"TLS_METHOD"` is not actually available in pyOpenSSL yet, but should be coming soon.. + result = family + "_METHOD" } override API::Node version_constants() { result = API::moduleImport("OpenSSL").getMember("SSL") } @@ -70,4 +74,8 @@ class PyOpenSSL extends TlsLibrary { override ConnectionCreation connection_creation() { result instanceof ConnectionCall } override ProtocolRestriction protocol_restriction() { result instanceof SetOptionsCall } + + override ProtocolUnrestriction protocol_unrestriction() { + result instanceof UnspecificPyOpenSSLContextCreation + } } diff --git a/python/ql/src/Security/CWE-327/Ssl.qll b/python/ql/src/Security/CWE-327/Ssl.qll index 4caa0ae7302..e749bb9bc3c 100644 --- a/python/ql/src/Security/CWE-327/Ssl.qll +++ b/python/ql/src/Security/CWE-327/Ssl.qll @@ -56,6 +56,31 @@ class OptionsAugOr extends ProtocolRestriction { override ProtocolVersion getRestriction() { result = restriction } } +class OptionsAugAndNot extends ProtocolUnrestriction { + ProtocolVersion restriction; + + OptionsAugAndNot() { + exists(AugAssign aa, AttrNode attr, Expr flag, UnaryExpr notFlag | + aa.getOperation().getOp() instanceof BitAnd and + aa.getTarget() = attr.getNode() and + attr.getName() = "options" and + attr.getObject() = node and + notFlag.getOp() instanceof Invert and + notFlag.getOperand() = flag and + flag = API::moduleImport("ssl").getMember("OP_NO_" + restriction).getAUse().asExpr() and + ( + aa.getValue() = notFlag + or + impliesValue(aa.getValue(), notFlag, true, true) + ) + ) + } + + override DataFlow::CfgNode getContext() { result = this } + + override ProtocolVersion getUnrestriction() { result = restriction } +} + /** Whether `part` evaluates to `partIsTrue` if `whole` evaluates to `wholeIsTrue`. */ predicate impliesValue(BinaryExpr whole, Expr part, boolean partIsTrue, boolean wholeIsTrue) { whole.getOp() instanceof BitAnd and @@ -75,8 +100,8 @@ predicate impliesValue(BinaryExpr whole, Expr part, boolean partIsTrue, boolean ) } -class ContextSetVersion extends ProtocolRestriction { - string restriction; +class ContextSetVersion extends ProtocolRestriction, ProtocolUnrestriction { + ProtocolVersion restriction; ContextSetVersion() { exists(Attributes::AttrWrite aw | @@ -90,6 +115,21 @@ class ContextSetVersion extends ProtocolRestriction { override DataFlow::CfgNode getContext() { result = this } override ProtocolVersion getRestriction() { result.lessThan(restriction) } + + override ProtocolVersion getUnrestriction() { + restriction = result or restriction.lessThan(result) + } +} + +class UnspecificSSLContextCreation extends SSLContextCreation, UnspecificContextCreation { + UnspecificSSLContextCreation() { library = "ssl" } + + override ProtocolVersion getUnrestriction() { + result = UnspecificContextCreation.super.getUnrestriction() and + // These are turned off by default + // see https://docs.python.org/3/library/ssl.html#ssl-contexts + not result in ["SSLv2", "SSLv3"] + } } class Ssl extends TlsLibrary { @@ -100,16 +140,7 @@ class Ssl extends TlsLibrary { result = "PROTOCOL_" + version } - override string unspecific_version_name() { - result = - "PROTOCOL_" + - [ - "TLS", - // This can negotiate a TLS 1.3 connection (!) - // see https://docs.python.org/3/library/ssl.html#ssl-contexts - "SSLv23" - ] - } + override string unspecific_version_name(ProtocolFamily family) { result = "PROTOCOL_" + family } override API::Node version_constants() { result = API::moduleImport("ssl") } @@ -132,4 +163,12 @@ class Ssl extends TlsLibrary { or result instanceof ContextSetVersion } + + override ProtocolUnrestriction protocol_unrestriction() { + result instanceof OptionsAugAndNot + or + result instanceof ContextSetVersion + or + result instanceof UnspecificSSLContextCreation + } } diff --git a/python/ql/src/Security/CWE-327/TlsLibraryModel.qll b/python/ql/src/Security/CWE-327/TlsLibraryModel.qll index 36e58acd926..97ceec00688 100644 --- a/python/ql/src/Security/CWE-327/TlsLibraryModel.qll +++ b/python/ql/src/Security/CWE-327/TlsLibraryModel.qll @@ -19,6 +19,13 @@ class ProtocolVersion extends string { or this = ["TLSv1", "TLSv1_1", "TLSv1_2"] and version = "TLSv1_3" } + + predicate isInsecure() { this in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1"] } +} + +/** An unspecific protocol version */ +class ProtocolFamily extends string { + ProtocolFamily() { this in ["SSLv23", "TLS"] } } /** The creation of a context. */ @@ -42,6 +49,34 @@ abstract class ProtocolRestriction extends DataFlow::CfgNode { abstract ProtocolVersion getRestriction(); } +/** A context is being relaxed on which protocols it can accepts. */ +abstract class ProtocolUnrestriction extends DataFlow::CfgNode { + /** Gets the context being relaxed. */ + abstract DataFlow::CfgNode getContext(); + + /** Gets the protocol version being allowed. */ + abstract ProtocolVersion getUnrestriction(); +} + +abstract class UnspecificContextCreation extends ContextCreation, ProtocolUnrestriction { + TlsLibrary library; + ProtocolFamily family; + + UnspecificContextCreation() { this.getProtocol() = library.unspecific_version(family) } + + override DataFlow::CfgNode getContext() { result = this } + + override ProtocolVersion getUnrestriction() { + family = "TLS" and + result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] + or + // This can negotiate a TLS 1.3 connection (!) + // see https://docs.python.org/3/library/ssl.html#ssl-contexts + family = "SSLv23" and + result in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] + } +} + abstract class TlsLibrary extends string { TlsLibrary() { this in ["ssl", "pyOpenSSL"] } @@ -49,7 +84,7 @@ abstract class TlsLibrary extends string { abstract string specific_insecure_version_name(ProtocolVersion version); /** The name of an unspecific protocol version, say TLS, known to have insecure instances. */ - abstract string unspecific_version_name(); + abstract string unspecific_version_name(ProtocolFamily family); /** The module or class holding the version constants. */ abstract API::Node version_constants(); @@ -60,8 +95,8 @@ abstract class TlsLibrary extends string { } /** A dataflow node representing an unspecific protocol version, say TLS, known to have insecure instances. */ - DataFlow::Node unspecific_version() { - result = version_constants().getMember(unspecific_version_name()).getAUse() + DataFlow::Node unspecific_version(ProtocolFamily family) { + result = version_constants().getMember(unspecific_version_name(family)).getAUse() } /** The creation of a context with a deafult protocol. */ @@ -77,11 +112,11 @@ abstract class TlsLibrary extends string { } /** The creation of a context with an unspecific protocol version, say TLS, known to have insecure instances. */ - DataFlow::CfgNode unspecific_context_creation() { + DataFlow::CfgNode unspecific_context_creation(ProtocolFamily family) { result = default_context_creation() or result = specific_context_creation() and - result.(ContextCreation).getProtocol() = unspecific_version() + result.(ContextCreation).getProtocol() = unspecific_version(family) } /** A connection is created in an insecure manner, not from a context. */ @@ -92,4 +127,7 @@ abstract class TlsLibrary extends string { /** A context is being restricted on which protocols it can accepts. */ abstract ProtocolRestriction protocol_restriction(); + + /** A context is being relaxed on which protocols it can accepts. */ + abstract ProtocolUnrestriction protocol_unrestriction(); } diff --git a/python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.expected b/python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.expected index e116662ce65..afd9cc15d9f 100644 --- a/python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.expected +++ b/python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.expected @@ -1,32 +1,40 @@ -| InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified in $@ | InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | -| InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv3 specified in $@ | InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | -| InsecureProtocol.py:8:1:8:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version TLSv1 specified in $@ | InsecureProtocol.py:8:1:8:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | -| InsecureProtocol.py:10:1:10:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified in $@ | InsecureProtocol.py:10:1:10:39 | ControlFlowNode for SSLContext() | call to SSLContext | -| InsecureProtocol.py:11:1:11:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv3 specified in $@ | InsecureProtocol.py:11:1:11:39 | ControlFlowNode for SSLContext() | call to SSLContext | -| InsecureProtocol.py:12:1:12:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version TLSv1 specified in $@ | InsecureProtocol.py:12:1:12:39 | ControlFlowNode for SSLContext() | call to SSLContext | -| InsecureProtocol.py:14:1:14:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified in $@ | InsecureProtocol.py:14:1:14:29 | ControlFlowNode for Attribute() | call to SSL.Context | -| InsecureProtocol.py:16:1:16:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv3 specified in $@ | InsecureProtocol.py:16:1:16:29 | ControlFlowNode for Attribute() | call to SSL.Context | -| InsecureProtocol.py:17:1:17:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version TLSv1 specified in $@ | InsecureProtocol.py:17:1:17:29 | ControlFlowNode for Attribute() | call to SSL.Context | -| InsecureProtocol.py:32:1:32:19 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified in $@ | InsecureProtocol.py:32:1:32:19 | ControlFlowNode for Attribute() | call to SSL.Context | -| InsecureProtocol.py:48:1:48:43 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified in $@ | InsecureProtocol.py:48:1:48:43 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | -| InsecureProtocol.py:49:1:49:35 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified in $@ | InsecureProtocol.py:49:1:49:35 | ControlFlowNode for SSLContext() | call to SSLContext | -| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 specified in $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 specified in $@ | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:19:14:19:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:15:15:15:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:37:14:37:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 specified in $@ | ssl_fluent.py:34:15:34:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:37:14:37:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:34:15:34:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:47:14:47:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:43:15:43:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:75:14:75:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 specified in $@ | ssl_fluent.py:71:15:71:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:75:14:75:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:71:15:71:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 specified in $@ | ssl_fluent.py:89:12:89:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 specified in $@ | ssl_fluent.py:128:15:128:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:89:12:89:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:128:15:128:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:104:14:104:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 specified in $@ | ssl_fluent.py:89:12:89:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:104:14:104:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:89:12:89:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:173:14:173:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:169:15:169:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:192:14:192:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 specified in $@ | ssl_fluent.py:188:15:188:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context | -| ssl_fluent.py:192:14:192:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 specified in $@ | ssl_fluent.py:188:15:188:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context | +| InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | +| InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv3 specified by $@ | InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | +| InsecureProtocol.py:8:1:8:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version TLSv1 specified by $@ | InsecureProtocol.py:8:1:8:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | +| InsecureProtocol.py:10:1:10:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:10:1:10:39 | ControlFlowNode for SSLContext() | call to SSLContext | +| InsecureProtocol.py:11:1:11:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv3 specified by $@ | InsecureProtocol.py:11:1:11:39 | ControlFlowNode for SSLContext() | call to SSLContext | +| InsecureProtocol.py:12:1:12:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version TLSv1 specified by $@ | InsecureProtocol.py:12:1:12:39 | ControlFlowNode for SSLContext() | call to SSLContext | +| InsecureProtocol.py:14:1:14:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:14:1:14:29 | ControlFlowNode for Attribute() | call to SSL.Context | +| InsecureProtocol.py:16:1:16:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv3 specified by $@ | InsecureProtocol.py:16:1:16:29 | ControlFlowNode for Attribute() | call to SSL.Context | +| InsecureProtocol.py:17:1:17:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version TLSv1 specified by $@ | InsecureProtocol.py:17:1:17:29 | ControlFlowNode for Attribute() | call to SSL.Context | +| InsecureProtocol.py:32:1:32:19 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:32:1:32:19 | ControlFlowNode for Attribute() | call to SSL.Context | +| InsecureProtocol.py:48:1:48:43 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:48:1:48:43 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | +| InsecureProtocol.py:49:1:49:35 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:49:1:49:35 | ControlFlowNode for SSLContext() | call to SSLContext | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@ | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@ | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:29:27:29:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@ | pyOpenSSL_fluent.py:25:15:25:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:29:27:29:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@ | pyOpenSSL_fluent.py:25:15:25:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:19:14:19:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:15:15:15:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:37:14:37:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:34:15:34:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:37:14:37:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:34:15:34:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:47:14:47:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:43:15:43:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:75:14:75:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:71:15:71:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:75:14:75:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:71:15:71:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:89:12:89:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:128:15:128:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:89:12:89:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:128:15:128:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:144:5:144:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:98:14:98:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:162:5:162:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:104:14:104:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:89:12:89:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:104:14:104:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:89:12:89:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:124:14:124:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:122:5:122:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:173:14:173:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:170:5:170:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:192:14:192:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@ | ssl_fluent.py:189:5:189:11 | ControlFlowNode for context | context modification |