diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.qhelp b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.qhelp new file mode 100644 index 00000000000..e0d6ac080d0 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.qhelp @@ -0,0 +1,15 @@ + + + +

Using TLS or SSLv23 protool from the boost::asio library, but not disabling deprecated protocols or disabling minimum-recommended protocols.

+
+ + +
  • + Boost.Asio documentation. +
  • +
    +
    + diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql new file mode 100644 index 00000000000..83ed90bafab --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -0,0 +1,119 @@ +/** + * @name Boost_asio TLS Settings Misconfiguration + * @description Using TLS or SSLv23 protool from the boost::asio library, but not disabling deprecated protocols or disabling minimum-recommended protocols + * @kind problem + * @problem.severity error + * @id cpp/boost/tls_settings_misconfiguration + * @tags security + */ + +import cpp +import semmle.code.cpp.security.boostorg.asio.protocols + +class ExistsAnyFlowConfig extends DataFlow::Configuration { + ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" } + + override predicate isSource(DataFlow::Node source) { any() } + + override predicate isSink(DataFlow::Node sink) { any() } +} + +bindingset[flag] +predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { + exists( + BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig, + Expr optionsSink + | + config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + exists(VariableAccess contextSetOptions | + testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | + contextSetOptions = fcSetOptions.getQualifier() and + forall( + Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, + Expr optionArgumentSource + | + optionArgument = fcSetOptions.getArgument(0) and + optionArgConfig + .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) + | + optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag + ) + ) + ) + ) +} + +bindingset[flag] +predicate isOptionNotSet(ConstructorCall cc, int flag) { + not exists( + BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig, + Expr optionsSink + | + config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + exists(VariableAccess contextSetOptions | + testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + exists(FunctionCall fcSetOptions, BoostorgAsio::SslSetOptionsFunction f | + f.getACallToThisFunction() = fcSetOptions + | + contextSetOptions = fcSetOptions.getQualifier() and + forall( + Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, + Expr optionArgumentSource + | + optionArgument = fcSetOptions.getArgument(0) and + optionArgConfig + .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) + | + optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag + ) + ) + ) + ) +} + +from + BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, + BoostorgAsio::SslContextFlowsToSetOptionConfig config, Expr protocolSource, Expr protocolSink, + ConstructorCall cc, Expr e, string msg +where + configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and + cc.getArgument(0) = protocolSink and + ( + BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and + not exists(Expr optionsSink | + config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoSsl3(), _) and + isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and + isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and + isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2()) + ) + or + BoostorgAsio::isExprTlsBoostProtocol(protocolSource) and + not BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and + not exists(Expr optionsSink | + config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and + isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and + isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2()) + ) + ) and + ( + BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and + isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoSsl3()) and + e = cc and + msg = "no_sslv3 has not been set" + or + isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1()) and + e = cc and + msg = "no_tlsv1 has not been set" + or + isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1()) and + e = cc and + msg = "no_tlsv1_1 has not been set" + or + isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2(), e) and + msg = "no_tlsv1_2 was set" + ) +select cc, "Usage of $@ with protocol $@ is not configured correctly: The option $@.", cc, + "boost::asio::ssl::context::context", protocolSource, protocolSource.toString(), e, msg diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.qhelp b/cpp/ql/src/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.qhelp new file mode 100644 index 00000000000..6f4d2acedd6 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.qhelp @@ -0,0 +1,16 @@ + + + +

    Using boost::asio library but specifying a deprecated hardcoded protocol.

    +

    Using a deprecated hardcoded protocol instead of negotiting would lock your application to a protocol that has known vulnerabilities or weaknesses.

    +
    + + +
  • + Boost.Asio documentation. +
  • +
    +
    + diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.ql new file mode 100644 index 00000000000..b3693ead656 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.ql @@ -0,0 +1,27 @@ +/** + * @name boost::asio Use of deprecated hardcoded Protocol + * @description Using a deprecated hard-coded protocol using the boost::asio library. + * @kind problem + * @problem.severity error + * @id cpp/boost/use-of-deprecated-hardcoded-security-protocol + * @tags security + */ + +import cpp +import semmle.code.cpp.security.boostorg.asio.protocols + +from + BoostorgAsio::SslContextCallConfig config, Expr protocolSource, Expr protocolSink, + ConstructorCall cc +where + config.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and + not exists(BoostorgAsio::SslContextCallTlsProtocolConfig tlsConfig | + tlsConfig.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) + ) and + cc.getArgument(0) = protocolSink and + exists(BoostorgAsio::SslContextCallBannedProtocolConfig bannedConfig | + bannedConfig.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) + ) +select protocolSink, "Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@.", + cc, "boost::asio::ssl::context::context", protocolSource, protocolSource.toString(), + cc.getEnclosingFunction(), cc.getEnclosingFunction().toString() diff --git a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll new file mode 100644 index 00000000000..ae3733473ad --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -0,0 +1,487 @@ +import cpp +import semmle.code.cpp.dataflow.DataFlow + +module BoostorgAsio { + /** + * Represents boost::asio::ssl::context enum + */ + class SslContextMethod extends Enum { + SslContextMethod() { + this.getName().toString() = "method" and + this.getQualifiedName().toString().matches("boost::asio::ssl::context%") + } + + /** + * returns the value for a banned protocol + */ + EnumConstant getABannedProtocolConstant() { + result = this.getAnEnumConstant() and + ( + /// Generic SSL version 2. + result.getName() = "sslv2" + or + /// SSL version 2 client. + result.getName() = "sslv2_client" + or + /// SSL version 2 server. + result.getName() = "sslv2_server" + or + /// Generic SSL version 3. + result.getName() = "sslv3" + or + /// SSL version 3 client. + result.getName() = "sslv3_client" + or + /// SSL version 3 server. + result.getName() = "sslv3_server" + or + /// Generic TLS version 1. + result.getName() = "tlsv1" + or + /// TLS version 1 client. + result.getName() = "tlsv1_client" + or + /// TLS version 1 server. + result.getName() = "tlsv1_server" + or + /// Generic TLS version 1.1. + result.getName() = "tlsv11" + or + /// TLS version 1.1 client. + result.getName() = "tlsv11_client" + or + /// TLS version 1.1 server. + result.getName() = "tlsv11_server" + ) + } + + /** + * returns the value for a approved protocols, but that are hard-coded (i.e. no protocol negotiation) + */ + EnumConstant getAnApprovedButHardcodedProtocolConstant() { + result = this.getATls12ProtocolConstant() + } + + /** + * returns the value for a TLS v1.2 protocol + */ + EnumConstant getATls12ProtocolConstant() { + result = this.getAnEnumConstant() and + ( + /// Generic TLS version 1.2. + result.getName() = "tlsv12" + or + /// TLS version 1.2 client. + result.getName() = "tlsv12_client" + or + /// TLS version 1.2 server. + result.getName() = "tlsv12_server" + ) + } + + /** + * returns the value for a TLS v1.3 protocol + */ + EnumConstant getATls13ProtocolConstant() { + result = this.getAnEnumConstant() and + ( + /// Generic TLS version 1.3. + result.getName() = "tlsv13" + or + /// TLS version 1.3 client. + result.getName() = "tlsv13_client" + or + /// TLS version 1.3 server. + result.getName() = "tlsv13_server" + ) + } + + /** + * returns the value of a generic TLS or SSL/TLS protocol + */ + EnumConstant getAGenericTlsProtocolConstant() { + result = this.getAnEnumConstant() and + ( + /// Generic TLS + result.getName() = "tls" + or + /// TLS client. + result.getName() = "tls_client" + or + /// TLS server. + result.getName() = "tls_server" + ) + or + result = getASslv23ProtocolConstant() + } + + /** + * returns the value of a generic SSL/TLS protocol + */ + EnumConstant getASslv23ProtocolConstant() { + result = this.getAnEnumConstant() and + ( + /// OpenSSL - SSLv23 == A TLS/SSL connection established with these methods may understand the SSLv2, SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols. + /// Generic SSL/TLS. + result.getName() = "sslv23" + or + /// SSL/TLS client. + result.getName() = "sslv23_client" + or + /// SSL/TLS server. + result.getName() = "sslv23_server" + ) + } + } + + /** + * NOTE: ignore - Modern versions of OpenSSL do not support SSL v2 anymore, so this option is for backwards compatibility only + */ + int getShiftedSslOptionsNoSsl2() { + // SSL_OP_NO_SSLv2 was removed from modern OpenSSL versions + result = 0 + } + + /** + * RightShift(16) value for no_sslv3 constant + */ + int getShiftedSslOptionsNoSsl3() { + // SSL_OP_NO_SSLv3 == 0x02000000U + result = 512 + } + + /** + * RightShift(16) value for no_tlsv1 constant + */ + int getShiftedSslOptionsNoTls1() { + // SSL_OP_NO_TLSv1 == 0x04000000U + result = 1024 + } + + /** + * RightShift(16) value for no_tlsv1_1 constant + */ + int getShiftedSslOptionsNoTls1_1() { + // SSL_OP_NO_TLSv1_1 == 0x10000000U + result = 4096 + } + + /** + * RightShift(16) value for no_tlsv1_2 constant + */ + int getShiftedSslOptionsNoTls1_2() { + // SSL_OP_NO_TLSv1_2 == 0x08000000U + result = 2048 + } + + /** + * RightShift(16) value for no_tlsv1_3 constant + */ + int getShiftedSslOptionsNoTls1_3() { + // SSL_OP_NO_TLSv1_2 == 0x20000000U + result = 8192 + } + + /** + * Represents boost::asio::ssl::context class + */ + class SslContextClass extends Class { + SslContextClass() { this.getQualifiedName() = "boost::asio::ssl::context" } + + ConstructorCall getAContructorCall() { + this.getAConstructor().getACallToThisFunction() = result and + not result.getLocation().getFile().toString().matches("%/boost/asio/%") and + result.fromSource() + } + } + + /** + * Represents boost::asio::ssl::context::set_options member function + */ + class SslSetOptionsFunction extends Function { + SslSetOptionsFunction() { + this.getQualifiedName().matches("boost::asio::ssl::context::set_options") + } + } + + /** + * holds if the expression represents a banned protocol + */ + predicate isExprBannedBoostProtocol(Expr e) { + exists(Literal va | va = e | + va.getValue().toInt() = 0 or + va.getValue().toInt() = 1 or + va.getValue().toInt() = 2 or + va.getValue().toInt() = 3 or + va.getValue().toInt() = 4 or + va.getValue().toInt() = 5 or + va.getValue().toInt() = 6 or + va.getValue().toInt() = 7 or + va.getValue().toInt() = 8 or + va.getValue().toInt() = 12 or + va.getValue().toInt() = 13 or + va.getValue().toInt() = 14 + ) + or + exists(VariableAccess va | va = e | + va.getValue().toInt() = 0 or + va.getValue().toInt() = 1 or + va.getValue().toInt() = 2 or + va.getValue().toInt() = 3 or + va.getValue().toInt() = 4 or + va.getValue().toInt() = 5 or + va.getValue().toInt() = 6 or + va.getValue().toInt() = 7 or + va.getValue().toInt() = 8 or + va.getValue().toInt() = 12 or + va.getValue().toInt() = 13 or + va.getValue().toInt() = 14 + ) + or + exists(EnumConstantAccess eca, SslContextMethod enum | e = eca | + enum.getABannedProtocolConstant().getAnAccess() = eca + ) + } + + /** + * holds if the expression represents a TLS v1.2 protocol + */ + predicate isExprTls12BoostProtocol(Expr e) { + exists(Literal va | va = e | + ( + va.getValue().toInt() = 15 or /// Generic TLS version 1.2. + va.getValue().toInt() = 16 or /// TLS version 1.2 client. + va.getValue().toInt() = 17 /// TLS version 1.2 server. + ) + ) + or + exists(VariableAccess va | va = e | + ( + va.getValue().toInt() = 15 or /// Generic TLS version 1.2. + va.getValue().toInt() = 16 or /// TLS version 1.2 client. + va.getValue().toInt() = 17 /// TLS version 1.2 server. + ) + ) + or + exists(EnumConstantAccess eca, SslContextMethod enum | e = eca | + enum.getATls12ProtocolConstant().getAnAccess() = eca + ) + } + + /** + * holds if the expression represents a protocol that requires Crypto Board approval + */ + predicate isExprTls13BoostProtocol(Expr e) { + exists(Literal va | va = e | + ( + va.getValue().toInt() = 18 or + va.getValue().toInt() = 19 or + va.getValue().toInt() = 20 + ) + ) + or + exists(VariableAccess va | va = e | + ( + va.getValue().toInt() = 18 or + va.getValue().toInt() = 19 or + va.getValue().toInt() = 20 + ) + ) + or + exists(EnumConstantAccess eca, SslContextMethod enum | e = eca | + enum.getATls13ProtocolConstant().getAnAccess() = eca + ) + } + + /** + * holds if the expression represents a generic TLS or SSL/TLS protocol + */ + predicate isExprTlsBoostProtocol(Expr e) { + exists(Literal va | va = e | + ( + va.getValue().toInt() = 9 or /// Generic SSL/TLS. + va.getValue().toInt() = 10 or /// SSL/TLS client. + va.getValue().toInt() = 11 or /// SSL/TLS server. + va.getValue().toInt() = 21 or /// Generic TLS. + va.getValue().toInt() = 22 or /// TLS client. + va.getValue().toInt() = 23 /// TLS server. + ) + ) + or + exists(VariableAccess va | va = e | + ( + va.getValue().toInt() = 9 or /// Generic SSL/TLS. + va.getValue().toInt() = 10 or /// SSL/TLS client. + va.getValue().toInt() = 11 or /// SSL/TLS server. + va.getValue().toInt() = 21 or /// Generic TLS. + va.getValue().toInt() = 22 or /// TLS client. + va.getValue().toInt() = 23 /// TLS server. + ) + ) + or + exists(EnumConstantAccess eca, SslContextMethod enum | e = eca | + enum.getAGenericTlsProtocolConstant().getAnAccess() = eca + ) + } + + /** + * holds if the expression represents a generic SSl/TLS protocol + */ + predicate isExprSslV23BoostProtocol(Expr e) { + exists(Literal va | va = e | + ( + va.getValue().toInt() = 9 or /// Generic SSL/TLS. + va.getValue().toInt() = 10 or /// SSL/TLS client. + va.getValue().toInt() = 11 /// SSL/TLS server. + ) + ) + or + exists(VariableAccess va | va = e | + ( + va.getValue().toInt() = 9 or /// Generic SSL/TLS. + va.getValue().toInt() = 10 or /// SSL/TLS client. + va.getValue().toInt() = 11 /// SSL/TLS server. + ) + ) + or + exists(EnumConstantAccess eca, SslContextMethod enum | e = eca | + enum.getASslv23ProtocolConstant().getAnAccess() = eca + ) + } + + //////////////////////// Dataflow ///////////////////// + /** + * Abstract - Protocol value Flows to the first argument of the context constructor + */ + abstract class SslContextCallAbstractConfig extends DataFlow::Configuration { + bindingset[this] + SslContextCallAbstractConfig() { any() } + + override predicate isSink(DataFlow::Node sink) { + exists(ConstructorCall cc, SslContextClass c, Expr e | e = sink.asExpr() | + c.getAContructorCall() = cc and + cc.getArgument(0) = e + ) + } + } + + /** + * any Protocol value Flows to the first argument of the context constructor + */ + class SslContextCallConfig extends SslContextCallAbstractConfig { + SslContextCallConfig() { this = "SslContextCallConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") + ) + } + } + + /** + * a banned protocol value Flows to the first argument of the context constructor + */ + class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig { + SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") and + isExprBannedBoostProtocol(e) + ) + } + } + + /** + * a TLS 1.2 protocol value Flows to the first argument of the context constructor + */ + class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig { + SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") and + isExprTls12BoostProtocol(e) + ) + } + } + + /** + * a TLS 1.3 protocol value Flows to the first argument of the context constructor + */ + class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig { + SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") and + isExprTls13BoostProtocol(e) + ) + } + } + + /** + * a generic TLS protocol value Flows to the first argument of the context constructor + */ + class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig { + SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") and + isExprTlsBoostProtocol(e) + ) + } + } + + /** + * a context constructor call flows to a call calling SetOptions() + */ + class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration { + SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(SslContextClass c, ConstructorCall cc | + cc = source.asExpr() and + c.getAContructorCall() = cc + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(FunctionCall fc, SslSetOptionsFunction f, Variable v, VariableAccess va | + va = sink.asExpr() + | + f.getACallToThisFunction() = fc and + v.getAnAccess() = va and + va = fc.getQualifier() + ) + } + } + + /** + * an option value flows to the 1st parameter of SetOptions() + */ + class SslOptionConfig extends DataFlow::Configuration { + SslOptionConfig() { this = "SslOptionConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(SslSetOptionsFunction f, FunctionCall call | + sink.asExpr() = call.getArgument(0) and + f.getACallToThisFunction() = call and + not sink.getLocation().getFile().toString().matches("%/boost/asio/%") + ) + } + } +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected new file mode 100644 index 00000000000..8a3acb1aeb5 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected @@ -0,0 +1,7 @@ +| test.cpp:25:32:25:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:65 | call to context | boost::asio::ssl::context::context | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_sslv3 has not been set | +| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_sslv3 has not been set | +| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set | +| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1_1 has not been set | +| test.cpp:36:32:36:62 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:36:32:36:62 | call to context | boost::asio::ssl::context::context | test.cpp:36:32:36:61 | tls | tls | test.cpp:36:32:36:62 | call to context | no_tlsv1 has not been set | +| test.cpp:36:32:36:62 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:36:32:36:62 | call to context | boost::asio::ssl::context::context | test.cpp:36:32:36:61 | tls | tls | test.cpp:36:32:36:62 | call to context | no_tlsv1_1 has not been set | +| test.cpp:41:32:41:62 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:41:32:41:62 | call to context | boost::asio::ssl::context::context | test.cpp:41:32:41:61 | tls | tls | test.cpp:43:6:43:16 | call to set_options | no_tlsv1_2 was set | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.qlref b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.qlref new file mode 100644 index 00000000000..fd20bf3f8bd --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.qlref @@ -0,0 +1 @@ +Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.expected b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.expected new file mode 100644 index 00000000000..6e62650929d --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.expected @@ -0,0 +1,24 @@ +| test.cpp:50:38:50:69 | sslv2 | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:50:38:50:70 | call to context | boost::asio::ssl::context::context | test.cpp:50:38:50:69 | sslv2 | sslv2 | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:51:39:51:77 | sslv2_client | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:51:39:51:78 | call to context | boost::asio::ssl::context::context | test.cpp:51:39:51:77 | sslv2_client | sslv2_client | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:52:39:52:77 | sslv2_server | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:52:39:52:78 | call to context | boost::asio::ssl::context::context | test.cpp:52:39:52:77 | sslv2_server | sslv2_server | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:54:38:54:69 | sslv3 | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:54:38:54:70 | call to context | boost::asio::ssl::context::context | test.cpp:54:38:54:69 | sslv3 | sslv3 | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:55:39:55:77 | sslv3_client | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:55:39:55:78 | call to context | boost::asio::ssl::context::context | test.cpp:55:39:55:77 | sslv3_client | sslv3_client | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:56:39:56:77 | sslv3_server | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:56:39:56:78 | call to context | boost::asio::ssl::context::context | test.cpp:56:39:56:77 | sslv3_server | sslv3_server | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:58:38:58:69 | tlsv1 | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:58:38:58:70 | call to context | boost::asio::ssl::context::context | test.cpp:58:38:58:69 | tlsv1 | tlsv1 | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:59:39:59:77 | tlsv1_client | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:59:39:59:78 | call to context | boost::asio::ssl::context::context | test.cpp:59:39:59:77 | tlsv1_client | tlsv1_client | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:60:39:60:77 | tlsv1_server | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:60:39:60:78 | call to context | boost::asio::ssl::context::context | test.cpp:60:39:60:77 | tlsv1_server | tlsv1_server | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:62:39:62:71 | tlsv11 | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:62:39:62:72 | call to context | boost::asio::ssl::context::context | test.cpp:62:39:62:71 | tlsv11 | tlsv11 | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:63:40:63:79 | tlsv11_client | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:63:40:63:80 | call to context | boost::asio::ssl::context::context | test.cpp:63:40:63:79 | tlsv11_client | tlsv11_client | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:64:40:64:79 | tlsv11_server | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:64:40:64:80 | call to context | boost::asio::ssl::context::context | test.cpp:64:40:64:79 | tlsv11_server | tlsv11_server | test.cpp:47:6:47:27 | TestHardcodedProtocols | TestHardcodedProtocols | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:85:22:85:53 | sslv2 | sslv2 | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:86:22:86:60 | sslv2_client | sslv2_client | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:87:22:87:60 | sslv2_server | sslv2_server | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:89:22:89:53 | sslv3 | sslv3 | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:90:22:90:60 | sslv3_client | sslv3_client | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:91:22:91:60 | sslv3_server | sslv3_server | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:93:22:93:53 | tlsv1 | tlsv1 | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:94:22:94:60 | tlsv1_client | tlsv1_client | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:95:22:95:60 | tlsv1_server | tlsv1_server | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:97:22:97:54 | tlsv11 | tlsv11 | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:98:22:98:61 | tlsv11_client | tlsv11_client | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | +| test.cpp:79:33:79:33 | m | Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@. | test.cpp:79:33:79:34 | call to context | boost::asio::ssl::context::context | test.cpp:99:22:99:61 | tlsv11_server | tlsv11_server | test.cpp:77:6:77:24 | InterProceduralTest | InterProceduralTest | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.qlref b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.qlref new file mode 100644 index 00000000000..75800f425f8 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.qlref @@ -0,0 +1 @@ +Likely Bugs/Protocols/boostorg/UseOfDeprecatedHardcodedProtocol.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/asio/boost_simulation.hpp b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/asio/boost_simulation.hpp new file mode 100644 index 00000000000..7468d71980e --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/asio/boost_simulation.hpp @@ -0,0 +1,112 @@ + +#define SSL_OP_ALL 0x80000BFFU +#define SSL_OP_NO_SSLv2 0 +#define SSL_OP_NO_SSLv3 0x02000000U +#define SSL_OP_NO_TLSv1 0x04000000U +#define SSL_OP_NO_TLSv1_1 0x10000000U +#define SSL_OP_NO_TLSv1_2 0x08000000U +#define SSL_OP_NO_TLSv1_3 0x20000000U + +namespace boost { + namespace asio { + namespace ssl { + + class context + { + public: + /// Different methods supported by a context. + enum method + { + /// Generic SSL version 2. + sslv2, + + /// SSL version 2 client. + sslv2_client, + + /// SSL version 2 server. + sslv2_server, + + /// Generic SSL version 3. + sslv3, + + /// SSL version 3 client. + sslv3_client, + + /// SSL version 3 server. + sslv3_server, + + /// Generic TLS version 1. + tlsv1, + + /// TLS version 1 client. + tlsv1_client, + + /// TLS version 1 server. + tlsv1_server, + + /// Generic SSL/TLS. + sslv23, + + /// SSL/TLS client. + sslv23_client, + + /// SSL/TLS server. + sslv23_server, + + /// Generic TLS version 1.1. + tlsv11, + + /// TLS version 1.1 client. + tlsv11_client, + + /// TLS version 1.1 server. + tlsv11_server, + + /// Generic TLS version 1.2. + tlsv12, + + /// TLS version 1.2 client. + tlsv12_client, + + /// TLS version 1.2 server. + tlsv12_server, + + /// Generic TLS version 1.3. + tlsv13, + + /// TLS version 1.3 client. + tlsv13_client, + + /// TLS version 1.3 server. + tlsv13_server, + + /// Generic TLS. + tls, + + /// TLS client. + tls_client, + + /// TLS server. + tls_server + }; + + /// Bitmask type for SSL options. + typedef long options; + + static const long default_workarounds = SSL_OP_ALL; + static const long no_sslv2 = SSL_OP_NO_SSLv2; + static const long no_sslv3 = SSL_OP_NO_SSLv3; + static const long no_tlsv1 = SSL_OP_NO_TLSv1; + static const long no_tlsv1_1 = SSL_OP_NO_TLSv1_1; + static const long no_tlsv1_2 = SSL_OP_NO_TLSv1_2; + static const long no_tlsv1_3 = SSL_OP_NO_TLSv1_3; + + /// Constructor. + explicit context(method m) {} + + void context::set_options(context::options o) {} + + }; + } + } +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test.cpp new file mode 100644 index 00000000000..d9650089a33 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test.cpp @@ -0,0 +1,110 @@ +#include "asio/boost_simulation.hpp" + +void SetOptionsNoOldTls(boost::asio::ssl::context& ctx) +{ + ctx.set_options(boost::asio::ssl::context::no_tlsv1); + ctx.set_options(boost::asio::ssl::context::no_tlsv1_1); +} + +void TestProperConfiguration_inter_CorrectUsage01() +{ + boost::asio::ssl::context ctx(boost::asio::ssl::context::tls_client); + SetOptionsNoOldTls(ctx); +} + +void TestProperConfiguration_inter_CorrectUsage02() +{ + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | + boost::asio::ssl::context::no_tlsv1_1 | + boost::asio::ssl::context::no_sslv3); +} + +void TestProperConfiguration_inter_IncorrectUsage01() +{ + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); // BUG - missing disable SSLv3 + SetOptionsNoOldTls(ctx); +} + +void TestProperConfiguration_IncorrectUsage01() +{ + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); // BUG +} + +void TestProperConfiguration_IncorrectUsage02() +{ + boost::asio::ssl::context ctx(boost::asio::ssl::context::tls); // BUG +} + +void TestProperConfiguration_IncorrectUsage03() +{ + boost::asio::ssl::context ctx(boost::asio::ssl::context::tls); // BUG + SetOptionsNoOldTls(ctx); + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | + boost::asio::ssl::context::no_tlsv1_2 ); // BUG - disabling TLS 1.2 +} + +void TestHardcodedProtocols() +{ + //////////////////////// Banned Hardcoded algorithms + boost::asio::ssl::context cxt_sslv2(boost::asio::ssl::context::sslv2); // BUG + boost::asio::ssl::context cxt_sslv2c(boost::asio::ssl::context::sslv2_client); // BUG + boost::asio::ssl::context cxt_sslv2s(boost::asio::ssl::context::sslv2_server); // BUG + + boost::asio::ssl::context cxt_sslv3(boost::asio::ssl::context::sslv3); // BUG + boost::asio::ssl::context cxt_sslv3c(boost::asio::ssl::context::sslv3_client); // BUG + boost::asio::ssl::context cxt_sslv3s(boost::asio::ssl::context::sslv3_server); // BUG + + boost::asio::ssl::context cxt_tlsv1(boost::asio::ssl::context::tlsv1); // BUG + boost::asio::ssl::context cxt_tlsv1c(boost::asio::ssl::context::tlsv1_client); // BUG + boost::asio::ssl::context cxt_tlsv1s(boost::asio::ssl::context::tlsv1_server); // BUG + + boost::asio::ssl::context cxt_tlsv11(boost::asio::ssl::context::tlsv11); // BUG + boost::asio::ssl::context cxt_tlsv11c(boost::asio::ssl::context::tlsv11_client); // BUG + boost::asio::ssl::context cxt_tlsv11s(boost::asio::ssl::context::tlsv11_server); // BUG + + ////////////////////// Hardcoded algorithms + + boost::asio::ssl::context cxt_tlsv12(boost::asio::ssl::context::tlsv12); // BUG + boost::asio::ssl::context cxt_tlsv12c(boost::asio::ssl::context::tlsv12_client); // BUG + boost::asio::ssl::context cxt_tlsv12s(boost::asio::ssl::context::tlsv12_server); // BUG + + boost::asio::ssl::context cxt_tlsv13(boost::asio::ssl::context::tlsv13); // BUG + boost::asio::ssl::context cxt_tlsv13c(boost::asio::ssl::context::tlsv13_client); // BUG + boost::asio::ssl::context cxt_tlsv13s(boost::asio::ssl::context::tlsv13_server); // BUG +} + +void InterProceduralTest(boost::asio::ssl::context::method m) +{ + boost::asio::ssl::context cxt1(m); // BUG - Multiple hits (sink) +} + +void TestHardcodedProtocols_inter() +{ + //////////////////////// Banned Hardcoded algorithms + InterProceduralTest(boost::asio::ssl::context::sslv2); // BUG + InterProceduralTest(boost::asio::ssl::context::sslv2_client); // BUG + InterProceduralTest(boost::asio::ssl::context::sslv2_server); // BUG + + InterProceduralTest(boost::asio::ssl::context::sslv3); // BUG + InterProceduralTest(boost::asio::ssl::context::sslv3_client); // BUG + InterProceduralTest(boost::asio::ssl::context::sslv3_server); // BUG + + InterProceduralTest(boost::asio::ssl::context::tlsv1); // BUG + InterProceduralTest(boost::asio::ssl::context::tlsv1_client); // BUG + InterProceduralTest(boost::asio::ssl::context::tlsv1_server); // BUG + + InterProceduralTest(boost::asio::ssl::context::tlsv11); // BUG + InterProceduralTest(boost::asio::ssl::context::tlsv11_client); // BUG + InterProceduralTest(boost::asio::ssl::context::tlsv11_server); // BUG + + ////////////////////// Hardcoded algorithms + + InterProceduralTest(boost::asio::ssl::context::tlsv12); // BUG + InterProceduralTest(boost::asio::ssl::context::tlsv12_client); // BUG + InterProceduralTest(boost::asio::ssl::context::tlsv12_server); // BUG + + InterProceduralTest(boost::asio::ssl::context::tlsv13); // BUG + InterProceduralTest(boost::asio::ssl::context::tlsv13_client); // BUG + InterProceduralTest(boost::asio::ssl::context::tlsv13_server); // BUG +}