TryHackMe – Madness Makinesinin Çözümü

TryHackMe – Madness Makinesinin Çözümü

Herkese merhaba, ben Anıl Çelik. Bugünkü yazımda sizlerle TryHackMe platforumda bulunan Madness isimli makinenin çözümünü paylaşacağım.

  • Öncelikle, nmap taramasıyla başlayalım:
  • Nmap sonucunda gördüğümüz gibi, hedef makine üzerinde sadece SSH ve HTTP portları açık. SSH üzerinde pek bir şey yapamayacağımız için, web servisini incelemeye başlayalım:
  • İlk bakışta, karşımıza Apache2’nin default sayfası açıldı, fakat burada dikkatimizi çeken bir şey var:
  • Buradan görebileceğimiz gibi, arka tarafta yüklenirken hata veren bir resim dosyası olabilir. Kaynak kodları inceleyelim:
  • Şüphemiz haksız çıkmadı, gerçekten bir resim dosyası var. Önce resmin bulunduğu dizine gidelim:
  • Gördüğümüz gibi dosya açılırken hata meydana geliyor. Resim dosyasını incelemeye başlamadan önce, bir gobuster taraması yapıp web servisinde bulunan dizinleri kontrol edelim:
  • Gobuster’dan bir şey elde edemedik. Şimdi resmi incelemeye başlayabiliriz, öncelikle wget ile dosyayı indirelim:
  • İncelemeye başlayalım:
  • Dosyayı exiftool ile incelediğimizde, dosya uzantısının “.jpg” olduğunu fakat dosyanın sahip olduğu header nedeniyle File Type kısmında PNG olduğunu görüyoruz. Dosyanın header’ını düzeltmek için hexeditor’de açmayı deneyelim:
  • Gördüğümüz gibi, header bilgisindeki byte yerleşiminden dolayı dosya PNG formatında görünüyor. Bunu “.jpg” uzantısı ile uyumlu hale getirmek için Google’da arama yaptığımda, SANS üzerinde şöyle bir bilgiyle karşılaşıyoruz:
  • Dosya header düzenini burada belirtildiği gibi “FF D8 FF E0” şeklinde düzelttim fakat ASCII formatında JFIF karşılığını elde edemedim, sonrasında tekrar aradığımda şu bilgiye ulaştım:
  • “FF D8 FF E0” sonrasına “00 10 4A 46” bilgilerini de eklediğimde, istediğimi elde ettim:
  • Şimdi ise dosyayı kaydedip içeriğini görüntülemeye çalışalım:
  • Gizli bir dizinle karşılaştık. Dizine gitmeye çalışalım:
  • Dizine gittiğimizde, kimlik bilgilerine erişebilmek için, secret adında yani gizli bilgiyi tahmin etmemiz gerektiğini söyleyen bir sayfayla karşılaşıyoruz. Secret’ın ne olabileceğine dair sayfanın kaynağına baktığımızda:
  • Secret değerinin 0 ile 99 arasında olduğunu görebiliriz. Bunun için dizin sonuna “?secret=” parametresini ekleyip manuel olarak 0’dan 99’a kadar gidebiliriz. Ancak bu bize çok fazla vakit kaybettireceği için, burada bizim yerimize 0’dan 99’a kadar istekleri otomatik olarak gönderip sonuca ulaşıp ulaşamayacağımıza bakabiliriz. Script’e geçmeden önce, “?secret=” parametresine random bir değer verdiğimizde nasıl bir sonuçla karşılaştığımıza bakalım:
  • Secret değerine “2” değerini verdiğimde, “That is wrong! Get outta here!” şeklinde bir hata mesajıyla karşılaştım. Buradan anlayabileceğimiz şey, yazacağımız script içerisinde yollanan request’e dönen response içerisinde bu mesajın olup olmadığını kontrol edebilirsek, istediğimiz sonuca ulaşabiliriz. Öncelikle python içerisinde HTTP GET Requestlerin nasıl yapıldığına bir bakalım:
  • Bir get request yapmadan önce, requests modülünü dosyaya eklememiz gerektiğini görüyoruz. Sonrasında, URL ve PARAMS değerlerini, yani adres ve içerisinde gidecek parametre değerlerini de ayarladıktan sonra, “r = requests.get(url = URL, params = PARAMS)” şeklinde isteğimizi gönderebileceğimizi görüyoruz.
  • “r = requests.get(url = URL, params = PARAMS)” kısmında birkaç hata aldıktan sonra, params değerini nasıl gönderebileceğime dair şöyle bir şey buldum:
  • Göndermemiz gereken params değerini {param:value} şeklinde olması gerektiğini görüyoruz. Daha fazla uzatmadan scripte geçelim:
  • Burada en baştan görebileceğimiz gibi, önce “#!/usr/bin/python3” şeklinde “#!” (shebang) karakterleri sonrasında “/usr/bin/python3” yazarak dosyayı çalıştırırken sonuna “.py” uzantısını eklemekten kurtulmuş oluyoruz.
  • Sonrasında “requests” modülünü script’e import ettikten sonra, isteğimizi gerçekleştireceğimiz URL’i ekliyoruz.
  • for döngüsü içerisinde i değişkeniyle range(100) kontrolünde i’yi 100’e kadar kontrol ederek toplamda kontrol etmemiz gereken 100 tane secret değerinin kontrolünü otomatik olarak gerçekleştiriyoruz.
  • Bir sonraki “r = requests.get(URL, params = {“secret”:i}) kısmında request objemizi oluşturup, aşağıdaki if kontrolünde de “That is wrong! Get outta here!” mesajını almayacağımız bir response’un kontrolünü sağlıyoruz. Burada mesaj öncesinde gelen “b” ekini koymadığımızda, şöyle bir  hata alıyoruz:
  • Burada kontrolü string şeklinde değil, “bytes-like object” türünde sağlamamız gerektiğini görüyoruz. Biraz araştırmadan sonra “b” eklememiz gerektiğini görebiliriz:
  • Script’i çalıştıralım:
  • Gördüğümüz gibi, içerisinde “That is wrong! Get outta here!” mesajı yer alan responselarda hata mesajı alıyoruz. Fakat doğru “i” değerini bulduğumuzda:
  • Şekildeki gibi “True secret is: 73” mesajını alıyoruz. Vakit kaybetmeyip hemen ilgili secret dizinine gidelim:
  • Gizli dizinde bir parola ile karşılaştık. Bu parolayla ne yapabileceğime dair biraz enumeration yaptıktan sonra, en başta ulaştığımız resim içerisinden gizli bilgi çıkarırken kullanabileceğimi buluyorum:
  • “hidden.txt” içerisine göz atalım:
  • Bir username’e ulaştık. Burada biraz takıldıktan sonra, ne yapacağımı araştırırken en son sayfa üzerinde verilen fotoğrafın içini incelemeye çalıştım:
  • Nihayet bir parola elde ettikten sonra, SSH oturumu elde etmeye çalışalım:
  • (EDEMEDİ). Bu aşamada biraz uğraşıp hem ulaştığım username hem de password için ikisinden birinin veya ikisinin de encrypted olup olmadığını kontrol ederken, username’in ROT13 formatında encrypted bir data olduğunu buldum. Decrypt ettiğimde ise gerçek kullanıcı adına ulaştım:
  • Nihayet SSH oturumu elde edebildik:
  • User flag’i alalım:
  • “sudo -l” ile içerisinde bulunduğumuz kullanıcının sudo yetkilerini kontrol edelim:
  • Görünene göre kullanıcı sudo yetkisiyle herhangi bir komut çalıştıramıyor. Burdan sonra daha fazla vakit kaybetmeden linPEAS scriptini makineye atıp yetkilerimi yükseltmek için bir tarama yapacağım:
  • “linPEAS.sh” dosyasına çalıştırma izni verip dosyayı çalıştıralım:
  • linPEAS çıktısında sarı arkaplanlı kırmızı fontta yazılmış sonuçların %99 ihtimalle privilege escalation vector olduğuna dair bilgiyi script’i çalıştırdığınızda görebilirsiniz. Sonuçlarda da tam bu formatta bir bilgi buluyoruz. Eğer bunu bulamamış olsaydık, çıkan bütün sonuçları sırasıyla dikkatli bir şekilde incelememiz gerekecekti. Çıkan sonuca dair bir exploit olup olmadığına dair ister bir google araması yapabilir isterseniz searchsploit üzerinden de aratabilirsiniz:
  • Tam aradığımız formatta bir sonuçla karşılatık, içine bakalım:
  • Görebileceğimiz gibi, bu kod ld.so.preload modülünün overwriting yani üzerine yazma zafiyetini sömürerek root kullanıcısına geçiş yapmamızı sağlıyor. Kodu hedef makineye aldıktan sonra çalıştıralım:
  • Gördüğümüz gibi, haklarımızı root kullanıcısına yükseltmeyi başardık. Root flag’i elde edelim:
  • Madness makinesi ile ilgili sizinle paylaşmak istediklerim bu kadardı, yazımı okuduğunuz için teşekkür ederim. Bir sonraki yazıda görüşmek üzere. 

Kaynaklar:

  • https://digital-forensics.sans.org/media/hex_file_and_regex_cheat_sheet.pdf
  • https://www.ntfs.com/jpeg-signature-format.htm
  • https://www.geeksforgeeks.org/get-post-requests-using-python/
  • https://stackoverflow.com/questions/18810777/how-do-i-read-a-response-from-python-requests
  • https://stackoverflow.com/questions/33054527/typeerror-a-bytes-like-object-is-required-not-str-when-writing-to-a-file-in
  • https://medium.com/python/python-requests-mod%C3%BCl%C3%BC-4af79ebdb8c8

Related Posts

Facebook Comments