C++: Full dataflow version.

This commit is contained in:
Geoffrey White
2021-09-08 13:32:33 +01:00
parent e696eaaa2f
commit f58177f292
3 changed files with 40 additions and 18 deletions

View File

@@ -5,7 +5,7 @@
* @kind problem
* @problem.severity warning
* @security-severity 7.5 TODO
* @precision high
* @precision high TODO
* @id cpp/cleartext-transmission
* @tags security
* external/cwe/cwe-319
@@ -13,9 +13,7 @@
import cpp
import semmle.code.cpp.security.SensitiveExprs
import semmle.code.cpp.security.FileWrite
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* A function call that sends or receives data over a network.
@@ -65,10 +63,31 @@ class NetworkRecv extends NetworkSendRecv {
override Expr getDataExpr() { result = this.getArgument(1) }
}
from NetworkSendRecv transmission, SensitiveExpr e
/**
* Taint flow from a sensitive expression to a network operation with data
* tainted by that expression.
*/
class SensitiveSendRecvConfiguration extends DataFlow::Configuration {
SensitiveSendRecvConfiguration() { this = "SensitiveSendRecvConfiguration" }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr }
override predicate isSink(DataFlow::Node sink) {
exists(NetworkSendRecv transmission |
sink.asExpr() = transmission.getDataExpr() and
not exists(Zero zero |
DataFlow::localFlow(DataFlow::exprNode(zero),
DataFlow::exprNode(transmission.getSocketExpr()))
)
)
}
}
from SensitiveSendRecvConfiguration config1, Expr source, Expr sink
where
DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(transmission.getDataExpr())) and
not exists(Zero zero |
DataFlow::localFlow(DataFlow::exprNode(zero), DataFlow::exprNode(transmission.getSocketExpr()))
exists(DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode |
config1.hasFlowPath(sourceNode, sinkNode) and
source = sourceNode.getNode().asExpr() and
sink = sinkNode.getNode().asExpr()
)
select transmission, e
select sink, source

View File

@@ -1,7 +1,10 @@
| test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 |
| test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 |
| test3.cpp:41:3:41:6 | call to recv | test3.cpp:41:15:41:22 | password |
| test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password |
| test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 |
| test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password |
| test3.cpp:95:3:95:6 | call to read | test3.cpp:95:12:95:19 | password |
| test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 |
| test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 |
| test3.cpp:41:15:41:22 | password | test3.cpp:41:15:41:22 | password |
| test3.cpp:49:15:49:22 | password | test3.cpp:49:15:49:22 | password |
| test3.cpp:70:15:70:17 | ptr | test3.cpp:68:21:68:29 | password1 |
| test3.cpp:77:15:77:17 | ptr | test3.cpp:75:15:75:22 | password |
| test3.cpp:95:12:95:19 | password | test3.cpp:95:12:95:19 | password |
| test3.cpp:108:14:108:19 | buffer | test3.cpp:128:11:128:18 | password |
| test3.cpp:134:15:134:17 | ptr | test3.cpp:132:24:132:32 | password1 |
| test3.cpp:140:15:140:18 | data | test3.cpp:120:9:120:23 | global_password |

View File

@@ -125,18 +125,18 @@ void test_interprocedural(const char *password1)
{
char password[256];
my_recv(password, 256); // BAD: `password` is received plaintext [NOT DETECTED]
my_recv(password, 256); // BAD: `password` is received plaintext [detected on line 108]
}
{
const char *ptr = id(password1);
send(val(), ptr, strlen(ptr), val()); // BAD: `password1` is sent plaintext [NOT DETECTED]
send(val(), ptr, strlen(ptr), val()); // BAD: `password1` is sent plaintext
}
{
char *data = get_global_str();
send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext [NOT DETECTED]
send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext
}
}