The Magic Informer
A web challenge ranked easy in the HTB university CTF
Challenge description:
I started doing web things about a month ago so i am still a begginner but i easily flagged this one and did a big part of the medium one so i am still happy about my performance.
Initial recon
We perform a pentest in a black box environment and have access to a website probably built in nodejs (Wappalyzer).
website root:
Uppon clicking on the bottom right button “WE ARE HIRING” we are prompted to a register page (/register)
- We can’t create an account with username
admin
because it does already exist. - Creating an account redirect us to /login.
- Logging in redirect us to /dashboard
dashboard page:
- On the dashboard we can find a form to apply to be an editor, but it doesnt seems to be vulnerable to SQLi
- We also have the ability to upload a resume, it gets rename to a “random” name and has the extension .docx
- The download resume feature is vulnerable to a directory traversal attack.
Directory traversal via resume
The url to download your resume will look like this:
http://134.209.22.69:32474/download?resume=788b6eafb766a230c8bef6b741cc2d90.docx
Changing the resume
query parameter allow us to read any file on the server.
It tries to protect against directory traversal by removing any ../
in finds in the resume parameter but we can bypass this using a common ....//
payload (shrinked to ../
by the server)
Example:
http://134.209.22.69:32474/download?resume=....//....//etc/passwd
Getting index.js with resume=....//index.js
, we learn the existence of a 2 new files, database.js
, debug.env
In index.js
we obtain the port number the application binded itself to: 1337
In debug.env
we obtain the following DEBUG_PASS: CzliwZJkV60hpPJ
(which will be used later on)
Auth bypass via flawed jwt
The website is using jwt token for it’s authentication process, the signature of the token is not checked by the server and thus, we can craft arbitrary tokens.
Here we can just change "username": "avan",
to "username": "admin",
in Payload, paste the new token (wich has an erroneous signature) into our session cookie and here goes the admin account.
Using token.dev
admin account dashboard
Admin dashboard recon
The admin account has access to more functionnality compared to a regular user:
- An “SMS Gateway” which by default contact an external api to send sms (SSRF redflagged)
- An “SQL Prompt” which require a debug password (we got it earlier) but whitelisted to localhost (we didnt even bother trying to bypass the localhost directly because we had an SSRF)
SMS gateway menu:
SQL Prompt menu
SSRF to SQLi
We had a complete control over the request parameter in the SMS Gateway
menu thus, we opened burp to intercept the request made to the backend and modify it with more ease.
Here’s how the sms request looks like (POST /api/sms/test) (need the admin session cookie obviously)
And here’s the sql request (POST /debug/sql/exec) (admin cookie blablabla…)
Now we need to build our exploit to make a request to /debug/sql/exec via the SSRF
Here how the SMS request looks like now
The server gladly request the /debug/sql/exec which execute our SQL payload and we back who created an account on their platform.
SSRF to SQLi to RCE
We did recon the database but didn’t find anything useful, only to realize some minutes later the presence of a command injection vulnerability. So it’s more like SSRF to RCE right now
SSRF to RCE
Using revshells.com we craft an mkfifo reverse shell and put it inside the SQL query
Final payload
Listening on port 4444 on my public IP we get back a shell and we can retreive the flag !
HTB{br0k3n_4u7h_55RF_4s_4_s3rv1c3_d3bug_ftw}
ps: ty to Camille (Royal) and Arthur (Pasteque)