mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Python: Adjust InsecureProtocol query.
This commit is contained in:
@@ -20,48 +20,100 @@ import TlsLibraryModel
|
||||
* Since we really want "the last unrestriction, not nullified by a restriction",
|
||||
* we also disallow flow into restrictions.
|
||||
*/
|
||||
class InsecureContextConfiguration extends DataFlow::Configuration {
|
||||
TlsLibrary library;
|
||||
ProtocolVersion tracked_version;
|
||||
module InsecureContextConfiguration2 implements DataFlow::StateConfigSig {
|
||||
private newtype TFlowState =
|
||||
TMkFlowState(TlsLibrary library, int bits) {
|
||||
bits in [0 .. max(any(ProtocolVersion v).getBit()) * 2 - 1]
|
||||
}
|
||||
|
||||
InsecureContextConfiguration() {
|
||||
this = library + "Allows" + tracked_version and
|
||||
tracked_version.isInsecure()
|
||||
class FlowState extends TFlowState {
|
||||
int getBits() { this = TMkFlowState(_, result) }
|
||||
|
||||
TlsLibrary getLibrary() { this = TMkFlowState(result, _) }
|
||||
|
||||
predicate allowsInsecureVersion(ProtocolVersion v) {
|
||||
v.isInsecure() and this.getBits().bitAnd(v.getBit()) != 0
|
||||
}
|
||||
|
||||
string toString() {
|
||||
result =
|
||||
"FlowState(" + this.getLibrary().toString() + ", " +
|
||||
concat(ProtocolVersion v | this.allowsInsecureVersion(v) | v, ", ") + ")"
|
||||
}
|
||||
}
|
||||
|
||||
ProtocolVersion getTrackedVersion() { result = tracked_version }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { this.isUnrestriction(source) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = library.connection_creation().getContext()
|
||||
}
|
||||
|
||||
override predicate isBarrierIn(DataFlow::Node node) {
|
||||
this.isRestriction(node)
|
||||
private predicate relevantState(FlowState state) {
|
||||
isSource(_, state)
|
||||
or
|
||||
this.isUnrestriction(node)
|
||||
}
|
||||
|
||||
private predicate isRestriction(DataFlow::Node node) {
|
||||
exists(ProtocolRestriction r |
|
||||
r = library.protocol_restriction() and
|
||||
r.getRestriction() = tracked_version
|
||||
|
|
||||
node = r.getContext()
|
||||
exists(FlowState state0 | relevantState(state0) |
|
||||
exists(ProtocolRestriction r |
|
||||
r = state0.getLibrary().protocol_restriction() and
|
||||
state.getBits() = state0.getBits().bitAnd(sum(r.getRestriction().getBit()).bitNot()) and
|
||||
state0.getLibrary() = state.getLibrary()
|
||||
)
|
||||
or
|
||||
exists(ProtocolUnrestriction pu |
|
||||
pu = state0.getLibrary().protocol_unrestriction() and
|
||||
state.getBits() = state0.getBits().bitOr(sum(pu.getUnrestriction().getBit())) and
|
||||
state0.getLibrary() = state.getLibrary()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isUnrestriction(DataFlow::Node node) {
|
||||
exists(ProtocolUnrestriction pu |
|
||||
pu = library.protocol_unrestriction() and
|
||||
pu.getUnrestriction() = tracked_version
|
||||
|
|
||||
node = pu.getContext()
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
exists(ProtocolFamily family |
|
||||
source = state.getLibrary().unspecific_context_creation(family) and
|
||||
state.getBits() = family.getBits()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
sink = state.getLibrary().connection_creation().getContext() and
|
||||
state.allowsInsecureVersion(_)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
DataFlow::localFlowStep(node1, node2) and
|
||||
relevantState(state1) and
|
||||
(
|
||||
exists(ProtocolRestriction r |
|
||||
r = state1.getLibrary().protocol_restriction() and
|
||||
node2 = r.getContext() and
|
||||
state2.getBits() = state1.getBits().bitAnd(sum(r.getRestriction().getBit()).bitNot()) and
|
||||
state1.getLibrary() = state2.getLibrary()
|
||||
)
|
||||
or
|
||||
exists(ProtocolUnrestriction pu |
|
||||
pu = state1.getLibrary().protocol_unrestriction() and
|
||||
node2 = pu.getContext() and
|
||||
state2.getBits() = state1.getBits().bitOr(sum(pu.getUnrestriction().getBit())) and
|
||||
state1.getLibrary() = state2.getLibrary()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) {
|
||||
relevantState(state) and
|
||||
(
|
||||
exists(ProtocolRestriction r |
|
||||
r = state.getLibrary().protocol_restriction() and
|
||||
node = r.getContext() and
|
||||
state.allowsInsecureVersion(r.getRestriction())
|
||||
)
|
||||
or
|
||||
exists(ProtocolUnrestriction pu |
|
||||
pu = state.getLibrary().protocol_unrestriction() and
|
||||
node = pu.getContext() and
|
||||
not state.allowsInsecureVersion(pu.getUnrestriction())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private module InsecureContextFlow = DataFlow::MakeWithState<InsecureContextConfiguration2>;
|
||||
|
||||
/**
|
||||
* Holds if `conectionCreation` marks the creation of a connection based on the contex
|
||||
* found at `contextOrigin` and allowing `insecure_version`.
|
||||
@@ -74,8 +126,11 @@ predicate unsafe_connection_creation_with_context(
|
||||
boolean specific
|
||||
) {
|
||||
// Connection created from a context allowing `insecure_version`.
|
||||
exists(InsecureContextConfiguration c | c.hasFlow(contextOrigin, connectionCreation) |
|
||||
insecure_version = c.getTrackedVersion() and
|
||||
exists(InsecureContextFlow::PathNode src, InsecureContextFlow::PathNode sink |
|
||||
InsecureContextFlow::hasFlowPath(src, sink) and
|
||||
src.getNode() = contextOrigin and
|
||||
sink.getNode() = connectionCreation and
|
||||
sink.getState().allowsInsecureVersion(insecure_version) and
|
||||
specific = false
|
||||
)
|
||||
or
|
||||
|
||||
@@ -52,7 +52,7 @@ class SetOptionsCall extends ProtocolRestriction, DataFlow::CallCfgNode {
|
||||
}
|
||||
|
||||
class UnspecificPyOpenSslContextCreation extends PyOpenSslContextCreation, UnspecificContextCreation {
|
||||
UnspecificPyOpenSslContextCreation() { library instanceof PyOpenSsl }
|
||||
// UnspecificPyOpenSslContextCreation() { library instanceof PyOpenSsl }
|
||||
}
|
||||
|
||||
class PyOpenSsl extends TlsLibrary {
|
||||
|
||||
@@ -162,23 +162,21 @@ class ContextSetVersion extends ProtocolRestriction, ProtocolUnrestriction, Data
|
||||
}
|
||||
|
||||
class UnspecificSslContextCreation extends SslContextCreation, UnspecificContextCreation {
|
||||
UnspecificSslContextCreation() { library instanceof Ssl }
|
||||
|
||||
override ProtocolVersion getUnrestriction() {
|
||||
result = UnspecificContextCreation.super.getUnrestriction() and
|
||||
// These are turned off by default since Python 3.6
|
||||
// see https://docs.python.org/3.6/library/ssl.html#ssl.SSLContext
|
||||
not result in ["SSLv2", "SSLv3"]
|
||||
}
|
||||
// UnspecificSslContextCreation() { library instanceof Ssl }
|
||||
// override ProtocolVersion getUnrestriction() {
|
||||
// result = UnspecificContextCreation.super.getUnrestriction() and
|
||||
// // These are turned off by default since Python 3.6
|
||||
// // see https://docs.python.org/3.6/library/ssl.html#ssl.SSLContext
|
||||
// not result in ["SSLv2", "SSLv3"]
|
||||
// }
|
||||
}
|
||||
|
||||
class UnspecificSslDefaultContextCreation extends SslDefaultContextCreation, ProtocolUnrestriction {
|
||||
override DataFlow::Node getContext() { result = this }
|
||||
|
||||
// see https://docs.python.org/3/library/ssl.html#ssl.create_default_context
|
||||
override ProtocolVersion getUnrestriction() {
|
||||
result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"]
|
||||
}
|
||||
class UnspecificSslDefaultContextCreation extends SslDefaultContextCreation {
|
||||
// override DataFlow::Node getContext() { result = this }
|
||||
// // see https://docs.python.org/3/library/ssl.html#ssl.create_default_context
|
||||
// override ProtocolVersion getUnrestriction() {
|
||||
// result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"]
|
||||
// }
|
||||
}
|
||||
|
||||
class Ssl extends TlsLibrary {
|
||||
|
||||
@@ -15,18 +15,45 @@ class ProtocolVersion extends string {
|
||||
or
|
||||
this = "TLSv1" and version = ["TLSv1_1", "TLSv1_2", "TLSv1_3"]
|
||||
or
|
||||
this = ["TLSv1", "TLSv1_1"] and version = ["TLSv1_2", "TLSv1_3"]
|
||||
this = "TLSv1_1" and version = ["TLSv1_2", "TLSv1_3"]
|
||||
or
|
||||
this = ["TLSv1", "TLSv1_1", "TLSv1_2"] and version = "TLSv1_3"
|
||||
this = "TLSv1_2" and version = "TLSv1_3"
|
||||
}
|
||||
|
||||
/** Holds if this protocol version is known to be insecure. */
|
||||
predicate isInsecure() { this in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1"] }
|
||||
|
||||
/** Gets the bit mask for this protocol version. */
|
||||
int getBit() {
|
||||
this = "SSLv2" and result = 1
|
||||
or
|
||||
this = "SSLv3" and result = 2
|
||||
or
|
||||
this = "TLSv1" and result = 4
|
||||
or
|
||||
this = "TLSv1_1" and result = 8
|
||||
or
|
||||
this = "TLSv1_2" and result = 16
|
||||
or
|
||||
this = "TLSv1_3" and result = 32
|
||||
}
|
||||
|
||||
/** Gets the protocol family for this protocol version. */
|
||||
ProtocolFamily getFamily() {
|
||||
result = "SSLv23" and this in ["SSLv2", "SSLv3"]
|
||||
or
|
||||
result = "TLS" and this in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"]
|
||||
}
|
||||
}
|
||||
|
||||
/** An unspecific protocol version */
|
||||
class ProtocolFamily extends string {
|
||||
ProtocolFamily() { this in ["SSLv23", "TLS"] }
|
||||
|
||||
/** Gets the bit mask for this protocol family. */
|
||||
int getBits() {
|
||||
result = sum(ProtocolVersion version | version.getFamily() = this | version.getBit())
|
||||
}
|
||||
}
|
||||
|
||||
/** The creation of a context. */
|
||||
@@ -63,21 +90,14 @@ abstract class ProtocolUnrestriction extends DataFlow::Node {
|
||||
* A context is being created with a range of allowed protocols.
|
||||
* This also serves as unrestricting these protocols.
|
||||
*/
|
||||
abstract class UnspecificContextCreation extends ContextCreation, ProtocolUnrestriction {
|
||||
TlsLibrary library;
|
||||
ProtocolFamily family;
|
||||
|
||||
UnspecificContextCreation() { this.getProtocol() = family }
|
||||
|
||||
override DataFlow::CfgNode getContext() { result = this }
|
||||
|
||||
override ProtocolVersion getUnrestriction() {
|
||||
// There is only one family, the two names are aliases in OpenSSL.
|
||||
// see https://github.com/openssl/openssl/blob/13888e797c5a3193e91d71e5f5a196a2d68d266f/include/openssl/ssl.h.in#L1953-L1955
|
||||
family in ["SSLv23", "TLS"] and
|
||||
// see https://docs.python.org/3/library/ssl.html#ssl-contexts
|
||||
result in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"]
|
||||
}
|
||||
abstract class UnspecificContextCreation extends ContextCreation {
|
||||
// override ProtocolVersion getUnrestriction() {
|
||||
// // There is only one family, the two names are aliases in OpenSSL.
|
||||
// // see https://github.com/openssl/openssl/blob/13888e797c5a3193e91d71e5f5a196a2d68d266f/include/openssl/ssl.h.in#L1953-L1955
|
||||
// family in ["SSLv23", "TLS"] and
|
||||
// // see https://docs.python.org/3/library/ssl.html#ssl-contexts
|
||||
// result in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"]
|
||||
// }
|
||||
}
|
||||
|
||||
/** A model of a SSL/TLS library. */
|
||||
|
||||
@@ -12,28 +12,25 @@
|
||||
| InsecureProtocol.py:24:1:24:35 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:24:1:24: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 |
|
||||
| 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:28:14:28:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:24:15:24:53 | 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:33:15:33:53 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:101:15:101:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:71:14:71: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:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:101:15:101:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:117:5:117:11 | ControlFlowNode for context | context modification |
|
||||
| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:135:5:135:11 | ControlFlowNode for context | context modification |
|
||||
| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:115:15:115:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:77:14:77:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:77:14:77:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
|
||||
| ssl_fluent.py:97:14:97:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:95:5:95:11 | ControlFlowNode for context | context modification |
|
||||
| ssl_fluent.py:146:14:146:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:143:5:143:11 | ControlFlowNode for context | context modification |
|
||||
| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | ssl_fluent.py:162:5:162:11 | ControlFlowNode for context | context modification |
|
||||
| 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 |
|
||||
|
||||
Reference in New Issue
Block a user