Skip to content

Commit 5938659

Browse files
committed
Rust: Add .qhelp.
1 parent babfa75 commit 5938659

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
Using a broken or weak cryptographic hash function can leave data
8+
vulnerable, and should not be used in security related code.
9+
</p>
10+
11+
<p>
12+
A strong cryptographic hash function should be resistant to:
13+
</p>
14+
<ul>
15+
<li>
16+
<b>Pre-image attacks</b>. If you know a hash value <code>h(x)</code>,
17+
you should not be able to easily find the input <code>x</code>.
18+
</li>
19+
<li>
20+
<b>Collision attacks</b>. If you know a hash value <code>h(x)</code>,
21+
you should not be able to easily find a different input
22+
<code>y</code>
23+
with the same hash value <code>h(x) = h(y)</code>.
24+
</li>
25+
<li>
26+
<b>Brute force</b>. For passwords and other data with limited
27+
input space, if you know a hash value <code>h(x)</code>
28+
you should not be able to find the input <code>x</code> even using
29+
a brute force attack (without significant computational effort).
30+
</li>
31+
</ul>
32+
33+
<p>
34+
As an example, both MD5 and SHA-1 are known to be vulnerable to collision attacks.
35+
</p>
36+
37+
<p>
38+
All of MD5, SHA-1, SHA-2 and SHA-3 are weak against offline brute forcing, so
39+
they are not suitable for hashing passwords. This includes SHA-224, SHA-256,
40+
SHA-384 and SHA-512, which are in the SHA-2 family.
41+
</p>
42+
43+
<p>
44+
Since it's OK to use a weak cryptographic hash function in a non-security
45+
context, this query only alerts when these are used to hash sensitive
46+
data (such as passwords, certificates, usernames).
47+
</p>
48+
49+
</overview>
50+
<recommendation>
51+
52+
<p>
53+
Ensure that you use a strong, modern cryptographic hash function, such as:
54+
</p>
55+
56+
<ul>
57+
<li>
58+
Argon2, scrypt, bcrypt, or PBKDF2 for passwords and other data with limited input space where
59+
a dictionary-like attack is feasible.
60+
</li>
61+
<li>
62+
SHA-2, or SHA-3 in other cases.
63+
</li>
64+
</ul>
65+
66+
<p>
67+
Note that special purpose algorithms, which are used to ensure that a message comes from a
68+
particular sender, exist for message authentication. These algorithms should be used when
69+
appropriate, as they address common vulnerabilities of simple hashing schemes in this context.
70+
</p>
71+
72+
</recommendation>
73+
<example>
74+
75+
<p>
76+
The following examples show hashing sensitive data using the MD5 hashing algorithm that is known to be
77+
vulnerable to collision attacks, and hashing passwords using the SHA-3 algorithm that is weak to brute
78+
force attacks:
79+
</p>
80+
<sample src="WeakSensitiveDataHashingBad.rs"/>
81+
82+
<p>
83+
To make these secure, we can use the SHA-3 algorithm for sensitive data and Argon2 for passwords:
84+
</p>
85+
<sample src="WeakSensitiveDataHashingGood.rs"/>
86+
87+
</example>
88+
<references>
89+
<li>
90+
OWASP:
91+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html">
92+
Password Storage Cheat Sheet
93+
</a>
94+
and
95+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html">
96+
Transport Layer Security Cheat Sheet
97+
</a>
98+
GitHub:
99+
<a href="https://github.com/RustCrypto/hashes?tab=readme-ov-file#rustcrypto-hashes">
100+
RustCrypto: Hashes
101+
</a>
102+
and
103+
<a href="https://github.com/RustCrypto/password-hashes?tab=readme-ov-file#rustcrypto-password-hashes">
104+
RustCrypto: Password Hashes
105+
</a>
106+
</li>
107+
</references>
108+
109+
</qhelp>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// MD5 is not appropriate for hashing sensitive data.
2+
let mut md5_hasher = md5::Md5::new();
3+
...
4+
md5_hasher.update(emergency_contact); // BAD
5+
md5_hasher.update(credit_card_no); // BAD
6+
...
7+
my_hash = md5_hasher.finalize();
8+
9+
// SHA3-256 is not appropriate for hashing passwords.
10+
my_hash = sha3::Sha3_256::digest(password); // BAD
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// SHA3-256 *is* appropriate for hashing sensitive data.
2+
let mut sha3_256_hasher = sha3::Sha3_256::new();
3+
...
4+
sha3_256_hasher.update(emergency_contact); // GOOD
5+
sha3_256_hasher.update(credit_card_no); // GOOD
6+
...
7+
my_hash = sha3_256_hasher.finalize();
8+
9+
// Argon2 is appropriate for hashing passwords.
10+
let argon2_salt = argon2::password_hash::Salt::from_b64(salt)?;
11+
my_hash = argon2::Argon2::default().hash_password(password.as_bytes(), argon2_salt)?.to_string(); // GOOD

0 commit comments

Comments
 (0)