Skip to content

Commit e585e67

Browse files
committed
Rust: Add qhelp and examples.
1 parent a3110a9 commit e585e67

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>
8+
Sensitive information that is stored unencrypted in a database is accessible to an attacker
9+
who gains access to that database. For example, the information could be accessed by any
10+
process or user in a rooted device, or exposed through another vulnerability.
11+
</p>
12+
</overview>
13+
14+
<recommendation>
15+
<p>
16+
Either encrypt the entire database, or ensure that each piece of sensitive information is
17+
encrypted before being stored. In general, decrypt sensitive information only at the point
18+
where it is necessary for it to be used in cleartext. Avoid storing sensitive information
19+
at all if you do not need to keep it.
20+
</p>
21+
</recommendation>
22+
23+
<example>
24+
<p>
25+
The following example stores sensitive information into a database without encryption, using the
26+
SQLx library:
27+
</p>
28+
<sample src="CleartextStorageDatabaseBad.rs"/>
29+
<p>
30+
This is insecure because the sensitive data is stored in cleartext, making it accessible to anyone
31+
with access to the database.
32+
</p>
33+
<p>
34+
To fix this, we can either encrypt the entire database or encrypt just the sensitive data before it
35+
is stored. Take care to select a secure modern encryption algorithm and put suitable key management
36+
practices into place. In the following example, we have encrypted the sensitive data using 256-bit
37+
AES before storing it in the database:
38+
</p>
39+
<sample src="CleartextStorageDatabaseGood.rs"/>
40+
</example>
41+
42+
<references>
43+
<li>
44+
OWASP Top 10:2021:
45+
<a href="https://owasp.org/Top10/A02_2021-Cryptographic_Failures/">A02:2021 - Cryptographic Failures</a>.
46+
</li>
47+
<li>
48+
OWASP:
49+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html">Key Management Cheat Sheet</a>.
50+
</li>
51+
</references>
52+
53+
</qhelp>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
let query = "INSERT INTO PAYMENTDETAILS(ID, CARDNUM) VALUES(?, ?)";
2+
let result = sqlx::query(query)
3+
.bind(id)
4+
.bind(credit_card_number) // BAD: Cleartext storage of sensitive data in the database
5+
.execute(pool)
6+
.await?;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
fn encrypt(text: String, encryption_key: &aes_gcm::Key<Aes256Gcm>) -> String {
3+
// encrypt text -> ciphertext
4+
let cipher = Aes256Gcm::new(&encryption_key);
5+
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
6+
let ciphertext = cipher.encrypt(&nonce, text.as_ref()).unwrap();
7+
8+
// append (nonce, ciphertext)
9+
let mut combined = nonce.to_vec();
10+
combined.extend(ciphertext);
11+
12+
// encode to base64 string
13+
BASE64_STANDARD.encode(combined)
14+
}
15+
16+
fn decrypt(data: String, encryption_key: &aes_gcm::Key<Aes256Gcm>) -> String {
17+
let cipher = Aes256Gcm::new(&encryption_key);
18+
19+
// decode base64 string
20+
let decoded = BASE64_STANDARD.decode(data).unwrap();
21+
22+
// split into (nonce, ciphertext)
23+
let nonce_size = <Aes256Gcm as AeadCore>::NonceSize::to_usize();
24+
let (nonce, ciphertext) = decoded.split_at(nonce_size);
25+
26+
// decrypt ciphertext -> plaintext
27+
let plaintext = cipher.decrypt(nonce.into(), ciphertext).unwrap();
28+
String::from_utf8(plaintext).unwrap()
29+
}
30+
31+
...
32+
33+
let encryption_key = Aes256Gcm::generate_key(OsRng);
34+
35+
...
36+
37+
let query = "INSERT INTO PAYMENTDETAILS(ID, CARDNUM) VALUES(?, ?)";
38+
let result = sqlx::query(query)
39+
.bind(id)
40+
.bind(encrypt(credit_card_number, &encryption_key)) // GOOD: Encrypted storage of sensitive data in the database
41+
.execute(pool)
42+
.await?;

0 commit comments

Comments
 (0)