Rust: Add .qhelp.

This commit is contained in:
Geoffrey White
2025-01-09 18:02:00 +00:00
parent babfa758a3
commit 59386597c3
3 changed files with 130 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Using a broken or weak cryptographic hash function can leave data
vulnerable, and should not be used in security related code.
</p>
<p>
A strong cryptographic hash function should be resistant to:
</p>
<ul>
<li>
<b>Pre-image attacks</b>. If you know a hash value <code>h(x)</code>,
you should not be able to easily find the input <code>x</code>.
</li>
<li>
<b>Collision attacks</b>. If you know a hash value <code>h(x)</code>,
you should not be able to easily find a different input
<code>y</code>
with the same hash value <code>h(x) = h(y)</code>.
</li>
<li>
<b>Brute force</b>. For passwords and other data with limited
input space, if you know a hash value <code>h(x)</code>
you should not be able to find the input <code>x</code> even using
a brute force attack (without significant computational effort).
</li>
</ul>
<p>
As an example, both MD5 and SHA-1 are known to be vulnerable to collision attacks.
</p>
<p>
All of MD5, SHA-1, SHA-2 and SHA-3 are weak against offline brute forcing, so
they are not suitable for hashing passwords. This includes SHA-224, SHA-256,
SHA-384 and SHA-512, which are in the SHA-2 family.
</p>
<p>
Since it's OK to use a weak cryptographic hash function in a non-security
context, this query only alerts when these are used to hash sensitive
data (such as passwords, certificates, usernames).
</p>
</overview>
<recommendation>
<p>
Ensure that you use a strong, modern cryptographic hash function, such as:
</p>
<ul>
<li>
Argon2, scrypt, bcrypt, or PBKDF2 for passwords and other data with limited input space where
a dictionary-like attack is feasible.
</li>
<li>
SHA-2, or SHA-3 in other cases.
</li>
</ul>
<p>
Note that special purpose algorithms, which are used to ensure that a message comes from a
particular sender, exist for message authentication. These algorithms should be used when
appropriate, as they address common vulnerabilities of simple hashing schemes in this context.
</p>
</recommendation>
<example>
<p>
The following examples show hashing sensitive data using the MD5 hashing algorithm that is known to be
vulnerable to collision attacks, and hashing passwords using the SHA-3 algorithm that is weak to brute
force attacks:
</p>
<sample src="WeakSensitiveDataHashingBad.rs"/>
<p>
To make these secure, we can use the SHA-3 algorithm for sensitive data and Argon2 for passwords:
</p>
<sample src="WeakSensitiveDataHashingGood.rs"/>
</example>
<references>
<li>
OWASP:
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html">
Password Storage Cheat Sheet
</a>
and
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html">
Transport Layer Security Cheat Sheet
</a>
GitHub:
<a href="https://github.com/RustCrypto/hashes?tab=readme-ov-file#rustcrypto-hashes">
RustCrypto: Hashes
</a>
and
<a href="https://github.com/RustCrypto/password-hashes?tab=readme-ov-file#rustcrypto-password-hashes">
RustCrypto: Password Hashes
</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,10 @@
// MD5 is not appropriate for hashing sensitive data.
let mut md5_hasher = md5::Md5::new();
...
md5_hasher.update(emergency_contact); // BAD
md5_hasher.update(credit_card_no); // BAD
...
my_hash = md5_hasher.finalize();
// SHA3-256 is not appropriate for hashing passwords.
my_hash = sha3::Sha3_256::digest(password); // BAD

View File

@@ -0,0 +1,11 @@
// SHA3-256 *is* appropriate for hashing sensitive data.
let mut sha3_256_hasher = sha3::Sha3_256::new();
...
sha3_256_hasher.update(emergency_contact); // GOOD
sha3_256_hasher.update(credit_card_no); // GOOD
...
my_hash = sha3_256_hasher.finalize();
// Argon2 is appropriate for hashing passwords.
let argon2_salt = argon2::password_hash::Salt::from_b64(salt)?;
my_hash = argon2::Argon2::default().hash_password(password.as_bytes(), argon2_salt)?.to_string(); // GOOD