PHP Tricks
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Obtén la perspectiva de un hacker sobre tus aplicaciones web, red y nube
Encuentra e informa sobre vulnerabilidades críticas y explotables con un impacto real en el negocio. Utiliza nuestras más de 20 herramientas personalizadas para mapear la superficie de ataque, encontrar problemas de seguridad que te permitan escalar privilegios y usar exploits automatizados para recopilar evidencia esencial, convirtiendo tu arduo trabajo en informes persuasivos.
Esto también es válido para las cookies de phpMyAdmin.
Cookies:
Ubicaciones:
Si se utiliza ==
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 deseas comparar que el tipo de los datos comparados sea el mismo, necesitas usar ===
.
Tablas de comparación de PHP: https://www.php.net/manual/en/types.comparisons.php
"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 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 comparando con ello. Por lo tanto, si puedes proporcionar un valor que cree 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
"X" == 0 --> True
Cualquier letra en una cadena es igual a int 0
Más info en https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
Juggling de tipos también afecta a la función in_array()
por defecto (necesitas establecer en true el tercer argumento para hacer una comparación estricta):
Si esta función se utiliza para cualquier verificación de autenticación (como verificar la contraseña) y el usuario controla un lado de la comparación, puede enviar un array vacío en lugar de una cadena como el valor de la contraseña (https://example.com/login.php/?username=admin&password[]=
) y eludir esta verificación:
El mismo error ocurre con strcasecmp()
Incluso si ===
se está utilizando, podría 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 diferente de objeto antes de comparar:
preg_match()
podría ser utilizado 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).
Sin embargo, al delimitar el inicio de la regexp preg_match()
solo verifica la primera línea de la entrada del usuario, entonces si de alguna manera puedes enviar la entrada en varias líneas, podrías ser capaz de eludir esta verificación. Ejemplo:
Para eludir esta verificación, podrías enviar el valor con nuevas líneas urlencoded (%0A
) o si puedes enviar datos JSON, envíalos en varias líneas:
Encuentra un ejemplo aquí: https://ramadistra.dev/fbctf-2019-rceservice
(Este bypass se intentó 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 bypassear la verificación. Por ejemplo, si está bloqueando un JSON, podrías enviar:
From: https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0
Truco de: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223 y https://mizu.re/post/pong
En resumen, el problema ocurre porque las funciones preg_*
en PHP se basan en la biblioteca PCRE. En PCRE, ciertas expresiones regulares se emparejan utilizando muchas llamadas recursivas, lo que consume mucho espacio en la pila. Es posible establecer un límite en la cantidad de recursiones permitidas, pero en PHP este límite por defecto es 100.000, que es más de lo que cabe en la pila.
Este hilo de Stackoverflow también fue vinculado en la publicación donde se habla más a fondo sobre este problema. Nuestra tarea ahora estaba clara:
Enviar una entrada que hiciera que la regex realizara 100_000+ recursiones, causando SIGSEGV, haciendo que la función preg_match()
devolviera false
, haciendo que la aplicación pensara que nuestra entrada no es maliciosa, lanzando la sorpresa al final de la carga útil algo como {system(<verybadcommand>)}
para obtener SSTI --> RCE --> flag :).
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 por defecto es 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):
Si PHP está redirigiendo a otra página pero no se llama a ninguna función die
o exit
después de que se establece el encabezado Location
, PHP continúa ejecutándose y agregando los datos al cuerpo:
Check:
File Inclusion/Path traversalregister_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 configurando 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 path1 se aplique a path2. Y luego path2 tomará como válidos las variables de path1 (dándole a la cookie el nombre que le corresponde en path2).
Cuando tengas los nombres de usuario de los usuarios de la máquina. Verifica la dirección: /~<USERNAME> para ver si los directorios php están activados.
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 soportados 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:
Desde este hilo de twitter puedes ver que al enviar más de 1000 parámetros GET o 1000 parámetros POST o 20 archivos, PHP no va a establecer encabezados en la respuesta.
Permitiendo el bypass, por ejemplo, de los encabezados CSP que se establecen en códigos como:
Si una página PHP está imprimiendo errores y devolviendo alguna entrada proporcionada por el usuario, el usuario puede hacer que el servidor PHP imprima de vuelta algún contenido lo suficientemente largo para que cuando intente agregar los encabezados a la respuesta, el servidor arroje un error. En el siguiente escenario, el atacante hizo que el servidor arrojara algunos errores grandes, y como puedes ver en la pantalla, cuando PHP intentó modificar la información del encabezado, no pudo (por ejemplo, el encabezado CSP no se envió al usuario):
Consulta la página:
PHP SSRFsystem("ls"); `ls`; shell_exec("ls");
Consulta esto para más funciones útiles de PHP
Para ejecutar el código en el argumento "replace" se necesita al menos una coincidencia. Esta opción de preg_replace ha sido desaprobada a partir de PHP 5.5.0.
Esta función dentro de php 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 medio de una cadena. Por ejemplo:
assert("strpos($_GET['page']),'..') === false")
--> En este caso, para obtener RCE podrías hacer:
Necesitarás romper la sintaxis del código, agregar tu payload, y luego arreglarlo de nuevo. Puedes usar operaciones lógicas como "and" o "%26%26" o "|". Ten en cuenta que "or", "||" no funciona 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"
Esta función se utiliza para ordenar un array de elementos utilizando una función específica. Para abusar de esta función:
Puedes usar también // 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 correcto.
?order=id));}//
: obtenemos un mensaje de error (Parse error: syntax error, unexpected ')' i
). Probablemente tengamos demasiados corchetes de cierre.
Si puedes subir un .htaccess, entonces puedes configurar varias cosas e incluso ejecutar código (configurando que los archivos con extensión .htaccess pueden ser ejecutados).
Se pueden encontrar diferentes shells .htaccess aquí
Si encuentras una vulnerabilidad que te permite modificar variables de entorno en PHP (y otra para subir archivos, aunque con más investigación tal vez esto se pueda eludir), podrías abusar de este comportamiento para obtener RCE.
LD_PRELOAD
: Esta variable de entorno te permite cargar bibliotecas arbitrarias al ejecutar otros binarios (aunque en este caso podría no funcionar).
PHPRC
: Instruye a PHP sobre 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 señalar a PHP hacia él. Agrega 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 runtime de PHP antes de cualquier otro código.
Sube un archivo PHP que contenga nuestro shellcode
Sube un segundo archivo, que contenga una directiva de auto_prepend_file
instruyendo al preprocesador de PHP a ejecutar el archivo que subiste en el paso 1
Establece la variable PHPRC
al archivo que subiste en el paso 2.
Obtén más información sobre cómo ejecutar esta cadena del informe original.
PHPRC - otra opción
Si no puedes subir archivos, podrías usar en FreeBSD el "archivo" /dev/fd/0
que contiene el stdin
, siendo el cuerpo de la solicitud enviada al stdin
:
curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
O para obtener RCE, habilita allow_url_include
y prepende un archivo con código PHP en base64:
curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'
Técnica de este informe.
El servidor web analiza las solicitudes HTTP y las pasa a un script PHP ejecutando una solicitud como http://host/cgi.php?foo=bar
como php.exe cgi.php foo=bar
, lo que permite una inyección de parámetros. Esto permitiría inyectar los siguientes parámetros para cargar el código PHP desde el cuerpo:
Además, es posible inyectar el parámetro "-" utilizando el carácter 0xAD debido a la normalización posterior de PHP. Consulta el ejemplo de exploit de esta publicación:
En esta publicación es posible encontrar grandes ideas para generar un código PHP de brain fuck con muy pocos caracteres permitidos. Además, también se propone una forma interesante de ejecutar funciones que les permitió eludir varias verificaciones:
Mira si puedes insertar código en las llamadas a estas funciones (de aquí):
Si estás depurando una aplicación PHP, puedes habilitar globalmente la impresión de errores en /etc/php5/apache2/php.ini
añadiendo display_errors = On
y reiniciar apache: sudo systemctl restart apache2
Puedes usar el web www.unphp.net para desofuscar código php.
Las envolturas y protocolos de PHP podrían permitirte eludir las protecciones de escritura y lectura en un sistema y comprometerlo. Para más información consulta esta página.
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
Si en una página puedes crear un nuevo objeto de una clase arbitraria podrías obtener RCE, consulta la siguiente página para aprender cómo:
PHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Según este informe es posible generar un código de shell fácil de esta manera:
Así que, si puedes ejecutar PHP arbitrario sin números y letras puedes enviar una solicitud como la siguiente abusando de esa carga útil para ejecutar PHP arbitrario:
Para una explicación más detallada, consulta https://ctf-wiki.org/web/php/php/#preg_match
Obtén la perspectiva de un hacker sobre tus aplicaciones web, red y nube
Encuentra e informa sobre vulnerabilidades críticas y explotables con un impacto real en el negocio. Utiliza nuestras más de 20 herramientas personalizadas para mapear la superficie de ataque, encontrar problemas de seguridad que te permitan escalar privilegios y usar exploits automatizados para recopilar evidencia esencial, convirtiendo tu arduo trabajo en informes persuasivos.
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)