-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust: Weak hashing query #18471
Rust: Weak hashing query #18471
Conversation
QHelp previews: rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.qhelpUse of a broken or weak cryptographic hashing algorithm on sensitive dataA broken or weak cryptographic hash function can leave data vulnerable, and should not be used in security-related code. A strong cryptographic hash function should be resistant to:
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. 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). RecommendationEnsure that you use a strong, modern cryptographic hash function, such as:
ExampleThe 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: // 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 To make these secure, we can use the SHA-3 algorithm for sensitive data and Argon2 for passwords: // 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 References
|
| file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::crate::fmt::format | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::crate::fmt::format | MaD:9 | | ||
| file://:0:0:0:0 | [summary param] self in lang:alloc::_::<crate::string::String>::as_str | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::string::String>::as_str | MaD:7 | | ||
| file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::crate::fmt::format | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::crate::fmt::format | MaD:14 | | ||
| file://:0:0:0:0 | [summary param] self in lang:alloc::_::<crate::string::String>::as_str | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::string::String>::as_str | MaD:12 | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hvitved this test is unrelated to the PR, apart from that they both use models-as-data. I think that means we shouldn't be outputting these IDs in the tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably be translating the IDs, like we do in query tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is that done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would have to pull out the relevant bits from the ShowProvenance
module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to do this, or shall I do this as a follow-up PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's do it on a separate PR.
DCA LGTM (uneventful). |
rust/ql/lib/codeql/rust/security/WeakSensitiveDataHashingExtensions.qll
Outdated
Show resolved
Hide resolved
rust/ql/lib/codeql/rust/security/WeakSensitiveDataHashingExtensions.qll
Outdated
Show resolved
Hide resolved
rust/ql/lib/codeql/rust/security/WeakSensitiveDataHashingExtensions.qll
Outdated
Show resolved
Hide resolved
rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql
Outdated
Show resolved
Hide resolved
| file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::crate::fmt::format | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::crate::fmt::format | MaD:9 | | ||
| file://:0:0:0:0 | [summary param] self in lang:alloc::_::<crate::string::String>::as_str | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::string::String>::as_str | MaD:7 | | ||
| file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::crate::fmt::format | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::crate::fmt::format | MaD:14 | | ||
| file://:0:0:0:0 | [summary param] self in lang:alloc::_::<crate::string::String>::as_str | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::string::String>::as_str | MaD:12 | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably be translating the IDs, like we do in query tests.
let mut md5_hasher = md5::Md5::new(); | ||
md5_hasher.update(b"abc"); | ||
md5_hasher.update(harmless); | ||
md5_hasher.update(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we know why this is missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure exactly. It's the method calls (rather than function calls) where we're having difficulty.
(MethodCallExpr).getResolvedCrateOrigin()
and (MethodCallExpr).getResolvedPath()
work as expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is resolving method call crates / paths and method calls as MAD sources something we expect to work (tested?), or are there known to be missing features here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can take a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason it doesn't work is because your logic is restricted to calls where the function is a PathExpr
, which is not the case above. In order to extend to the case above, I think we need to know the type of md5_hasher
, but that is currently not available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'll make a note in the issue for improvements to this query that we're waiting for type inference before we can fix that bit by replacing the PathExpr
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@geoffw0 - Approving this on behalf of Docs ✨
Left a few minor comments/suggestions.
rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.qhelp
Outdated
Show resolved
Hide resolved
rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.qhelp
Outdated
Show resolved
Hide resolved
rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.qhelp
Outdated
Show resolved
Hide resolved
rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.qhelp
Outdated
Show resolved
Hide resolved
rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.qhelp
Outdated
Show resolved
Hide resolved
rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.qhelp
Outdated
Show resolved
Hide resolved
Co-authored-by: mc <[email protected]>
Thanks for the reviews.
|
I think all issues have been resolved, I just need a re-approval (preferably from code). |
Add a weak hashing query for Rust (
rust/weak-sensitive-data-hashing
). We already had the necessary cryptography concepts, I recently added a sensitive data library, and @hvitved added the ability to express sources and sinks in MaD - which is everything needed for the query. Most of the new code is closely based on what we have in other languages, e.g. Ruby.Naturally there are plans to add further models and data flow to catch more of the test cases in future, after the basic query has been merged.
Needs: