Skip to content

Commit 6afcbce

Browse files
committed
C++: Prototype SSL result conflation query.
1 parent 1f3f7e9 commit 6afcbce

File tree

4 files changed

+209
-0
lines changed

4 files changed

+209
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* @name TODO
3+
* @description TODO
4+
* @kind problem
5+
* @problem.severity TODO
6+
* @security-severity TODO
7+
* @precision TODO
8+
* @id TODO
9+
* @tags TODO
10+
*/
11+
12+
13+
import cpp
14+
import semmle.code.cpp.controlflow.Guards
15+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
16+
import semmle.code.cpp.dataflow.DataFlow
17+
18+
class SSLGetVerifyResultCall extends FunctionCall {
19+
SSLGetVerifyResultCall() {
20+
getTarget().getName() = "SSL_get_verify_result"
21+
}
22+
}
23+
24+
class VerifyResultConfig extends DataFlow::Configuration {
25+
VerifyResultConfig() { this = "VerifyResultConfig" }
26+
27+
override predicate isSource(DataFlow::Node source) {
28+
source.asExpr() instanceof SSLGetVerifyResultCall
29+
}
30+
31+
override predicate isSink(DataFlow::Node sink) {
32+
exists(GuardCondition guard |
33+
guard.getAChild*() = sink.asExpr()
34+
)
35+
}
36+
}
37+
38+
// TODO: use GVN on *both* sinks to get more results!?
39+
40+
from
41+
VerifyResultConfig config, DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2,
42+
GuardCondition guard, Expr c1, Expr c2, boolean testIsTrue
43+
where
44+
config.hasFlow(source, sink1) and
45+
globalValueNumber(sink1.asExpr()) = globalValueNumber(sink2.asExpr()) and
46+
guard.comparesEq(sink1.asExpr(), c1, 0, false, testIsTrue) and // (value != c1) => testIsTrue
47+
guard.comparesEq(sink2.asExpr(), c2, 0, false, testIsTrue) and // (value != c2) => testIsTrue
48+
c1.getValue().toInt() = 0 and
49+
c2.getValue().toInt() != 0
50+
select
51+
guard, "This expression conflates OK and non-OK results from $@.", source, source.toString()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
| 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 |
2+
| 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 |
3+
| 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 |
4+
| 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 |
5+
| 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 |
6+
| 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 |
7+
| 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 |
8+
| 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 |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE/CWE-295/SSLResultConflation.ql
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
2+
struct SSL {
3+
// ...
4+
};
5+
6+
int SSL_get_verify_result(const SSL *ssl);
7+
int get_verify_result_indirect(const SSL *ssl) { return SSL_get_verify_result(ssl); }
8+
9+
int something_else(const SSL *ssl);
10+
11+
bool is_ok(int result)
12+
{
13+
return (result == 0); // GOOD
14+
}
15+
16+
bool is_maybe_ok(int result)
17+
{
18+
return (result == 0) || (result == 1); // BAD (conflates OK and a non-OK codes)
19+
}
20+
21+
void test1_1(SSL *ssl)
22+
{
23+
{
24+
int result = SSL_get_verify_result(ssl);
25+
26+
if (result == 0) // GOOD
27+
{
28+
}
29+
30+
if (result == 1) // GOOD
31+
{
32+
}
33+
}
34+
35+
{
36+
int result = SSL_get_verify_result(ssl);
37+
38+
if ((result == 0) || (result == 1)) // BAD (conflates OK and a non-OK codes)
39+
{
40+
}
41+
}
42+
43+
{
44+
int result = SSL_get_verify_result(ssl);
45+
46+
if ((result == 1) || (result == 2)) // GOOD (both results are non-OK)
47+
{
48+
}
49+
}
50+
51+
{
52+
int result = SSL_get_verify_result(ssl);
53+
54+
if ((result == 0) || (false) || (result == 2)) // BAD (conflates OK and a non-OK codes)
55+
{
56+
}
57+
}
58+
59+
{
60+
int result = SSL_get_verify_result(ssl);
61+
62+
if ((0 == result) || (1 == result)) // BAD (conflates OK and a non-OK codes)
63+
{
64+
}
65+
}
66+
67+
{
68+
int result = SSL_get_verify_result(ssl);
69+
70+
if ((result != 0) && (result != 1)) // BAD (conflates OK and a non-OK codes)
71+
{
72+
} else {
73+
// conflation occurs here
74+
}
75+
}
76+
77+
{
78+
int result = SSL_get_verify_result(ssl);
79+
int result_cpy = result;
80+
int result2 = get_verify_result_indirect(ssl);
81+
int result3 = something_else(ssl);
82+
83+
if ((result == 0) || (result_cpy == 1)) // BAD (conflates OK and a non-OK codes)
84+
{
85+
}
86+
87+
if ((result2 == 0) || (result2 == 1)) // BAD (conflates OK and a non-OK codes)
88+
{
89+
}
90+
91+
if ((result3 == 0) || (result3 == 1)) // GOOD (not an SSL result)
92+
{
93+
}
94+
}
95+
96+
if (is_ok(SSL_get_verify_result(ssl)))
97+
{
98+
}
99+
100+
if (is_maybe_ok(SSL_get_verify_result(ssl)))
101+
{
102+
}
103+
104+
{
105+
int result = SSL_get_verify_result(ssl);
106+
107+
bool ok = (result == 0) || (result == 1); // BAD (conflates OK and a non-OK codes)
108+
109+
if (ok) {
110+
}
111+
}
112+
113+
{
114+
int result = SSL_get_verify_result(ssl);
115+
116+
if (result == 1) // BAD (conflates OK and a non-OK codes in `else`) [NOT DETECTED]
117+
{
118+
} else {
119+
}
120+
}
121+
}
122+
123+
void do_good();
124+
125+
void test1_2(SSL *ssl)
126+
{
127+
int result = SSL_get_verify_result(ssl);
128+
129+
if (result == 0) { // GOOD
130+
do_good();
131+
} else if (result == 1) {
132+
throw 1;
133+
} else {
134+
throw 1;
135+
}
136+
}
137+
138+
void test1_3(SSL *ssl)
139+
{
140+
int result = SSL_get_verify_result(ssl);
141+
142+
if (result == 0) { // BAD (error code 1 is treated as OK, not as non-OK) [NOT DETECTED]
143+
do_good();
144+
} else if (result == 1) {
145+
do_good();
146+
} else {
147+
throw 1;
148+
}
149+
}

0 commit comments

Comments
 (0)