1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
import jwt from "jsonwebtoken";
import { expect, describe, it } from "bun:test";
import crypto from "crypto";
describe("when verifying a malicious token", function () {
// attacker has access to the public rsa key, but crafts the token as HS256
// with kid set to the id of the rsa key, instead of the id of the hmac secret.
// const maliciousToken = jwt.sign(
// {foo: 'bar'},
// pubRsaKey,
// {algorithm: 'HS256', keyid: 'rsaKeyId'}
// );
// consumer accepts self signed tokens (HS256) and third party tokens (RS256)
const options = { algorithms: ["RS256", "HS256"] };
const { publicKey: pubRsaKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048 });
it("should not allow HMAC verification with an RSA key in KeyObject format", function () {
const maliciousToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJzYUtleUlkIn0.eyJmb28iOiJiYXIiLCJpYXQiOjE2NTk1MTA2MDh9.cOcHI1TXPbxTMlyVTfjArSWskrmezbrG8iR7uJHwtrQ";
expect(() => jwt.verify(maliciousToken, pubRsaKey, options)).toThrow("must be a symmetric key");
});
it("should not allow HMAC verification with an RSA key in PEM format", function () {
const maliciousToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJzYUtleUlkIn0.eyJmb28iOiJiYXIiLCJpYXQiOjE2NTk1MTA2MDh9.cOcHI1TXPbxTMlyVTfjArSWskrmezbrG8iR7uJHwtrQ";
expect(() => jwt.verify(maliciousToken, pubRsaKey.export({ type: "spki", format: "pem" }), options)).toThrow(
"must be a symmetric key",
);
});
it("should not allow arbitrary execution from malicious Buffers containing objects with overridden toString functions", function () {
const token = jwt.sign({ "foo": "bar" }, "secret");
const maliciousBuffer = {
toString: () => {
throw new Error("Arbitrary Code Execution");
},
};
expect(() => jwt.verify(token, maliciousBuffer)).toThrow("not valid key material");
});
});
|