Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,49 @@ class CipherBlockStringConstExpr extends BlockMode {
override string getName() { result = modeName }
}

class HmacAlgorithmObjectCreation extends HmacAlgorithm, CryptoAlgorithmObjectCreation {
string algName;

HmacAlgorithmObjectCreation() {
(
objectName = "system.security.cryptography." + algName or
objectName = algName
) and
isHmacAlgorithm(algName)
Comment on lines +183 to +187
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the class further below (i.e., XXX) we do this:

objectName = ["", "system.security.cryptography."] + algName and
isHmacAlgorithm(algName)

could we not do a similarly pretty thing here?

}

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;

Expand Down
24 changes: 24 additions & 0 deletions powershell/ql/src/queries/security/cwe-327/WeakHmac.qhelp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
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.
</p>
</overview>
<recommendation>
<p>
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.
</p>
</recommendation>

<references>
<li>NIST, SP 800-131A: <a href="https://csrc.nist.gov/publications/detail/sp/800-131a/rev-2/final">Transitioning the Use of Cryptographic Algorithms and Key Lengths</a>.</li>
<li>CWE-327: <a href="https://cwe.mitre.org/data/definitions/327.html">Use of a Broken or Risky Cryptographic Algorithm</a>.</li>
<li>CWE-328: <a href="https://cwe.mitre.org/data/definitions/328.html">Use of Weak Hash</a>.</li>
</references>
</qhelp>
21 changes: 21 additions & 0 deletions powershell/ql/src/queries/security/cwe-327/WeakHmac.ql
Original file line number Diff line number Diff line change
@@ -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/microsoft/security/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"]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will also raise an alert if no name can be found (i.e., getHmacName returns no results). Two questions:

  1. Can that ever happen?
  2. If so, is that what we want?

select hmacAlg, "Use of weak HMAC algorithm: " + hmacAlg.getHmacName() + ". Use HMACSHA256 or stronger."
Original file line number Diff line number Diff line change
@@ -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. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
queries/security/cwe-327/WeakHmac.ql
28 changes: 28 additions & 0 deletions powershell/ql/test/query-tests/security/cwe-327/WeakHmac/test.ps1
Original file line number Diff line number Diff line change
@@ -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
Loading