Skip to content

Commit f58177f

Browse files
committed
C++: Full dataflow version.
1 parent e696eaa commit f58177f

File tree

3 files changed

+40
-18
lines changed

3 files changed

+40
-18
lines changed

cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@
55
* @kind problem
66
* @problem.severity warning
77
* @security-severity 7.5 TODO
8-
* @precision high
8+
* @precision high TODO
99
* @id cpp/cleartext-transmission
1010
* @tags security
1111
* external/cwe/cwe-319
1212
*/
1313

1414
import cpp
1515
import semmle.code.cpp.security.SensitiveExprs
16-
import semmle.code.cpp.security.FileWrite
1716
import semmle.code.cpp.dataflow.DataFlow
18-
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
1917

2018
/**
2119
* A function call that sends or receives data over a network.
@@ -65,10 +63,31 @@ class NetworkRecv extends NetworkSendRecv {
6563
override Expr getDataExpr() { result = this.getArgument(1) }
6664
}
6765

68-
from NetworkSendRecv transmission, SensitiveExpr e
66+
/**
67+
* Taint flow from a sensitive expression to a network operation with data
68+
* tainted by that expression.
69+
*/
70+
class SensitiveSendRecvConfiguration extends DataFlow::Configuration {
71+
SensitiveSendRecvConfiguration() { this = "SensitiveSendRecvConfiguration" }
72+
73+
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr }
74+
75+
override predicate isSink(DataFlow::Node sink) {
76+
exists(NetworkSendRecv transmission |
77+
sink.asExpr() = transmission.getDataExpr() and
78+
not exists(Zero zero |
79+
DataFlow::localFlow(DataFlow::exprNode(zero),
80+
DataFlow::exprNode(transmission.getSocketExpr()))
81+
)
82+
)
83+
}
84+
}
85+
86+
from SensitiveSendRecvConfiguration config1, Expr source, Expr sink
6987
where
70-
DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(transmission.getDataExpr())) and
71-
not exists(Zero zero |
72-
DataFlow::localFlow(DataFlow::exprNode(zero), DataFlow::exprNode(transmission.getSocketExpr()))
88+
exists(DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode |
89+
config1.hasFlowPath(sourceNode, sinkNode) and
90+
source = sourceNode.getNode().asExpr() and
91+
sink = sinkNode.getNode().asExpr()
7392
)
74-
select transmission, e
93+
select sink, source
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
| test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 |
2-
| test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 |
3-
| test3.cpp:41:3:41:6 | call to recv | test3.cpp:41:15:41:22 | password |
4-
| test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password |
5-
| test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 |
6-
| test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password |
7-
| test3.cpp:95:3:95:6 | call to read | test3.cpp:95:12:95:19 | password |
1+
| test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 |
2+
| test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 |
3+
| test3.cpp:41:15:41:22 | password | test3.cpp:41:15:41:22 | password |
4+
| test3.cpp:49:15:49:22 | password | test3.cpp:49:15:49:22 | password |
5+
| test3.cpp:70:15:70:17 | ptr | test3.cpp:68:21:68:29 | password1 |
6+
| test3.cpp:77:15:77:17 | ptr | test3.cpp:75:15:75:22 | password |
7+
| test3.cpp:95:12:95:19 | password | test3.cpp:95:12:95:19 | password |
8+
| test3.cpp:108:14:108:19 | buffer | test3.cpp:128:11:128:18 | password |
9+
| test3.cpp:134:15:134:17 | ptr | test3.cpp:132:24:132:32 | password1 |
10+
| test3.cpp:140:15:140:18 | data | test3.cpp:120:9:120:23 | global_password |

cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,18 +125,18 @@ void test_interprocedural(const char *password1)
125125
{
126126
char password[256];
127127

128-
my_recv(password, 256); // BAD: `password` is received plaintext [NOT DETECTED]
128+
my_recv(password, 256); // BAD: `password` is received plaintext [detected on line 108]
129129
}
130130

131131
{
132132
const char *ptr = id(password1);
133133

134-
send(val(), ptr, strlen(ptr), val()); // BAD: `password1` is sent plaintext [NOT DETECTED]
134+
send(val(), ptr, strlen(ptr), val()); // BAD: `password1` is sent plaintext
135135
}
136136

137137
{
138138
char *data = get_global_str();
139139

140-
send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext [NOT DETECTED]
140+
send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext
141141
}
142142
}

0 commit comments

Comments
 (0)