mirror of
https://github.com/github/codeql.git
synced 2026-05-02 20:25:13 +02:00
C++: Prototype SSL result conflation query.
This commit is contained in:
51
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql
Normal file
51
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @name TODO
|
||||
* @description TODO
|
||||
* @kind problem
|
||||
* @problem.severity TODO
|
||||
* @security-severity TODO
|
||||
* @precision TODO
|
||||
* @id TODO
|
||||
* @tags TODO
|
||||
*/
|
||||
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
|
||||
class SSLGetVerifyResultCall extends FunctionCall {
|
||||
SSLGetVerifyResultCall() {
|
||||
getTarget().getName() = "SSL_get_verify_result"
|
||||
}
|
||||
}
|
||||
|
||||
class VerifyResultConfig extends DataFlow::Configuration {
|
||||
VerifyResultConfig() { this = "VerifyResultConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr() instanceof SSLGetVerifyResultCall
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(GuardCondition guard |
|
||||
guard.getAChild*() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use GVN on *both* sinks to get more results!?
|
||||
|
||||
from
|
||||
VerifyResultConfig config, DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2,
|
||||
GuardCondition guard, Expr c1, Expr c2, boolean testIsTrue
|
||||
where
|
||||
config.hasFlow(source, sink1) and
|
||||
globalValueNumber(sink1.asExpr()) = globalValueNumber(sink2.asExpr()) and
|
||||
guard.comparesEq(sink1.asExpr(), c1, 0, false, testIsTrue) and // (value != c1) => testIsTrue
|
||||
guard.comparesEq(sink2.asExpr(), c2, 0, false, testIsTrue) and // (value != c2) => testIsTrue
|
||||
c1.getValue().toInt() = 0 and
|
||||
c2.getValue().toInt() != 0
|
||||
select
|
||||
guard, "This expression conflates OK and non-OK results from $@.", source, source.toString()
|
||||
@@ -0,0 +1,8 @@
|
||||
| test.cpp:18:9:18:38 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:100:18:100:38 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:38:7:38:36 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:36:16:36:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:54:7:54:47 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:52:16:52:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:62:7:62:36 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:60:16:60:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:70:7:70:36 | ... && ... | This expression conflates OK and non-OK results from $@. | test.cpp:68:16:68:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:83:7:83:40 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:78:16:78:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:87:7:87:38 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:7:57:7:77 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:107:13:107:42 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:105:16:105:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-295/SSLResultConflation.ql
|
||||
149
cpp/ql/test/query-tests/Security/CWE/CWE-295/test.cpp
Normal file
149
cpp/ql/test/query-tests/Security/CWE/CWE-295/test.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
|
||||
struct SSL {
|
||||
// ...
|
||||
};
|
||||
|
||||
int SSL_get_verify_result(const SSL *ssl);
|
||||
int get_verify_result_indirect(const SSL *ssl) { return SSL_get_verify_result(ssl); }
|
||||
|
||||
int something_else(const SSL *ssl);
|
||||
|
||||
bool is_ok(int result)
|
||||
{
|
||||
return (result == 0); // GOOD
|
||||
}
|
||||
|
||||
bool is_maybe_ok(int result)
|
||||
{
|
||||
return (result == 0) || (result == 1); // BAD (conflates OK and a non-OK codes)
|
||||
}
|
||||
|
||||
void test1_1(SSL *ssl)
|
||||
{
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if (result == 0) // GOOD
|
||||
{
|
||||
}
|
||||
|
||||
if (result == 1) // GOOD
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if ((result == 0) || (result == 1)) // BAD (conflates OK and a non-OK codes)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if ((result == 1) || (result == 2)) // GOOD (both results are non-OK)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if ((result == 0) || (false) || (result == 2)) // BAD (conflates OK and a non-OK codes)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if ((0 == result) || (1 == result)) // BAD (conflates OK and a non-OK codes)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if ((result != 0) && (result != 1)) // BAD (conflates OK and a non-OK codes)
|
||||
{
|
||||
} else {
|
||||
// conflation occurs here
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
int result_cpy = result;
|
||||
int result2 = get_verify_result_indirect(ssl);
|
||||
int result3 = something_else(ssl);
|
||||
|
||||
if ((result == 0) || (result_cpy == 1)) // BAD (conflates OK and a non-OK codes)
|
||||
{
|
||||
}
|
||||
|
||||
if ((result2 == 0) || (result2 == 1)) // BAD (conflates OK and a non-OK codes)
|
||||
{
|
||||
}
|
||||
|
||||
if ((result3 == 0) || (result3 == 1)) // GOOD (not an SSL result)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ok(SSL_get_verify_result(ssl)))
|
||||
{
|
||||
}
|
||||
|
||||
if (is_maybe_ok(SSL_get_verify_result(ssl)))
|
||||
{
|
||||
}
|
||||
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
bool ok = (result == 0) || (result == 1); // BAD (conflates OK and a non-OK codes)
|
||||
|
||||
if (ok) {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if (result == 1) // BAD (conflates OK and a non-OK codes in `else`) [NOT DETECTED]
|
||||
{
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_good();
|
||||
|
||||
void test1_2(SSL *ssl)
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if (result == 0) { // GOOD
|
||||
do_good();
|
||||
} else if (result == 1) {
|
||||
throw 1;
|
||||
} else {
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
void test1_3(SSL *ssl)
|
||||
{
|
||||
int result = SSL_get_verify_result(ssl);
|
||||
|
||||
if (result == 0) { // BAD (error code 1 is treated as OK, not as non-OK) [NOT DETECTED]
|
||||
do_good();
|
||||
} else if (result == 1) {
|
||||
do_good();
|
||||
} else {
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user