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
Admin
privileges 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 solution
when 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_id
was1
Looking into the sources
I looked into the source and found two interesting js files.
/static/js/toggle.js
:
|
|
/toggle
endpoint
/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
id
which was1
for 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
jwt
payload’suser_id
parameter from1
to12
- 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 got49
on 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 Verified
which 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!