C++: Support 'send' as well.

This commit is contained in:
Geoffrey White
2021-09-06 17:39:10 +01:00
parent 29ad3bf7f8
commit 1707d67adb
3 changed files with 35 additions and 13 deletions

View File

@@ -17,17 +17,36 @@ import semmle.code.cpp.security.FileWrite
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
// TODO: network send?
/**
* TODO
* A function call that sends or receives data over a network.
*/
class NetworkRecv extends FunctionCall {
NetworkRecv() { this.getTarget().hasGlobalName("recv") }
Expr getData() { result = this.getArgument(1) }
abstract class NetworkSendRecv extends FunctionCall {
/**
* Gets the expression for the buffer to be sent from / received into.
*/
abstract Expr getDataExpr();
}
from NetworkRecv recv, SensitiveExpr e
where DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(recv.(NetworkRecv).getData()))
select recv, e
/**
* A function call that sends data over a network.
*
* note: functions such as `read` may be reading from a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it probably isn't very important which query reports a result as long as its reported exactly once.
*/
class NetworkSend extends NetworkSendRecv {
NetworkSend() { this.getTarget().hasGlobalName("send") }
override Expr getDataExpr() { result = this.getArgument(1) }
}
/**
* A function call that receives data over a network.
*/
class NetworkRecv extends NetworkSendRecv {
NetworkRecv() { this.getTarget().hasGlobalName("recv") }
override Expr getDataExpr() { result = this.getArgument(1) }
}
from NetworkSendRecv transmission, SensitiveExpr e
where DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(transmission.getDataExpr()))
select transmission, e

View File

@@ -1,3 +1,6 @@
| 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 |

View File

@@ -17,11 +17,11 @@ void test_send(const char *password1, const char *password2, const char *passwor
{
LogonUserA(val(), val(), password1, val(), val(), val()); // proof `password1` is plaintext
send(val(), password1, strlen(password1), val()); // BAD: `password1` is sent plaintext (certainly) [NOT DETECTED]
send(val(), password1, strlen(password1), val()); // BAD: `password1` is sent plaintext (certainly)
}
{
send(val(), password2, strlen(password2), val()); // BAD: `password2` is sent plaintext (probably) [NOT DETECTED]
send(val(), password2, strlen(password2), val()); // BAD: `password2` is sent plaintext (probably)
}
{
@@ -67,7 +67,7 @@ void test_dataflow(const char *password1)
{
const char *ptr = password1;
send(val(), ptr, strlen(ptr), val()); // BAD: `password` is sent plaintext [NOT DETECTED]
send(val(), ptr, strlen(ptr), val()); // BAD: `password` is sent plaintext
}
{