C++: Test dataflow and other slightly more complex cases.

This commit is contained in:
Geoffrey White
2021-09-06 18:08:54 +01:00
parent cd5a5347fc
commit 29ad3bf7f8
2 changed files with 90 additions and 8 deletions

View File

@@ -1,2 +1,3 @@
| test3.cpp:39:3:39:6 | call to recv | test3.cpp:39:15:39:22 | password |
| test3.cpp:47:3:47:6 | call to recv | test3.cpp:47:15:47:22 | password |
| 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:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password |

View File

@@ -1,10 +1,12 @@
typedef unsigned long size_t;
#define STDIN_FILENO (0)
size_t strlen(const char *s);
void send(int a, const void *buf, size_t bufLen, int d);
void recv(int a, void *buf, size_t bufLen, int d);
void send(int fd, const void *buf, size_t bufLen, int d);
void recv(int fd, void *buf, size_t bufLen, int d);
void read(int fd, void *buf, size_t bufLen);
void LogonUserA(int a, int b, const char *password, int d, int e, int f);
@@ -13,17 +15,17 @@ int val();
void test_send(const char *password1, const char *password2, const char *password_hash, const char *message)
{
{
LogonUserA(val(), val(), password1, val(), val(), val()); // proof `password` is plaintext
LogonUserA(val(), val(), password1, val(), val(), val()); // proof `password1` is plaintext
send(val(), password1, strlen(password1), val()); // BAD: `password` is sent plaintext (certainly) [NOT DETECTED]
send(val(), password1, strlen(password1), val()); // BAD: `password1` is sent plaintext (certainly) [NOT DETECTED]
}
{
send(val(), password2, strlen(password2), val()); // BAD: `password` is sent plaintext (probably) [NOT DETECTED]
send(val(), password2, strlen(password2), val()); // BAD: `password2` is sent plaintext (probably) [NOT DETECTED]
}
{
send(val(), password_hash, strlen(password_hash), val()); // GOOD: `password` is sent encrypted
send(val(), password_hash, strlen(password_hash), val()); // GOOD: `password_hash` is sent encrypted
}
{
@@ -59,3 +61,82 @@ void test_receive()
recv(val(), message, 256, val()); // GOOD: `message` is not a password
}
}
void test_dataflow(const char *password1)
{
{
const char *ptr = password1;
send(val(), ptr, strlen(ptr), val()); // BAD: `password` is sent plaintext [NOT DETECTED]
}
{
char password[256];
char *ptr = password;
recv(val(), ptr, 256, val()); // BAD: `password` is received plaintext
}
{
char buffer[256];
recv(val(), buffer, 256, val()); // BAD: `password` is received plaintext [NOT DETECTED]
char *password = buffer;
}
}
void test_read()
{
{
char password[256];
int fd = val();
read(fd, password, 256); // BAD: `password` is received plaintext [NOT DETECTED]
}
{
char password[256];
int fd = STDIN_FILENO;
read(fd, password, 256); // GOOD: `password` is received from stdin, not a network socket
}
}
void my_recv(char *buffer, size_t bufferSize)
{
recv(val(), buffer, bufferSize, val());
}
const char *id(const char *buffer)
{
return buffer;
}
char *global_password;
char *get_global_str()
{
return global_password;
}
void test_interprocedural(const char *password1)
{
{
char password[256];
my_recv(password, 256); // BAD: `password` is received plaintext [NOT DETECTED]
}
{
const char *ptr = id(password1);
send(val(), ptr, strlen(ptr), val()); // BAD: `password1` is sent plaintext [NOT DETECTED]
}
{
char *data = get_global_str();
send(val(), data, strlen(data), val()); // BAD: `global_password` is sent plaintext [NOT DETECTED]
}
}