Files
codeql/python/ql/src/Security/CWE-327/TlsLibraryModel.qll
2021-03-26 17:51:18 +01:00

143 lines
5.1 KiB
Plaintext

import python
import semmle.python.ApiGraphs
import Ssl
import PyOpenSSL
/**
* A specific protocol version.
* We use this to identify a protocol.
*/
class ProtocolVersion extends string {
ProtocolVersion() { this in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] }
predicate lessThan(ProtocolVersion version) {
this = "SSLv2" and version = "SSLv3"
or
this = "TLSv1" and version = ["TLSv1_1", "TLSv1_2", "TLSv1_3"]
or
this = ["TLSv1", "TLSv1_1"] and version = ["TLSv1_2", "TLSv1_3"]
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. */
abstract class ContextCreation extends DataFlow::CfgNode {
/** Gets the requested protocol if any. */
abstract DataFlow::CfgNode getProtocol();
}
/** The creation of a connection from a context. */
abstract class ConnectionCreation extends DataFlow::CfgNode {
/** Gets the context used to create the connection. */
abstract DataFlow::CfgNode getContext();
}
/** A context is being restricted on which protocols it can accepts. */
abstract class ProtocolRestriction extends DataFlow::CfgNode {
/** Gets the context being restricted. */
abstract DataFlow::CfgNode getContext();
/** Gets the protocol version being disallowed. */
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();
}
/**
* 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() = library.unspecific_version(family) }
override DataFlow::CfgNode getContext() { result = this }
override ProtocolVersion getUnrestriction() {
// see https://www.openssl.org/docs/man1.1.0/man3/TLS_method.html
family = "TLS" and
result in ["SSLv3", "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
// - https://www.openssl.org/docs/man1.0.2/man3/TLSv1_method.html
family = "SSLv23" and
result in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"]
}
}
/** A model of a TLS library. */
abstract class TlsLibrary extends string {
TlsLibrary() { this in ["ssl", "pyOpenSSL"] }
/** The name of a specific protocol version. */
abstract string specific_version_name(ProtocolVersion version);
/** The name of an unspecific protocol version, say TLS, known to have insecure instances. */
abstract string unspecific_version_name(ProtocolFamily family);
/** The module or class holding the version constants. */
abstract API::Node version_constants();
/** A dataflow node representing a specific protocol version, known to be insecure. */
DataFlow::Node insecure_version(ProtocolVersion version) {
version.isInsecure() and
result = version_constants().getMember(specific_version_name(version)).getAUse()
}
/** A dataflow node representing an unspecific protocol version, say TLS, known to have insecure instances. */
DataFlow::Node unspecific_version(ProtocolFamily family) {
result = version_constants().getMember(unspecific_version_name(family)).getAUse()
}
/** The creation of a context with a deafult protocol. */
abstract ContextCreation default_context_creation();
/** The creation of a context with a specific protocol. */
abstract ContextCreation specific_context_creation();
/** The creation of a context with a specific protocol version, known to be insecure. */
ContextCreation insecure_context_creation(ProtocolVersion version) {
result = specific_context_creation() and
result.getProtocol() = insecure_version(version)
}
/** The creation of a context with an unspecific protocol version, say TLS, known to have insecure instances. */
DataFlow::CfgNode unspecific_context_creation(ProtocolFamily family) {
result = default_context_creation()
or
result = specific_context_creation() and
result.(ContextCreation).getProtocol() = unspecific_version(family)
}
/** A connection is created in an insecure manner, not from a context. */
abstract DataFlow::CfgNode insecure_connection_creation(ProtocolVersion version);
/** A connection is created from a context. */
abstract ConnectionCreation connection_creation();
/** 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();
}