Skip to content

Commit 54da53b

Browse files
authored
Merge pull request #345 from microsoft/users/chanely/jwt-none-algorithm
JWT token created with none algorithm
2 parents 9a9e8ad + d3c338e commit 54da53b

7 files changed

Lines changed: 110 additions & 0 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
7+
<p>Using the <code>"none"</code> algorithm when creating a JWT token with
8+
<code>JwtSecurityTokenHandler</code> disables signature verification. This allows attackers to
9+
forge arbitrary tokens that will be accepted as valid, potentially leading to authentication
10+
bypass and privilege escalation.</p>
11+
12+
</overview>
13+
<recommendation>
14+
15+
<p>Always use a secure signing algorithm such as <code>HS256</code>, <code>RS256</code>, or
16+
<code>ES256</code> when creating JWT tokens. Ensure that tokens are signed with a strong secret
17+
or key pair.</p>
18+
19+
</recommendation>
20+
<example>
21+
22+
<p>In this example, a JWT token is created using the <code>"none"</code> algorithm, which produces
23+
an unsigned token:</p>
24+
25+
<sample src="examples/JwtNoneAlgorithmBad.ps1" />
26+
27+
<p>The fix is to use a secure algorithm instead:</p>
28+
29+
<sample src="examples/JwtNoneAlgorithmGood.ps1" />
30+
31+
</example>
32+
<references>
33+
34+
<li>
35+
RFC 7518:
36+
<a href="https://datatracker.ietf.org/doc/html/rfc7518#section-3.6">JSON Web Algorithms - Unsecured JWS</a>.
37+
</li>
38+
39+
<li>
40+
CWE-347:
41+
<a href="https://cwe.mitre.org/data/definitions/347.html">Improper Verification of Cryptographic Signature</a>.
42+
</li>
43+
44+
</references>
45+
</qhelp>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* @name JWT none algorithm usage
3+
* @description Using the "none" algorithm for JWT tokens disables signature verification,
4+
* allowing token forgery.
5+
* @kind problem
6+
* @problem.severity error
7+
* @security-severity 9.8
8+
* @precision high
9+
* @id powershell/jwt-none-algorithm
10+
* @tags security
11+
* external/cwe/cwe-347
12+
*/
13+
14+
import powershell
15+
import semmle.code.powershell.dataflow.DataFlow
16+
17+
/**
18+
* A string literal "none" passed as an algorithm argument to .NET JWT methods
19+
* on a JwtSecurityTokenHandler instance.
20+
*/
21+
class JwtNoneInDotNetCall extends StringConstExpr {
22+
JwtNoneInDotNetCall() {
23+
this.getValueString().toLowerCase() = "none" and
24+
exists(DataFlow::CallNode cn, DataFlow::ObjectCreationNode ocn |
25+
cn.getQualifier().getALocalSource() = ocn and
26+
ocn.getConstructedTypeNode().asExpr().getExpr().(TypeNameExpr).hasQualifiedName("system.identitymodel.tokens.jwt", "jwtsecuritytokenhandler") and
27+
cn.getLowerCaseName() in [
28+
"createtoken", "writetoken", "createjwtsecuritytoken", "createencodedjwt"
29+
] and
30+
cn.getAnArgument().asExpr().getExpr() = this
31+
)
32+
}
33+
}
34+
35+
from JwtNoneInDotNetCall noneAlg
36+
select noneAlg,
37+
"JWT token created with 'none' algorithm via .NET API, disabling signature verification."
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
$handler = [System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler]::new()
2+
3+
# BAD: Creating a JWT token with the "none" algorithm disables signature verification.
4+
$token = $handler.CreateToken("none")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
$handler = [System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler]::new()
2+
3+
# GOOD: Creating a JWT token with a secure algorithm.
4+
$token = $handler.CreateToken("HS256")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.ps1:7:31:7:36 | none | JWT token created with 'none' algorithm via .NET API, disabling signature verification. |
2+
| test.ps1:10:36:10:41 | none | JWT token created with 'none' algorithm via .NET API, disabling signature verification. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
queries/security/cwe-347/JwtNoneAlgorithm.ql
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ===================================================================
2+
# ========== TRUE POSITIVES (should trigger alert) ==================
3+
# ===================================================================
4+
5+
# --- Case 1: .NET JwtSecurityTokenHandler.CreateToken with "none" ---
6+
$handler = [System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler]::new()
7+
$token = $handler.CreateToken("none") # BAD
8+
9+
# --- Case 2: .NET JwtSecurityTokenHandler.CreateEncodedJwt with "none" ---
10+
$token = $handler.CreateEncodedJwt("none") # BAD
11+
12+
# ===================================================================
13+
# ========== TRUE NEGATIVES (should NOT trigger alert) ==============
14+
# ===================================================================
15+
16+
# --- Safe: .NET CreateToken with HS256 ---
17+
$token = $handler.CreateToken("HS256") # GOOD

0 commit comments

Comments
 (0)