Skip to content

Commit e6c9067

Browse files
authored
Merge pull request github#7740 from erik-krogh/CWE-347
JS: promote the js/jwt-missing-verification query out of experimental
2 parents f7a0b17 + 8dcec2e commit e6c9067

File tree

9 files changed

+78
-45
lines changed

9 files changed

+78
-45
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> <qhelp>
2+
3+
<overview>
4+
<p>
5+
Applications decoding JSON Web Tokens (JWT) may be misconfigured due to the <code>None</code> algorithm.
6+
</p>
7+
<p>
8+
The <code>None</code> algorithm is selected by calling the <code>verify()</code> function with a falsy value
9+
instead of a cryptographic secret or key. The <code>None</code> algorithm disables the integrity enforcement of
10+
a JWT payload and may allow a malicious actor to make unintended changes to a JWT payload leading
11+
to critical security issues like privilege escalation.
12+
</p>
13+
14+
</overview>
15+
16+
<recommendation>
17+
<p>
18+
Calls to <code>verify()</code> functions should use a cryptographic secret or key to decode JWT payloads.
19+
</p>
20+
</recommendation>
21+
22+
<example>
23+
<p>
24+
In the example below, <code>false</code> is used to disable the integrity enforcement of a JWT payload.
25+
This may allow a malicious actor to make changes to a JWT payload.
26+
</p>
27+
28+
<sample src="examples/missing-key-verification-bad.js" />
29+
30+
<p>
31+
The following code fixes the problem by using a cryptographic secret or key to decode JWT payloads.
32+
</p>
33+
34+
<sample src="examples/missing-key-verification-good.js" />
35+
36+
</example>
37+
38+
<references>
39+
<li>Auth0 Blog: <a href="https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/#Meet-the--None--Algorithm">Meet the "None" Algorithm</a>.</li>
40+
41+
</references>
42+
</qhelp>
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@
1010
*/
1111

1212
import javascript
13-
import DataFlow
1413
import semmle.javascript.RestrictedLocations
1514

16-
from CallNode call
15+
from DataFlow::CallNode call
1716
where
18-
call = moduleMember("jsonwebtoken", "verify").getACall() and
19-
unique(boolean b | b = call.getArgument(1).analyze().getABooleanValue()) = false
20-
select call.asExpr().(FirstLineOf),
21-
"does not verify the JWT payload with a cryptographic secret or public key."
17+
call = DataFlow::moduleMember("jsonwebtoken", "verify").getACall() and
18+
call.getArgument(1).analyze().getTheBooleanValue() = false
19+
select call.getArgument(1),
20+
"This argument disables the integrity enforcement of the token verification."
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const jwt = require("jsonwebtoken");
2+
3+
const secret = "my-secret-key";
4+
5+
var token = jwt.sign({ foo: 'bar' }, secret, { algorithm: "none" })
6+
jwt.verify(token, false, { algorithms: ["HS256", "none"] })
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
const jwt = require("jsonwebtoken");
3+
4+
const secret = "my-secret-key";
5+
6+
var token = jwt.sign({ foo: 'bar' }, secret, { algorithm: "HS256" })
7+
jwt.verify(token, secret, { algorithms: ["HS256", "none"] })
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: newQuery
3+
---
4+
* A new query `js/jwt-missing-verification` has been added. The query detects applications that don't verify JWT tokens.

javascript/ql/src/experimental/Security/CWE-347/JWTMissingSecretOrPublicKeyVerification.help

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| bad-jwt.js:10:19:10:20 | "" | This argument disables the integrity enforcement of the token verification. |
2+
| bad-jwt.js:11:19:11:27 | undefined | This argument disables the integrity enforcement of the token verification. |
3+
| bad-jwt.js:12:19:12:23 | false | This argument disables the integrity enforcement of the token verification. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE-347/MissingJWTKeyVerification.ql
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
const jwt = require("jsonwebtoken");
22

3-
const secret = "buybtc";
4-
// #1
5-
var token = jwt.sign({ foo: 'bar' }, secret, { algorithm: "HS256" }) // alg:HS256
6-
jwt.verify(token, secret, { algorithms: ["HS256", "none"] }) // pass
7-
// #2
8-
var token = jwt.sign({ foo: 'bar' }, secret, { algorithm: "none" }) // alg:none (unsafe)
9-
jwt.verify(token, "", { algorithms: ["HS256", "none"] }) // detected
10-
jwt.verify(token, undefined, { algorithms: ["HS256", "none"] }) // detected
11-
jwt.verify(token, false, { algorithms: ["HS256", "none"] }) // detected
3+
const secret = "my-secret-key";
4+
5+
var token = jwt.sign({ foo: 'bar' }, secret, { algorithm: "HS256" })
6+
jwt.verify(token, secret, { algorithms: ["HS256", "none"] }) // OK
7+
8+
9+
var token = jwt.sign({ foo: 'bar' }, secret, { algorithm: "none" })
10+
jwt.verify(token, "", { algorithms: ["HS256", "none"] }) // NOT OK
11+
jwt.verify(token, undefined, { algorithms: ["HS256", "none"] }) // NOT OK
12+
jwt.verify(token, false, { algorithms: ["HS256", "none"] }) // NOT OK

0 commit comments

Comments
 (0)