writeup mesanet portal
weekly challenge: 08/02/26 - 15/02/26
- 🔴 difficulty: hard
- ⚡ xp earned: 100
- 📂 categories:
api - 🛠️ vulns:
type confusion, improper error handling, sqlite injection
0x00: recon
- as always, we have a express web application and we start with those credentials:
operator:operator
- all my web applications approaches basically consists in act like a normal user and then see the all the requests made by these actions. there is 3 main endpoints:
/apps/mail,/apps/nexusand/dev. on the first two, all requests are parsed from what apppears to be an internal api and on the last endpoint, a token that resets every minute is required. ok, lets analyze the internal api.
- as we can see, there exists 3 fields on this json:
id,endpointanddata. the endpoints used by the application are:/api/notes/list,/api/notes/get(recieve anidondatafield),/api/mail/inboxand/api/mail/get(recieve anidondatafield)
0x01: fuzzing
- after understanding how the requests are made, we can tamper them to trigger errors and make the application show us the path. to start, we can send the
POSTrequest with all fieldsnull, all fieldstrueorfalse, withoutContent-Type, invalid json's, some fieldstrueorfalse, etc. (use your creativity). - when we send the request with
"id":true, we recieve an interesting error:
"Rail endpoint not found". what that means? making a request to /api/rails, the same error persists, so, we can fuzz endpoints. after discoverr /api/rails/create, the application tell us the fields that they want and how they want.
- after providing the required fileds, we can try to tamper them and see how the application reacts. putting a simple quote on
messagefield, we trigger a500 Internal Server Error, what probably indicates a sql injection.
"message":"' || (SELECT group_concat(name) FROM sqlite_master WHERE type='table') || '"
"' || (SELECT group_concat(key || ':' || value) FROM config) || '"
- after get the credentials, we need to find where to put them. with another fuzzing, we discover the
/dbendpoint, that allow us to generate database backups
- with another fuzzing, we can guess two valid databases: railDb and
portalDb. atportalDb, we can retrieve the otp password for/devand get the flag. downloading the database:➜ ~ curl -X POST https://lab-1770738092145-8zzgln.labs-app.bugforge.io/db/backup -d '{"database":"portalDb"}' -H "Cookie: connect.sid=s%3ARTl8Kk45vICrVx7t8ZUKOJnqZ13b1Jcp.2NQiVBoHxUM1kMbAlF%2Bye%2BFsz1i2WBArYfcKLtjibw0" -H "Content-Type: application/json" -o bkp % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 20503 100 20480 100 23 18471 20 0:00:01 0:00:01 --:--:-- 18504 ➜ ~ sqlite3 bkp SQLite version 3.46.1 2024-08-13 09:16:08 Enter ".help" for usage hints. sqlite> .tables config users sqlite> select * from config; dev_otp|791006|1770743075 - getting the flag!
