Skip to content

Commit 52020f7

Browse files
authored
Merge pull request #17028 from geoffw0/cryptodoc
C++: Improve query doc advice for using encryption
2 parents 91f5f08 + 27314aa commit 52020f7

File tree

5 files changed

+49
-22
lines changed

5 files changed

+49
-22
lines changed

cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ contains sensitive data that could somehow be retrieved by an attacker.</p>
1010
</overview>
1111
<recommendation>
1212

13-
<p>Use alternative platform-supplied functions that will not get optimized away. Examples of such
14-
functions include <code>memset_s</code>, <code>SecureZeroMemory</code>, and <code>bzero_explicit</code>.
15-
Alternatively, passing the <code>-fno-builtin-memset</code> option to the GCC/Clang compiler usually
16-
also prevents the optimization. Finally, you can use the public-domain <code>secure_memzero</code> function
17-
(see references below). This function, however, is not guaranteed to work on all platforms and compilers.</p>
13+
<p>Use <code>memset_s</code> (from C11) instead of <code>memset</code>, as <code>memset_s</code> will not
14+
get optimized away. Alternatively use platform-supplied functions such as <code>SecureZeroMemory</code> or
15+
<code>bzero_explicit</code> that make the same guarantee. Passing the <code>-fno-builtin-memset</code>
16+
option to the GCC/Clang compiler usually also prevents the optimization. Finally, you can use the
17+
public-domain <code>secure_memzero</code> function (see references below). This function, however, is not
18+
guaranteed to work on all platforms and compilers.</p>
1819

1920
</recommendation>
2021
<example>
Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
1-
void writeCredentials() {
2-
char *password = "cleartext password";
3-
FILE* file = fopen("credentials.txt", "w");
4-
1+
#include <sodium.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
5+
void writeCredentialsBad(FILE *file, const char *cleartextCredentials) {
56
// BAD: write password to disk in cleartext
6-
fputs(password, file);
7-
8-
// GOOD: encrypt password first
9-
char *encrypted = encrypt(password);
10-
fputs(encrypted, file);
7+
fputs(cleartextCredentials, file);
118
}
129

10+
int writeCredentialsGood(FILE *file, const char *cleartextCredentials, const unsigned char *key, const unsigned char *nonce) {
11+
size_t credentialsLen = strlen(cleartextCredentials);
12+
size_t ciphertext_len = crypto_secretbox_MACBYTES + credentialsLen;
13+
unsigned char *ciphertext = malloc(ciphertext_len);
14+
if (!ciphertext) {
15+
logError();
16+
return -1;
17+
}
18+
19+
// encrypt the password first
20+
if (crypto_secretbox_easy(ciphertext, (const unsigned char *)cleartextCredentials, credentialsLen, nonce, key) != 0) {
21+
free(ciphertext);
22+
logError();
23+
return -1;
24+
}
25+
26+
// GOOD: write encrypted password to disk
27+
fwrite(ciphertext, 1, ciphertext_len, file);
28+
29+
free(ciphertext);
30+
return 0;
31+
}

cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,20 @@ cleartext.</p>
1919
<example>
2020

2121
<p>The following example shows two ways of storing user credentials in a file. In the 'BAD' case,
22-
the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before
22+
the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before
2323
storing them.</p>
2424

2525
<sample src="CleartextStorage.c" />
2626

27+
<p>Note that for the 'GOOD' example to work we need to link against an encryption library (in this case libsodium),
28+
initialize it with a call to <code>sodium_init</code>, and create the key and nonce with
29+
<code>crypto_secretbox_keygen</code> and <code>randombytes_buf</code> respectively. We also need to store those
30+
details securely so they can be used for decryption.</p>
31+
2732
</example>
2833
<references>
2934

30-
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
35+
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
3136
<li>M. Howard and D. LeBlanc, <i>Writing Secure Code</i>, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.</li>
3237

3338

cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
void bad(void) {
3-
char *password = "cleartext password";
3+
const char *password = "cleartext password";
44
sqlite3 *credentialsDB;
55
sqlite3_stmt *stmt;
66

@@ -16,14 +16,15 @@ void bad(void) {
1616
}
1717
}
1818

19-
void good(void) {
20-
char *password = "cleartext password";
19+
void good(const char *secretKey) {
20+
const char *password = "cleartext password";
2121
sqlite3 *credentialsDB;
2222
sqlite3_stmt *stmt;
2323

2424
if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) {
2525
// GOOD: database encryption enabled:
26-
sqlite3_exec(credentialsDB, "PRAGMA key = 'secretKey!'", NULL, NULL, NULL);
26+
std::string setKeyString = std::string("PRAGMA key = '") + secretKey + "'";
27+
sqlite3_exec(credentialsDB, setKeyString.c_str(), NULL, NULL, NULL);
2728
sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL);
2829
if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) {
2930
sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT);
@@ -33,4 +34,3 @@ void good(void) {
3334
}
3435
}
3536
}
36-

cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.qhelp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ In the 'GOOD' case, the database (and thus the credentials) are encrypted.</p>
2020

2121
<sample src="CleartextSqliteDatabase.c" />
2222

23+
<p>Note that for the 'GOOD' example to work we need to provide a secret key. Secure key generation and storage is required.</p>
24+
2325
</example>
2426
<references>
2527

26-
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
28+
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
2729
<li>M. Howard and D. LeBlanc, <i>Writing Secure Code</i>, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.</li>
2830

2931

0 commit comments

Comments
 (0)