diff --git a/ql/src/experimental/CWE-327/InsecureTLS.go b/ql/src/experimental/CWE-327/InsecureTLS.go new file mode 100644 index 00000000000..4d78dbc2aa9 --- /dev/null +++ b/ql/src/experimental/CWE-327/InsecureTLS.go @@ -0,0 +1,31 @@ +package main + +import ( + "crypto/tls" +) + +func main() {} + +func insecureMinMaxTlsVersion() { + { + config := &tls.Config{} + config.MinVersion = 0 //BAD: Setting the MinVersion to 0 equal to choosing the lowest supported version (i.e. SSL3.0) + } + { + config := &tls.Config{} + config.MinVersion = tls.VersionSSL30 //BAD: SSL 3.0 is a non-secure version of the protocol; it's not safe to use it as MinVersion. + } + { + config := &tls.Config{} + config.MaxVersion = tls.VersionSSL30 //BAD: SSL 3.0 is a non-secure version of the protocol; it's not safe to use it as MaxVersion. + } +} + +func insecureCipherSuites() { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_RSA_WITH_RC4_128_SHA, //BAD: TLS_RSA_WITH_RC4_128_SHA is one of the non-secure chiper suites; it's not safe to be used. + }, + } + _ = config +} diff --git a/ql/src/experimental/CWE-327/InsecureTLS.qhelp b/ql/src/experimental/CWE-327/InsecureTLS.qhelp new file mode 100644 index 00000000000..fcdb3d8875b --- /dev/null +++ b/ql/src/experimental/CWE-327/InsecureTLS.qhelp @@ -0,0 +1,47 @@ + + + +

+ The TLS (Transport Layer Security) protocol secures communications over the Internet. + The protocol allows client/server applications to communicate in a way that is designed + to prevent eavesdropping, tampering, or message forgery. +

+

+ The current latest version is 1.3 (with the 1.2 version still being considered secure). + Older versions are not deemed to be secure anymore because of various security vulnerabilities, + and tht makes them unfit for use in securing your applications. +

+

+ Unfortunately, many applications and websites still support deprecated SSL/TLS versions and + cipher suites. +

+
+ +

+ Only use secure TLS versions (1.3 and 1.2) and avoid using insecure cipher suites + (you can see a list here: https://golang.org/src/crypto/tls/cipher_suites.go#L81) +

+
+ +

+ The following example shows a few ways how an insecure TLS configuration can be created: +

+ +

+ The following example shows how to create a safer TLS configuration: +

+ +
+ +
  • + Wikipedia: + Transport Layer Security +
  • +
  • + OWASP: + Transport Layer Protection Cheat Sheet +
  • +
    +
    \ No newline at end of file diff --git a/ql/src/experimental/CWE-327/InsecureTLS.ql b/ql/src/experimental/CWE-327/InsecureTLS.ql new file mode 100644 index 00000000000..0f7af28e035 --- /dev/null +++ b/ql/src/experimental/CWE-327/InsecureTLS.ql @@ -0,0 +1,160 @@ +/** + * @name Insecure TLS configuration + * @description If an application supports insecure TLS versions or ciphers, it may be vulnerable to + * man-in-the-middle and other attacks. + * @kind path-problem + * @problem.severity warning + * @id go/insecure-tls + * @tags security + * external/cwe/cwe-327 + */ + +import go +import DataFlow::PathGraph + +/** + * Check whether the file where the node is located is a test file. + */ +predicate isTestFile(DataFlow::Node node) { + // Exclude results in test files: + exists(File fl | fl = node.getRoot().getFile() | + fl instanceof TestFile or fl.getPackageName() = "tests" + ) +} + +/** + * Returns the name of the write target field. + */ +string getSinkTargetFieldName(DataFlow::PathNode sink) { + result = any(DataFlow::Field fld | fld.getAWrite().getRhs() = sink.getNode()).getName() +} + +/** + * Returns the name of a ValueEntity. + */ +string getSourceValueEntityName(DataFlow::PathNode source) { + result = + any(DataFlow::ValueEntity val | source.getNode().(DataFlow::ReadNode).reads(val)).getName() +} + +/** + * Flow of unsecure TLS versions into a `tls.Config` struct, + * to the `MinVersion` and `MaxVersion` fields. + */ +class TlsVersionFlowConfig extends TaintTracking::Configuration { + TlsVersionFlowConfig() { this = "TlsVersionFlowConfig" } + + override predicate isSource(DataFlow::Node source) { + source.asExpr() = any(DataFlow::ValueExpr val | val.getIntValue() = [0]) or + source = + any(DataFlow::ValueEntity val | + val.hasQualifiedName("crypto/tls", ["VersionSSL30", "VersionTLS10", "VersionTLS11"]) + ).getARead() + } + + override predicate isSink(DataFlow::Node sink) { + exists(Write write | + write = + any(DataFlow::Field fld | + fld.hasQualifiedName("crypto/tls", "Config", ["MinVersion", "MaxVersion"]) + ).getAWrite() and + // The write must NOT happen inside a switch statement: + not exists(ExpressionSwitchStmt switch | + switch.getBody().getAChildStmt().getChild(0) = + any(Assignment asign | asign.getRhs() = sink.asExpr()) + ) + | + sink = write.getRhs() + ) + } + + override predicate isSanitizer(DataFlow::Node node) { isTestFile(node) } +} + +/** + * Find insecure TLS versions. + */ +predicate checkTlsVersions(DataFlow::PathNode source, DataFlow::PathNode sink, string message) { + exists(TlsVersionFlowConfig cfg | + cfg.hasFlowPath(source, sink) and + // Exclude tls.Config.Max = 0 (which is OK): + not exists(Write write, DataFlow::ValueExpr v0 | write.getRhs() = sink.getNode() | + v0 = source.getNode().asExpr() and + v0.getIntValue() = 0 and + exists(DataFlow::Field fld | + fld.hasQualifiedName("crypto/tls", "Config", "MaxVersion") and + fld.getAWrite().getRhs() = sink.getNode() + ) + ) + | + message = + "TLS version too low for " + getSinkTargetFieldName(sink) + ": " + + getSourceValueEntityName(source) + or + message = "Using lowest TLS version for " + getSinkTargetFieldName(sink) and + exists(DataFlow::ValueExpr v0 | + v0 = sink.getNode().asExpr() and + v0.getIntValue() = 0 + ) + ) +} + +/** + * Flow of unsecure TLS cipher suites into a `tls.Config` struct, + * to the `CipherSuites` field. + */ +class TlsInsecureCipherSuitesFlowConfig extends TaintTracking::Configuration { + TlsInsecureCipherSuitesFlowConfig() { this = "TlsInsecureCipherSuitesFlowConfig" } + + override predicate isSource(DataFlow::Node source) { + // TODO: source can also be result of tls.InsecureCipherSuites()[0].ID + source = + any(DataFlow::FieldReadNode fieldRead | + fieldRead.getBase().getAPredecessor*() = + any(Function insecureCipherSuites | + insecureCipherSuites.hasQualifiedName("crypto/tls", "InsecureCipherSuites") + ).getACall().getResult() and + fieldRead.getFieldName() = "ID" + ) + or + source = + any(DataFlow::ValueEntity val | + val + .hasQualifiedName("crypto/tls", + any(string suiteName | + suiteName = "TLS_RSA_WITH_RC4_128_SHA" or + suiteName = "TLS_RSA_WITH_AES_128_CBC_SHA256" or + suiteName = "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA" or + suiteName = "TLS_ECDHE_RSA_WITH_RC4_128_SHA" or + suiteName = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" or + suiteName = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" + )) + ).getARead() + } + + override predicate isSink(DataFlow::Node sink) { + sink = + any(DataFlow::Field fld | fld.hasQualifiedName("crypto/tls", "Config", "CipherSuites")) + .getAWrite() + .getRhs() + } + + override predicate isSanitizer(DataFlow::Node node) { isTestFile(node) } +} + +/** + * Find insecure TLS cipher suites. + */ +predicate checkTlsInsecureCipherSuites( + DataFlow::PathNode source, DataFlow::PathNode sink, string message +) { + exists(TlsInsecureCipherSuitesFlowConfig cfg | cfg.hasFlowPath(source, sink) | + message = "Use of an insecure cipher suite: " + getSourceValueEntityName(source) + ) +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, string message +where + checkTlsVersions(source, sink, message) or + checkTlsInsecureCipherSuites(source, sink, message) +select sink.getNode(), source, sink, message diff --git a/ql/src/experimental/CWE-327/SaferTLS.go b/ql/src/experimental/CWE-327/SaferTLS.go new file mode 100644 index 00000000000..b3e9fce2a4f --- /dev/null +++ b/ql/src/experimental/CWE-327/SaferTLS.go @@ -0,0 +1,11 @@ +package main + +import "crypto/tls" + +func saferTLSConfig() { + config := &tls.Config{} + config.MinVersion = tls.VersionTLS12 + config.MaxVersion = tls.VersionTLS13 + // OR + config.MaxVersion = 0 // Setting MaxVersion to 0 means that the highest version available in the package will be used. +} diff --git a/ql/test/experimental/CWE-327/UnsafeTLS.expected b/ql/test/experimental/CWE-327/UnsafeTLS.expected new file mode 100644 index 00000000000..c6591fdc957 --- /dev/null +++ b/ql/test/experimental/CWE-327/UnsafeTLS.expected @@ -0,0 +1,100 @@ +edges +| UnsafeTLS.go:91:5:91:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | +| UnsafeTLS.go:92:5:92:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | +| UnsafeTLS.go:93:5:93:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | +| UnsafeTLS.go:94:5:94:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | +| UnsafeTLS.go:95:5:95:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | +| UnsafeTLS.go:96:5:96:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | +| UnsafeTLS.go:104:5:104:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:103:18:105:4 | slice literal | +| UnsafeTLS.go:112:5:112:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:111:18:113:4 | slice literal | +| UnsafeTLS.go:120:5:120:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:119:18:121:4 | slice literal | +| UnsafeTLS.go:128:5:128:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:127:18:129:4 | slice literal | +| UnsafeTLS.go:136:5:136:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:135:18:137:4 | slice literal | +| UnsafeTLS.go:144:5:144:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:143:18:145:4 | slice literal | +| UnsafeTLS.go:158:3:158:8 | definition of config [pointer, CipherSuites] | UnsafeTLS.go:159:3:159:8 | config [pointer, CipherSuites] | +| UnsafeTLS.go:158:3:158:8 | definition of config [pointer, CipherSuites] | UnsafeTLS.go:160:3:160:8 | config [pointer, CipherSuites] | +| UnsafeTLS.go:158:3:158:8 | definition of config [pointer, CipherSuites] | UnsafeTLS.go:160:32:160:37 | config [pointer, CipherSuites] | +| UnsafeTLS.go:159:3:159:8 | config [pointer, CipherSuites] | UnsafeTLS.go:159:3:159:8 | implicit dereference [CipherSuites] : slice type | +| UnsafeTLS.go:159:3:159:8 | implicit dereference [CipherSuites] : slice type | UnsafeTLS.go:158:3:158:8 | definition of config [pointer, CipherSuites] | +| UnsafeTLS.go:160:3:160:8 | config [pointer, CipherSuites] | UnsafeTLS.go:160:3:160:8 | implicit dereference [CipherSuites] : slice type | +| UnsafeTLS.go:160:3:160:8 | implicit dereference [CipherSuites] : slice type | UnsafeTLS.go:158:3:158:8 | definition of config [pointer, CipherSuites] | +| UnsafeTLS.go:160:25:160:94 | call to append : slice type | UnsafeTLS.go:160:3:160:8 | implicit dereference [CipherSuites] : slice type | +| UnsafeTLS.go:160:32:160:37 | config [pointer, CipherSuites] | UnsafeTLS.go:160:32:160:37 | implicit dereference [CipherSuites] : slice type | +| UnsafeTLS.go:160:32:160:37 | implicit dereference [CipherSuites] : slice type | UnsafeTLS.go:160:32:160:50 | selection of CipherSuites : slice type | +| UnsafeTLS.go:160:32:160:50 | selection of CipherSuites : slice type | UnsafeTLS.go:160:25:160:94 | call to append | +| UnsafeTLS.go:160:32:160:50 | selection of CipherSuites : slice type | UnsafeTLS.go:160:25:160:94 | call to append : slice type | +| UnsafeTLS.go:160:53:160:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:160:25:160:94 | call to append | +| UnsafeTLS.go:160:53:160:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:160:25:160:94 | call to append : slice type | +nodes +| UnsafeTLS.go:14:23:14:23 | 0 | semmle.label | 0 | +| UnsafeTLS.go:18:23:18:23 | 0 | semmle.label | 0 | +| UnsafeTLS.go:23:16:23:16 | 0 | semmle.label | 0 | +| UnsafeTLS.go:29:16:29:16 | 0 | semmle.label | 0 | +| UnsafeTLS.go:36:23:36:38 | selection of VersionSSL30 | semmle.label | selection of VersionSSL30 | +| UnsafeTLS.go:40:23:40:38 | selection of VersionSSL30 | semmle.label | selection of VersionSSL30 | +| UnsafeTLS.go:45:23:45:38 | selection of VersionTLS10 | semmle.label | selection of VersionTLS10 | +| UnsafeTLS.go:49:23:49:38 | selection of VersionTLS10 | semmle.label | selection of VersionTLS10 | +| UnsafeTLS.go:54:23:54:38 | selection of VersionTLS11 | semmle.label | selection of VersionTLS11 | +| UnsafeTLS.go:58:23:58:38 | selection of VersionTLS11 | semmle.label | selection of VersionTLS11 | +| UnsafeTLS.go:63:16:63:31 | selection of VersionTLS11 | semmle.label | selection of VersionTLS11 | +| UnsafeTLS.go:69:16:69:31 | selection of VersionTLS11 | semmle.label | selection of VersionTLS11 | +| UnsafeTLS.go:90:18:97:4 | slice literal | semmle.label | slice literal | +| UnsafeTLS.go:91:5:91:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:92:5:92:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:93:5:93:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:94:5:94:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:95:5:95:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:96:5:96:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:103:18:105:4 | slice literal | semmle.label | slice literal | +| UnsafeTLS.go:104:5:104:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:111:18:113:4 | slice literal | semmle.label | slice literal | +| UnsafeTLS.go:112:5:112:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:119:18:121:4 | slice literal | semmle.label | slice literal | +| UnsafeTLS.go:120:5:120:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:127:18:129:4 | slice literal | semmle.label | slice literal | +| UnsafeTLS.go:128:5:128:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:135:18:137:4 | slice literal | semmle.label | slice literal | +| UnsafeTLS.go:136:5:136:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:143:18:145:4 | slice literal | semmle.label | slice literal | +| UnsafeTLS.go:144:5:144:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:158:3:158:8 | definition of config [pointer, CipherSuites] | semmle.label | definition of config [pointer, CipherSuites] | +| UnsafeTLS.go:159:3:159:8 | config [pointer, CipherSuites] | semmle.label | config [pointer, CipherSuites] | +| UnsafeTLS.go:159:3:159:8 | implicit dereference [CipherSuites] : slice type | semmle.label | implicit dereference [CipherSuites] : slice type | +| UnsafeTLS.go:160:3:160:8 | config [pointer, CipherSuites] | semmle.label | config [pointer, CipherSuites] | +| UnsafeTLS.go:160:3:160:8 | implicit dereference [CipherSuites] : slice type | semmle.label | implicit dereference [CipherSuites] : slice type | +| UnsafeTLS.go:160:25:160:94 | call to append | semmle.label | call to append | +| UnsafeTLS.go:160:25:160:94 | call to append : slice type | semmle.label | call to append : slice type | +| UnsafeTLS.go:160:32:160:37 | config [pointer, CipherSuites] | semmle.label | config [pointer, CipherSuites] | +| UnsafeTLS.go:160:32:160:37 | implicit dereference [CipherSuites] : slice type | semmle.label | implicit dereference [CipherSuites] : slice type | +| UnsafeTLS.go:160:32:160:50 | selection of CipherSuites : slice type | semmle.label | selection of CipherSuites : slice type | +| UnsafeTLS.go:160:53:160:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:199:23:199:38 | selection of VersionTLS11 | semmle.label | selection of VersionTLS11 | +| UnsafeTLS.go:208:24:208:39 | selection of VersionTLS10 | semmle.label | selection of VersionTLS10 | +| UnsafeTLS.go:209:24:209:39 | selection of VersionTLS11 | semmle.label | selection of VersionTLS11 | +#select +| UnsafeTLS.go:14:23:14:23 | 0 | UnsafeTLS.go:14:23:14:23 | 0 | UnsafeTLS.go:14:23:14:23 | 0 | Using lowest TLS version for MinVersion | +| UnsafeTLS.go:23:16:23:16 | 0 | UnsafeTLS.go:23:16:23:16 | 0 | UnsafeTLS.go:23:16:23:16 | 0 | Using lowest TLS version for MinVersion | +| UnsafeTLS.go:36:23:36:38 | selection of VersionSSL30 | UnsafeTLS.go:36:23:36:38 | selection of VersionSSL30 | UnsafeTLS.go:36:23:36:38 | selection of VersionSSL30 | TLS version too low for MinVersion: VersionSSL30 | +| UnsafeTLS.go:40:23:40:38 | selection of VersionSSL30 | UnsafeTLS.go:40:23:40:38 | selection of VersionSSL30 | UnsafeTLS.go:40:23:40:38 | selection of VersionSSL30 | TLS version too low for MaxVersion: VersionSSL30 | +| UnsafeTLS.go:45:23:45:38 | selection of VersionTLS10 | UnsafeTLS.go:45:23:45:38 | selection of VersionTLS10 | UnsafeTLS.go:45:23:45:38 | selection of VersionTLS10 | TLS version too low for MinVersion: VersionTLS10 | +| UnsafeTLS.go:49:23:49:38 | selection of VersionTLS10 | UnsafeTLS.go:49:23:49:38 | selection of VersionTLS10 | UnsafeTLS.go:49:23:49:38 | selection of VersionTLS10 | TLS version too low for MaxVersion: VersionTLS10 | +| UnsafeTLS.go:54:23:54:38 | selection of VersionTLS11 | UnsafeTLS.go:54:23:54:38 | selection of VersionTLS11 | UnsafeTLS.go:54:23:54:38 | selection of VersionTLS11 | TLS version too low for MinVersion: VersionTLS11 | +| UnsafeTLS.go:58:23:58:38 | selection of VersionTLS11 | UnsafeTLS.go:58:23:58:38 | selection of VersionTLS11 | UnsafeTLS.go:58:23:58:38 | selection of VersionTLS11 | TLS version too low for MaxVersion: VersionTLS11 | +| UnsafeTLS.go:63:16:63:31 | selection of VersionTLS11 | UnsafeTLS.go:63:16:63:31 | selection of VersionTLS11 | UnsafeTLS.go:63:16:63:31 | selection of VersionTLS11 | TLS version too low for MinVersion: VersionTLS11 | +| UnsafeTLS.go:69:16:69:31 | selection of VersionTLS11 | UnsafeTLS.go:69:16:69:31 | selection of VersionTLS11 | UnsafeTLS.go:69:16:69:31 | selection of VersionTLS11 | TLS version too low for MaxVersion: VersionTLS11 | +| UnsafeTLS.go:90:18:97:4 | slice literal | UnsafeTLS.go:91:5:91:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:90:18:97:4 | slice literal | UnsafeTLS.go:92:5:92:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:90:18:97:4 | slice literal | UnsafeTLS.go:93:5:93:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:90:18:97:4 | slice literal | UnsafeTLS.go:94:5:94:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:90:18:97:4 | slice literal | UnsafeTLS.go:95:5:95:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:90:18:97:4 | slice literal | UnsafeTLS.go:96:5:96:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:90:18:97:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:103:18:105:4 | slice literal | UnsafeTLS.go:104:5:104:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:103:18:105:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:111:18:113:4 | slice literal | UnsafeTLS.go:112:5:112:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:111:18:113:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:119:18:121:4 | slice literal | UnsafeTLS.go:120:5:120:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:119:18:121:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:127:18:129:4 | slice literal | UnsafeTLS.go:128:5:128:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:127:18:129:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:135:18:137:4 | slice literal | UnsafeTLS.go:136:5:136:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:135:18:137:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:143:18:145:4 | slice literal | UnsafeTLS.go:144:5:144:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:143:18:145:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:160:25:160:94 | call to append | UnsafeTLS.go:160:53:160:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:160:25:160:94 | call to append | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:199:23:199:38 | selection of VersionTLS11 | UnsafeTLS.go:199:23:199:38 | selection of VersionTLS11 | UnsafeTLS.go:199:23:199:38 | selection of VersionTLS11 | TLS version too low for MinVersion: VersionTLS11 | +| UnsafeTLS.go:208:24:208:39 | selection of VersionTLS10 | UnsafeTLS.go:208:24:208:39 | selection of VersionTLS10 | UnsafeTLS.go:208:24:208:39 | selection of VersionTLS10 | TLS version too low for MinVersion: VersionTLS10 | +| UnsafeTLS.go:209:24:209:39 | selection of VersionTLS11 | UnsafeTLS.go:209:24:209:39 | selection of VersionTLS11 | UnsafeTLS.go:209:24:209:39 | selection of VersionTLS11 | TLS version too low for MinVersion: VersionTLS11 | diff --git a/ql/test/experimental/CWE-327/UnsafeTLS.go b/ql/test/experimental/CWE-327/UnsafeTLS.go new file mode 100644 index 00000000000..6c7c206eb8d --- /dev/null +++ b/ql/test/experimental/CWE-327/UnsafeTLS.go @@ -0,0 +1,214 @@ +package main + +import ( + "crypto/tls" +) + +func main() { + +} + +func minMaxTlsVersion() { + { + config := &tls.Config{} + config.MinVersion = 0 //BAD + } + { + config := &tls.Config{} + config.MaxVersion = 0 //GOOD + } + /// + { + config := &tls.Config{ + MinVersion: 0, //BAD + } + _ = config + } + { + config := &tls.Config{ + MaxVersion: 0, //GOOD + } + _ = config + } + /// + { + config := &tls.Config{} + config.MinVersion = tls.VersionSSL30 //BAD + } + { + config := &tls.Config{} + config.MaxVersion = tls.VersionSSL30 //BAD + } + /// + { + config := &tls.Config{} + config.MinVersion = tls.VersionTLS10 //BAD + } + { + config := &tls.Config{} + config.MaxVersion = tls.VersionTLS10 //BAD + } + /// + { + config := &tls.Config{} + config.MinVersion = tls.VersionTLS11 //BAD + } + { + config := &tls.Config{} + config.MaxVersion = tls.VersionTLS11 //BAD + } + /// + { + config := &tls.Config{ + MinVersion: tls.VersionTLS11, //BAD + } + _ = config + } + { + config := &tls.Config{ + MaxVersion: tls.VersionTLS11, //BAD + } + _ = config + } + { + config := &tls.Config{ + MinVersion: tls.VersionTLS12, //GOOD + } + _ = config + } + { + config := &tls.Config{ + MaxVersion: tls.VersionTLS13, //GOOD + } + _ = config + } +} + +func cipherSuites() { + { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_RSA_WITH_RC4_128_SHA, //BAD + tls.TLS_RSA_WITH_AES_128_CBC_SHA256, //BAD + tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, //BAD + tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, //BAD + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, //BAD + tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, //BAD + }, + } + _ = config + } + { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_RSA_WITH_RC4_128_SHA, //BAD + }, + } + _ = config + } + { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_RSA_WITH_AES_128_CBC_SHA256, //BAD + }, + } + _ = config + } + { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, //BAD + }, + } + _ = config + } + { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, //BAD + }, + } + _ = config + } + { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, //BAD + }, + } + _ = config + } + { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, //BAD + }, + } + _ = config + } + { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_CHACHA20_POLY1305_SHA256, //GOOD + }, + } + _ = config + } + { + config := &tls.Config{} + config.CipherSuites = make([]uint16, 0) + config.CipherSuites = append(config.CipherSuites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) //BAD + } + { + config := &tls.Config{} + config.CipherSuites = make([]uint16, 0) + insecureSuites := tls.InsecureCipherSuites() + for _, v := range insecureSuites { + config.CipherSuites = append(config.CipherSuites, v.ID) //BAD + } + } +} + +func good(version string) { + config := &tls.Config{} + + switch version { + case "1.0": + config.MinVersion = tls.VersionTLS10 //OK + case "1.1": + config.MinVersion = tls.VersionTLS11 //OK + default: + config.MinVersion = tls.VersionTLS12 //OK + } + + _ = config +} +func badTlsVersion2(version string) { + { + config := &tls.Config{} + + switch version { + case "1.0": + config.MinVersion = tls.VersionTLS10 //OK + case "1.1": + config.MinVersion = tls.VersionTLS11 //OK + default: + config.MinVersion = tls.VersionTLS12 //OK + } + + config.MinVersion = tls.VersionTLS11 //BAD + + _ = config + } + { + + switch version { + case "1.0": + config := &tls.Config{} + config.MinVersion = tls.VersionTLS10 //BAD + config.MinVersion = tls.VersionTLS11 //BAD + _ = config + } + + } +} diff --git a/ql/test/experimental/CWE-327/UnsafeTLS.qlref b/ql/test/experimental/CWE-327/UnsafeTLS.qlref new file mode 100644 index 00000000000..9b614dde9fa --- /dev/null +++ b/ql/test/experimental/CWE-327/UnsafeTLS.qlref @@ -0,0 +1 @@ +experimental/CWE-327/InsecureTLS.ql