Bu güvenlik açığı tüm türler arasında en tehlikelisidir ve genelde 10 üzerinden 10 ile derecelendirilir. Bulmak zordur. Komut çalıştırma açığı aranan scriptte, komut çalıştıran bi kod parçası olması gerekir haliyle. Bu yüzden bulmak zordur, çünkü çok gerekmedikçe webmasterlar kolay kolay komut çalıştıran kodlar yazmaz. Ancak her sistemin her katmanında bu tip açıklara rastlanabilir. Biz burada web hacking'deki olayından bahsedeceğiz.
Önce "remote code execution" ve "remote command execution" farklarından bahsedeceğim.
Remote code execution demek, script üzerinden kod çalıştırma açığı demek. Bilirsiniz eval() fonksiyonu ve bu fonksiyonla aynı mantıkla çalışan veya bünyesinde bu fonksiyonu çağıran fonksiyonlar remote code execution'a sebebiyet vermektedir. Eval desteği olan her web programlama dilinde karşılaşılabilir ve o script dilinde yazacağınız kodları çalıştırabilmenize imkan sağlar. Ama "remote command execution" farklıdır. Bu açık türü ise bu tür script dilleri üzerinden işletim sistemine yapılan çağrıları kullanır. Yani script kodları değil, doğrudan cmd/shell komutları çalıştırırsınız.
Ben yazımda "remote command execution" dan bahsedeceğim. Diğeri aynı yazıya sığmayacak kadar büyük. Ve yazıda "php" dilini kullanacağım çünkü hem kullanım hem açık bakımından en yaygın olanı bu.
Önce php de sistem shell çağrısı yapan fonksiyonlara bakalım;
passthru() exec() shell_exec() proc_open() system() popen() `komut`
(` ve ` arasına yazılmış her şey shell_exec fonksiyonuna gönderilir. fonksiyondan emin değilim ama bi php açın içine komutu bu özel tırnak(backtick) içinde yazın, komut olarak çalıştırılır.)
Genel olarak bunlar sistemde komut veya herhangi bi uygulama çalıştırmaya yarayan fonksiyonlardır.
Peki bu fonksiyonları webmaster ne gibi durumlarda kullanır?
Örneğin; whois, ping, traceroute gibi komutlar, pek çok domain ve network işlemlerini kolaylaştırabilir. Dolayısıyla bu gibi formlar arka planda sizden aldığı verileri önce shell komutuna gönderip daha sonra çıktıyı size iletiyor olabilir. Bu tabi sadece bir örnek, video dönüştürme, image process, debugging vs. vs. vs. daha pek çok sebeple bu gibi sistem çağrıları kullanılıyor olabilir.
Örnek kod:
if(isset($_GET["domainname"])){ echo "Whois çıktısı:"; passthru("whois ".$_GET["domainname"]); }
bu kodda dikkat ettiyseniz bizden domainname alınıyor ve passthru() ya "whois "+domainname olarak gönderiliyor.
Whois komutunun çıktısı da haliyle sayfaya basılıyor. passthru direk çıktıyı sayfaya basar çünkü. Buraya kadar her şey yolunda gibi demi neticede adamın girdiği domainname "whois" komutuna gönderiliyor. Bişeyler yapsa bile "whois" içerisinden çıkamaz gibi düşünebilirsiniz. Peki ya özel karakterler kullanırsa?
ÖZEL KARAKTERLER
"|" (PIPE karakteri):
Bu karakter iki tane yan yana "||" konulduğunda "or" görevi görür. 1. komutta sıkıntı oluşursa 2. sini çalıştırır (herhalde öyle bişey yapıyodur. bildiğimiz or neticede).
Bu karakterden bi tane koyarsan, piping(payping) yaparsın. 1. komutun çıktısında 2. komut çalıştırılır.
Eğer "whois"i sadece senden parametre alıp çıktı üreten bir komutla pipe edersen, 2. komutun çıktısını alırsın.
Eğer birleştirecek bir komut kullanırsan, 2 komutun bileşkesini alırsın.
"&" (AND Karakteri):
2 tane koyarsanız(&&) 2 komutu da çalıştırır.
Bi tane koyarsanız değişik bişeyler yapıyor(Aslında
konsolda ilk komutu arka plana atar, orada çalıştırır). Ama and
karakteri filtreli değilse niye bi tane koyayım ki zaten, 2 tane koyar
keyfime bakarım.
- url 'den gönderilen & karakteri %26 ile urlencode edilmezse web server tarafından parametre ayracı olarak algılanır.
- Çıktıda önce ilk komut, sonra && 'den sonraki komut görünür.
" ` " (Backtick Karakterleri):
Bu karakter arasına yazılanlar da komut olarak çalıştırılır ve çıktısı olduğu gibi yazıldığı konuma yansır.
Örnek kullanım:
Burada `echo google.com` çıktısı "google.com" dur. Dolayısıyla "whois google.com" yapmış olduk. Bu karakter ile yapacağınız "rce" saldırılarında her zaman çıktı alamazsınız. Bu gibi durumlarda yaratıcılığınızı kullanın. Neticede kod çalışıyor. Örneğin wget ile kendi web adresinize istek göndertip gelen istekleri yakalatabilirsiniz(sniffer mantığı). Veya direk wget ile şelinizi sunucuya çekersiniz.
" $() " kombosu (shell değişken tanımlama):
Linux kullanan pek çoğunuz bi gün "apt-get install linux-headers-$(uname -r)" komutuna ihtiyaç duymuştur. Bu komutta kullanılan $(uname -r) kısmı bizim kernel versionumuzu basacaktır.
Burada bize "3.18.0-kali3-amd64" döndürmüş oldu. Dolayısıyla $() içine ne yazarsak onun çıktısını döndürür. Anlık değişken kullanmış oluruz. Çıktıyı bunda da her zaman görmemiz mümkün olmayabilir. Ama wget mevzusunu burada da uygulayabiliriz. Neticede komutumuz çalışacak.
" ; " Karakteri (noktalı virgül):
Bu da && görevi görür:
Yine en altta "ls -la" çıktısı görünmekte.
" > " (echo karakteri):
Bildiğiniz gibi hem windows hem unixte bu karakter çıktıyı dosyaya yazar.
Örnek "echo asd > asd.txt" yazarsanız "asd.txt" oluşturup içine "echo asd" çıktısını yazar. Dolayısıyla "asd" yazmış olur. Biz de haliyle şelde takıldığımıza göre, "whois google.com > asd.php" yazarsak "whois google.com" çıktısını "asd.php" ye yazmış oluruz. Çıktısına müdahale edebileceğimiz bir komutta ">" karakteri ile dosyaya yazabilirsek sunucuda "php" dosya oluşturarak kod çalıştırabiliriz.
Sonuç:
Bunlar gibi belki benim de bilmediğim veya aklıma gelmeyen daha pek çok müdahale yöntemi var. Burada önemli olan, önce hangi karakterler filtreli onları tespit edip, bunları kullanmadan komuta müdahale etmenin imkanı varmı onu bulmak. He unutmadan şuna da değineyim, shellshock saldırı komutları da bu gibi komut üzerinden çalıştığından şüphelenilen scriptlerde denenebilir.Burada ben yazımı unix ağırlıklı yazdım ama bu yöntemlerin neredeyse hepsi windows'ta da işe yaramaktadır. Çoğunun kullanımı orada da aynıdır.
Önce çalışan komutu yorumlamak gerekir. Neticede adam komuta parametreyi " " (çift tırnak işaretleri) arasında da alabilir. Bu gibi durumda yazdıklarımız String olarak algılanacaktır. Dolayısıyla biz önce " kullanarak String bloğundan dışarı çıkmalıyız. Aynı şey ' ' (tek tırnak işaretleri) için de geçerli. Bunları kullanıp da parametreyi alırken "escape" etmemişse yine her türlü bi yolunu bulup komut çalıştırabilirsiniz. O yüzden shell'de kullandığınızda özel karakter olarak algılanan ne kadar karakter varsa kullanmanızı ve bu sayede hata almaya çalışmanızı tavsiye ederim.
Hatalar direk basılmasa bile, iç sunucu hataları alarak da denemeler yapabilirsiniz. Ayrıca bazı örneklerde gördüğünüz gibi RCE her zaman görsel olarak çıktı alma imkanı tanımaz. Bazen de Blind RCE yapmanız gerekebilir.
Yorum Gönder