|
5 | 5 | * @kind problem |
6 | 6 | * @problem.severity error |
7 | 7 | * @security-severity 9.8 |
8 | | - * @precision medium |
9 | | - * @id powershell/microsoft/security/jwt-none-algorithm |
| 8 | + * @precision high |
| 9 | + * @id powershell/jwt-none-algorithm |
10 | 10 | * @tags security |
11 | 11 | * external/cwe/cwe-347 |
12 | 12 | */ |
13 | 13 |
|
14 | 14 | import powershell |
15 | 15 | import semmle.code.powershell.dataflow.DataFlow |
16 | 16 |
|
17 | | -// NOTE: PowerShell is a beta language for CodeQL and has no built-in JWT library modeling. |
18 | | -// This query detects common patterns of JWT "none" algorithm usage in PowerShell modules |
19 | | -// such as PSJwt, JWTPS, and direct .NET JWT library calls. |
20 | | -// Coverage may be limited for less common JWT libraries. |
21 | | - |
22 | | -/** |
23 | | - * A string literal containing "none" used in a JWT-related cmdlet call. |
24 | | - */ |
25 | | -class JwtNoneAlgorithmLiteral extends StringConstExpr { |
26 | | - JwtNoneAlgorithmLiteral() { |
27 | | - this.getValueString().toLowerCase() = "none" and |
28 | | - exists(CmdCall call | |
29 | | - call.matchesName([ |
30 | | - "New-Jwt", "New-JsonWebToken", "ConvertTo-Jwt", |
31 | | - "New-JWTToken", "ConvertTo-JWTToken" |
32 | | - ]) and |
33 | | - this = call.getAnArgument() |
34 | | - ) |
35 | | - } |
36 | | -} |
37 | | - |
38 | 17 | /** |
39 | | - * A string literal "none" passed as an algorithm argument to .NET JWT methods. |
| 18 | + * A string literal "none" passed as an algorithm argument to .NET JWT methods |
| 19 | + * on a JwtSecurityTokenHandler instance. |
40 | 20 | */ |
41 | 21 | class JwtNoneInDotNetCall extends StringConstExpr { |
42 | 22 | JwtNoneInDotNetCall() { |
43 | 23 | this.getValueString().toLowerCase() = "none" and |
44 | | - exists(InvokeMemberExpr call | |
45 | | - call.matchesName([ |
46 | | - "CreateToken", "WriteToken", "CreateJwtSecurityToken", "CreateEncodedJwt" |
47 | | - ]) and |
48 | | - this = call.getAnArgument() |
| 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 |
49 | 31 | ) |
50 | 32 | } |
51 | 33 | } |
52 | 34 |
|
53 | | -from StringConstExpr noneAlg, string msg |
54 | | -where |
55 | | - ( |
56 | | - noneAlg instanceof JwtNoneAlgorithmLiteral and |
57 | | - msg = "JWT token created with 'none' algorithm, disabling signature verification." |
58 | | - ) |
59 | | - or |
60 | | - ( |
61 | | - noneAlg instanceof JwtNoneInDotNetCall and |
62 | | - msg = |
63 | | - "JWT token created with 'none' algorithm via .NET API, disabling signature verification." |
64 | | - ) |
65 | | -select noneAlg, msg |
| 35 | +from JwtNoneInDotNetCall noneAlg |
| 36 | +select noneAlg, |
| 37 | + "JWT token created with 'none' algorithm via .NET API, disabling signature verification." |
0 commit comments