diff --git a/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptoAlgorithmNames.qll b/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptoAlgorithmNames.qll index 8275fdd83e60..c828a804fb85 100644 --- a/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptoAlgorithmNames.qll +++ b/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptoAlgorithmNames.qll @@ -22,6 +22,14 @@ predicate isSymmetricAlgorithm(string name) { ] } +predicate isHmacAlgorithm(string name) { + name = + [ + "hmacmd5", "hmacsha1", "hmacripemd160", "hmacsha256", "hmacsha384", "hmacsha512", + "hmacsha3256", "hmacsha3384", "hmacsha3512" + ] +} + predicate isCipherBlockModeAlgorithm(string name) { name = ["cbc", "gcm", "ccm", "cfb", "ofb", "cfb8", "ctr", "openpgp", "xts", "eax", "siv", "ecb"] } diff --git a/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptoArtifact.qll b/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptoArtifact.qll index 0aa91bff8c43..eb9cd159d61c 100644 --- a/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptoArtifact.qll +++ b/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptoArtifact.qll @@ -29,6 +29,14 @@ abstract class SymmetricAlgorithm extends CryptographicAlgorithm { } } +abstract class HmacAlgorithm extends CryptographicAlgorithm { + final string getHmacName() { + if exists(string n | n = this.getName() and isHmacAlgorithm(n)) + then result = this.getName() + else result = unknownAlgorithm() + } +} + abstract class BlockMode extends CryptographicAlgorithm { final string getBlockModeName() { if exists(string n | n = this.getName() and isCipherBlockModeAlgorithm(n)) diff --git a/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptographyModule.qll b/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptographyModule.qll index 0e6b2a434733..e0665792e57a 100644 --- a/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptographyModule.qll +++ b/powershell/ql/lib/semmle/code/powershell/security/cryptography/CryptographyModule.qll @@ -176,6 +176,46 @@ class CipherBlockStringConstExpr extends BlockMode { override string getName() { result = modeName } } +class HmacAlgorithmObjectCreation extends HmacAlgorithm, CryptoAlgorithmObjectCreation { + string algName; + + HmacAlgorithmObjectCreation() { + objectName = ["", "system.security.cryptography."] + algName and + isHmacAlgorithm(algName) + } + + override string getName() { result = algName } +} + +class HmacAlgorithmCreateCall extends HmacAlgorithm, DataFlow::CallNode { + string algName; + + HmacAlgorithmCreateCall() { + isHmacAlgorithm(algName) and + this = + API::getTopLevelMember("system") + .getMember("security") + .getMember("cryptography") + .getMember(algName) + .getMember(["create", "new"]) + .asCall() + + } + + override string getName() { result = algName } +} + +class HmacAlgorithmCreateFromNameCall extends HmacAlgorithm, CryptoAlgorithmCreateFromNameCall { + string algName; + + HmacAlgorithmCreateFromNameCall() { + objectName = ["", "system.security.cryptography."] + algName and + isHmacAlgorithm(algName) + } + + override string getName() { result = algName } +} + class CipherBlockModeEnum extends BlockMode { string modeName; diff --git a/powershell/ql/src/queries/security/cwe-327/WeakHmac.qhelp b/powershell/ql/src/queries/security/cwe-327/WeakHmac.qhelp new file mode 100644 index 000000000000..3cfae573f25b --- /dev/null +++ b/powershell/ql/src/queries/security/cwe-327/WeakHmac.qhelp @@ -0,0 +1,24 @@ + + + +

+ HMAC (Hash-based Message Authentication Code) algorithms are used to verify both the + integrity and authenticity of messages. Using weak HMAC algorithms such as HMACMD5, + HMACSHA1, or HMACRIPEMD160 can compromise message authentication, as the underlying + hash functions have known cryptographic weaknesses. +

+
+ +

+ Use a strong HMAC algorithm such as HMACSHA256, HMACSHA384, or HMACSHA512. These are + based on the SHA-2 family of hash functions and provide adequate security for message + authentication. +

+
+ + +
  • NIST, SP 800-131A: Transitioning the Use of Cryptographic Algorithms and Key Lengths.
  • +
  • CWE-327: Use of a Broken or Risky Cryptographic Algorithm.
  • +
  • CWE-328: Use of Weak Hash.
  • +
    +
    diff --git a/powershell/ql/src/queries/security/cwe-327/WeakHmac.ql b/powershell/ql/src/queries/security/cwe-327/WeakHmac.ql new file mode 100644 index 000000000000..ca97d69da7d9 --- /dev/null +++ b/powershell/ql/src/queries/security/cwe-327/WeakHmac.ql @@ -0,0 +1,21 @@ +/** + * @name Use of weak HMAC algorithm + * @description Using weak HMAC algorithms like HMACMD5 or HMACSHA1 can compromise message authentication. + * @kind problem + * @problem.severity warning + * @security-severity 7.5 + * @precision high + * @id powershell/weak-hmac + * @tags security + * external/cwe/cwe-327 + * external/cwe/cwe-328 + */ + +import powershell +import semmle.code.powershell.ApiGraphs +import semmle.code.powershell.dataflow.DataFlow +import semmle.code.powershell.security.cryptography.Concepts + +from HmacAlgorithm hmacAlg +where not hmacAlg.getHmacName() = ["hmacsha256", "hmacsha384", "hmacsha512"] +select hmacAlg, "Use of weak HMAC algorithm: " + hmacAlg.getHmacName() + ". Use HMACSHA256 or stronger." diff --git a/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/WeakHmac.expected b/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/WeakHmac.expected new file mode 100644 index 000000000000..a96f5b0fee52 --- /dev/null +++ b/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/WeakHmac.expected @@ -0,0 +1,4 @@ +| test.ps1:6:9:6:55 | Call to new-object | Use of weak HMAC algorithm: hmacmd5. Use HMACSHA256 or stronger. | +| test.ps1:9:9:9:56 | Call to new-object | Use of weak HMAC algorithm: hmacsha1. Use HMACSHA256 or stronger. | +| test.ps1:12:9:12:56 | Call to create | Use of weak HMAC algorithm: hmacmd5. Use HMACSHA256 or stronger. | +| test.ps1:15:9:15:54 | Call to new | Use of weak HMAC algorithm: hmacsha1. Use HMACSHA256 or stronger. | diff --git a/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/WeakHmac.qlref b/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/WeakHmac.qlref new file mode 100644 index 000000000000..f6476ddc9c32 --- /dev/null +++ b/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/WeakHmac.qlref @@ -0,0 +1 @@ +queries/security/cwe-327/WeakHmac.ql diff --git a/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/test.ps1 b/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/test.ps1 new file mode 100644 index 000000000000..a07d3b9b05ba --- /dev/null +++ b/powershell/ql/test/query-tests/security/cwe-327/WeakHmac/test.ps1 @@ -0,0 +1,28 @@ +# =================================================================== +# ========== TRUE POSITIVES (should trigger alert) ================== +# =================================================================== + +# --- Case 1: HMACMD5 via New-Object --- +$hmac = New-Object System.Security.Cryptography.HMACMD5 # BAD + +# --- Case 2: HMACSHA1 via New-Object --- +$hmac = New-Object System.Security.Cryptography.HMACSHA1 # BAD + +# --- Case 3: HMACMD5 via static Create --- +$hmac = [System.Security.Cryptography.HMACMD5]::Create() # BAD + +# --- Case 4: HMACSHA1 via ::new() --- +$hmac = [System.Security.Cryptography.HMACSHA1]::new() # BAD + +# =================================================================== +# ========== TRUE NEGATIVES (should NOT trigger alert) ============== +# =================================================================== + +# --- Safe: HMACSHA256 --- +$hmac = New-Object System.Security.Cryptography.HMACSHA256 # GOOD + +# --- Safe: HMACSHA384 --- +$hmac = [System.Security.Cryptography.HMACSHA384]::new() # GOOD + +# --- Safe: HMACSHA512 --- +$hmac = [System.Security.Cryptography.HMACSHA512]::Create() # GOOD