This repository was archived by the owner on Jan 5, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 126
Adding Crypto Query/Library #284
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
95342cd
adding go crypto library
7ce9e97
removing precision tag
4433f19
pr fixes for typo and qldoc
2ee654d
attempting to fix autoformat build error
79002b0
pr fixes
37eca95
restructured library
40d3f22
fixing commit error
7f980a4
pr fixes
a58070f
fixed build test error
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,245 @@ | ||
| /** | ||
| * Provides classes for modeling cryptographic libraries. | ||
| */ | ||
|
|
||
| import go | ||
|
|
||
| /** | ||
| * Names of cryptographic algorithms, separated into strong and weak variants. | ||
| * | ||
| * The names are normalized: upper-case, no spaces, dashes or underscores. | ||
| * | ||
| * The names are inspired by the names used in real world crypto libraries. | ||
| * | ||
| * The classification into strong and weak are based on OWASP and Wikipedia (2020). | ||
| * | ||
| * Sources (more links in qhelp file): | ||
| * https://en.wikipedia.org/wiki/Strong_cryptography#Cryptographically_strong_algorithms | ||
| * https://en.wikipedia.org/wiki/Strong_cryptography#Examples | ||
| * https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html | ||
| */ | ||
| private module AlgorithmNames { | ||
| predicate isStrongHashingAlgorithm(string name) { | ||
| name = "DSA" or | ||
| name = "ED25519" or | ||
| name = "ES256" or | ||
| name = "ECDSA256" or | ||
| name = "ES384" or | ||
| name = "ECDSA384" or | ||
| name = "ES512" or | ||
| name = "ECDSA512" or | ||
| name = "SHA2" or | ||
| name = "SHA224" or | ||
| name = "SHA256" or | ||
| name = "SHA384" or | ||
| name = "SHA512" or | ||
| name = "SHA3" | ||
| } | ||
|
|
||
| predicate isWeakHashingAlgorithm(string name) { | ||
| name = "HAVEL128" or | ||
| name = "MD2" or | ||
| name = "MD4" or | ||
| name = "MD5" or | ||
| name = "PANAMA" or | ||
| name = "RIPEMD" or | ||
| name = "RIPEMD128" or | ||
| name = "RIPEMD256" or | ||
| name = "RIPEMD320" or | ||
| name = "SHA0" or | ||
| name = "SHA1" | ||
| } | ||
|
|
||
| predicate isStrongEncryptionAlgorithm(string name) { | ||
| name = "AES" or | ||
| name = "AES128" or | ||
| name = "AES192" or | ||
| name = "AES256" or | ||
| name = "AES512" or | ||
| name = "RSA" or | ||
| name = "RABBIT" or | ||
| name = "BLOWFISH" | ||
| } | ||
|
|
||
| predicate isWeakEncryptionAlgorithm(string name) { | ||
| name = "DES" or | ||
| name = "3DES" or | ||
| name = "TRIPLEDES" or | ||
| name = "TDEA" or | ||
| name = "TRIPLEDEA" or | ||
| name = "ARC2" or | ||
| name = "RC2" or | ||
| name = "ARC4" or | ||
| name = "RC4" or | ||
| name = "ARCFOUR" or | ||
| name = "ARC5" or | ||
| name = "RC5" | ||
| } | ||
|
|
||
| predicate isStrongPasswordHashingAlgorithm(string name) { | ||
| name = "ARGON2" or | ||
| name = "PBKDF2" or | ||
| name = "BCRYPT" or | ||
| name = "SCRYPT" | ||
| } | ||
|
|
||
| predicate isWeakPasswordHashingAlgorithm(string name) { none() } | ||
| } | ||
|
|
||
| private import AlgorithmNames | ||
|
|
||
| /** | ||
| * A cryptographic algorithm. | ||
| */ | ||
| private newtype TCryptographicAlgorithm = | ||
| MkHashingAlgorithm(string name, boolean isWeak) { | ||
| isStrongHashingAlgorithm(name) and isWeak = false | ||
| or | ||
| isWeakHashingAlgorithm(name) and isWeak = true | ||
| } or | ||
| MkEncryptionAlgorithm(string name, boolean isWeak) { | ||
| isStrongEncryptionAlgorithm(name) and isWeak = false | ||
| or | ||
| isWeakEncryptionAlgorithm(name) and isWeak = true | ||
| } or | ||
| MkPasswordHashingAlgorithm(string name, boolean isWeak) { | ||
| isStrongPasswordHashingAlgorithm(name) and isWeak = false | ||
| or | ||
| isWeakPasswordHashingAlgorithm(name) and isWeak = true | ||
| } | ||
|
|
||
| /** | ||
| * A cryptographic algorithm. | ||
| */ | ||
| abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { | ||
| /** Gets a textual representation of this element. */ | ||
| string toString() { result = getName() } | ||
|
|
||
| /** | ||
| * Gets the name of this algorithm. | ||
| */ | ||
| abstract string getName(); | ||
|
|
||
| /** | ||
| * Holds if the name of this algorithm matches `name` modulo case, | ||
| * white space, dashes and underscores. | ||
| */ | ||
| bindingset[name] | ||
| predicate matchesName(string name) { | ||
| exists(name.regexpReplaceAll("[-_]", "").regexpFind("(?i)\\Q" + getName() + "\\E", _, _)) | ||
| } | ||
|
|
||
| /** | ||
| * Holds if this algorithm is weak. | ||
| */ | ||
| abstract predicate isWeak(); | ||
| } | ||
|
|
||
| /** | ||
| * A hashing algorithm such as `MD5` or `SHA512`. | ||
| */ | ||
| class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { | ||
| string name; | ||
| boolean isWeak; | ||
|
|
||
| HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } | ||
|
|
||
| override string getName() { result = name } | ||
|
|
||
| override predicate isWeak() { isWeak = true } | ||
| } | ||
|
|
||
| /** | ||
| * An encryption algorithm such as `DES` or `AES512`. | ||
| */ | ||
| class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { | ||
| string name; | ||
| boolean isWeak; | ||
|
|
||
| EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } | ||
|
|
||
| override string getName() { result = name } | ||
|
|
||
| override predicate isWeak() { isWeak = true } | ||
| } | ||
|
|
||
| /** | ||
| * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. | ||
| */ | ||
| class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { | ||
| string name; | ||
| boolean isWeak; | ||
|
|
||
| PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } | ||
|
|
||
| override string getName() { result = name } | ||
|
|
||
| override predicate isWeak() { isWeak = true } | ||
| } | ||
|
|
||
| /** | ||
| * An application of a cryptographic algorithm. | ||
| */ | ||
| abstract class CryptographicOperation extends DataFlow::Node { | ||
| /** | ||
| * Gets the input the algorithm is used on, e.g. the plain text input to be encrypted. | ||
| */ | ||
| abstract Expr getInput(); | ||
|
|
||
| /** | ||
| * Gets the applied algorithm. | ||
| */ | ||
| abstract CryptographicAlgorithm getAlgorithm(); | ||
| } | ||
|
|
||
| /** | ||
| * Models cryptographic operations of the `crypto/md5` package. | ||
| */ | ||
| class Md5 extends CryptographicOperation, DataFlow::CallNode { | ||
| Md5() { getTarget().hasQualifiedName("crypto/md5", ["New", "Sum"]) } | ||
|
|
||
| override Expr getInput() { result = this.getArgument(0).asExpr() } | ||
|
|
||
| override CryptographicAlgorithm getAlgorithm() { | ||
| result.matchesName(this.getTarget().getPackage().getName()) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Models cryptographic operations of the `crypto/sha1` package. | ||
| */ | ||
| class Sha1 extends CryptographicOperation, DataFlow::CallNode { | ||
| Sha1() { getTarget().hasQualifiedName("crypto/sha1", ["New", "Sum"]) } | ||
|
|
||
| override Expr getInput() { result = this.getArgument(0).asExpr() } | ||
|
|
||
| override CryptographicAlgorithm getAlgorithm() { | ||
| result.matchesName(this.getTarget().getPackage().getName()) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Models cryptographic operations of the `crypto/des` package. | ||
| */ | ||
| class Des extends CryptographicOperation, DataFlow::CallNode { | ||
| Des() { getTarget().hasQualifiedName("crypto/des", ["NewCipher", "NewTripleDESCipher"]) } | ||
|
|
||
| override Expr getInput() { result = this.getArgument(0).asExpr() } | ||
|
|
||
| override CryptographicAlgorithm getAlgorithm() { | ||
| result.matchesName(this.getTarget().getPackage().getName()) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Models cryptographic operations of the `crypto/rc4` package. | ||
| */ | ||
| class Rc4 extends CryptographicOperation, DataFlow::CallNode { | ||
| Rc4() { getTarget().hasQualifiedName("crypto/rc4", ["NewCipher"]) } | ||
|
|
||
| override Expr getInput() { result = this.getArgument(0).asExpr() } | ||
|
|
||
| override CryptographicAlgorithm getAlgorithm() { | ||
| result.matchesName(this.getTarget().getPackage().getName()) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| <!DOCTYPE qhelp PUBLIC | ||
| "-//Semmle//qhelp//EN" | ||
| "qhelp.dtd"> | ||
| <qhelp> | ||
| <overview> | ||
| <p> | ||
| Using weak cryptographic algorithms can leave data | ||
| vulnerable to being decrypted or forged by an attacker. | ||
| </p> | ||
|
|
||
| <p> | ||
| Many cryptographic algorithms provided by cryptography | ||
| libraries are known to be weak. Using such an | ||
| algorithm means that encrypted or hashed data is less | ||
| secure than it appears to be. | ||
| </p> | ||
|
|
||
| </overview> | ||
| <recommendation> | ||
|
|
||
| <p> | ||
| Ensure that you use a strong, modern cryptographic | ||
| algorithm. Use at least AES-128 or RSA-2048 for | ||
| encryption, and SHA-2 or SHA-3 for secure hashing. | ||
| </p> | ||
|
|
||
| </recommendation> | ||
| <example> | ||
|
|
||
| <p> | ||
| The following code uses the different packages to encrypt/hash | ||
| some secret data. The first few examples uses DES, MD5, RC4, and SHA1, | ||
| which are older algorithms that are now considered weak. The following | ||
| examples use AES and SHA256, which are stronger, more modern algorithms. | ||
| </p> | ||
|
|
||
| <sample src="examples/Crypto.go" /> | ||
|
|
||
| </example> | ||
|
|
||
| <references> | ||
| <li>OWASP: <a | ||
| href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html">Cryptographic Storage Cheat Sheet</a>. | ||
| </li> | ||
| <li>Wikipedia: <a | ||
| href="https://en.wikipedia.org/wiki/Strong_cryptography#Cryptographically_strong_algorithms">Cryptographically Strong Algorithms</a>. | ||
| </li> | ||
| <li>Wikipedia: <a | ||
| href="https://en.wikipedia.org/wiki/Strong_cryptography#Examples">Strong Cryptography Examples</a>. | ||
| </li> | ||
| <li>NIST, FIPS 140 Annex a: <a href="http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf"> Approved Security Functions</a>.</li> | ||
| <li>NIST, SP 800-131A: <a href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf"> Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths</a>.</li> | ||
| </references> | ||
|
|
||
| </qhelp> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /** | ||
| * @name Use of a weak cryptographic algorithm | ||
| * @description Using weak cryptographic algorithms can allow an attacker to compromise security. | ||
| * @kind path-problem | ||
| * @problem.severity error | ||
| * @id go/weak-crypto-algorithm | ||
| * @tags security | ||
dilanbhalla marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * external/cwe/cwe-327 | ||
| */ | ||
|
|
||
| import go | ||
| import WeakCryptoAlgorithmCustomizations::WeakCryptoAlgorithm | ||
| import DataFlow::PathGraph | ||
|
|
||
| from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink | ||
| where cfg.hasFlowPath(source, sink) | ||
| select sink.getNode(), source, sink, "$@ is used in a weak cryptographic algorithm.", | ||
| source.getNode(), "Sensitive data" | ||
61 changes: 61 additions & 0 deletions
61
ql/src/experimental/CWE-327/WeakCryptoAlgorithmCustomizations.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| /** | ||
| * Provides default sources, sinks and sanitizers for reasoning about | ||
| * sensitive information in weak cryptographic algorithms, | ||
| * as well as extension points for adding your own. | ||
| */ | ||
|
|
||
| import go | ||
| private import semmle.go.security.SensitiveActions | ||
| private import CryptoLibraries | ||
|
|
||
| module WeakCryptoAlgorithm { | ||
| /** | ||
| * A data flow source for sensitive information in weak cryptographic algorithms. | ||
| */ | ||
| abstract class Source extends DataFlow::Node { } | ||
|
|
||
| /** | ||
| * A data flow sink for sensitive information in weak cryptographic algorithms. | ||
| */ | ||
| abstract class Sink extends DataFlow::Node { } | ||
|
|
||
| /** | ||
| * A sanitizer for sensitive information in weak cryptographic algorithms. | ||
| */ | ||
| abstract class Sanitizer extends DataFlow::Node { } | ||
|
|
||
| /** | ||
| * A sensitive source. | ||
| */ | ||
| class SensitiveSource extends Source { | ||
| SensitiveSource() { this.asExpr() instanceof SensitiveExpr } | ||
| } | ||
|
|
||
| /** | ||
| * An expression used by a weak cryptographic algorithm. | ||
| */ | ||
| class WeakCryptographicOperationSink extends Sink { | ||
| WeakCryptographicOperationSink() { | ||
| exists(CryptographicOperation application | | ||
| application.getAlgorithm().isWeak() and | ||
| this.asExpr() = application.getInput() | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * A configuration depicting taint flow from sensitive information to weak cryptographic algorithms. | ||
| */ | ||
| class Configuration extends TaintTracking::Configuration { | ||
| Configuration() { this = "WeakCryptoAlgorithm" } | ||
|
|
||
| override predicate isSource(DataFlow::Node source) { source instanceof Source } | ||
|
|
||
| override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } | ||
|
|
||
| override predicate isSanitizer(DataFlow::Node node) { | ||
| super.isSanitizer(node) or | ||
| node instanceof Sanitizer | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.