Scan / Enumeration
Makinedeki bütün açık portları erişebilmek için nmap
‘e -p-
parametresini verdiğim bir tarama ile keşif aşamasına başlıyorum. Varsayılan olarak -T3
hızında tarama yapan nmap’in hızını -T4
parametresi ile arttırıyorum. Tarama bitmeden bulduğu port numaralarını ekrana basması ve taramanın ne kadar daha süreceği hakkında düzenli olarak bilgi vermesi için -vv
parametresini kullanıyorum.
sudo nmap -T4 -vv -p- $IP

Bu tarama sonucunda 22, 80 ve 3000 portlarının açık olduğunu görüyorum. Yaptığımız varsayılan tarama herhangi bir versiyon taraması yapmadığı için çıktıda bize söylediği servislerin, o port numarasında genelde kullanılan servisler olduğunu biliyorum ve doğru bilgiye ulaşabilmek için ayrıntılı bir nmap taraması yapıyorum.
-p
parametresini kullanarak hangi portları taramak istediğimi belirtiyorum. -sVC
parametresi ile hem versiyon taraması hem de script taraması yapmasını istiyorum. -oN
parametresiyle tarama tamamlandığında çıktıyı bir dosyaya yazmasını söylüyorum.
sudo nmap -sVC -p 22,80,3000 $IP -oN secret.nmap

22 portunda SSH
– Secure Shell – servisi, 80 portunda HTTP
web server’ı ve 3000 portunda ise ilk taramada söylediği ppp servisinin aksine HTTP
servisinin çalıştığını görüyorum. Temel nmap keşfinden sonra en küçük port numarasından başlayarak, bütün servisleri keşfetmeye ve olası zafiyetleri sömürmeye çabalıyorum.
22 OpenSSH
22 portunda çalışan SSH servisiyle başlıyorum. searchsploit
‘i kullanarak OpenSSH 8.2p1
versiyonu için zafiyet araması yapıyorum fakat bir şey bulamıyorum. Google aracılığıyla da OpenSSH servisinin bu versiyonu için herhangi bir zafiyet olup olmadığını kontrol ediyorum fakat elle tutulur bir şey ile karşılaşmıyorum. Son olarak nmap’in ssh için bulundurduğu scriptleri locate .nse | grep ssh
komutuyla kontrol edip inceliyorum fakat buradaki scriptlerin çoğunun enumeration’a yönelik olduğunu görüp diğer servislerden bir sonuç olamazsam dönmek üzere bırakıyorum.

80 & 3000 HTTP
80 portundaki HTTP servisi için tarayıcı üzerinden web sayfasını inceleyerek araştırmaya başlıyorum. Öncelikle safyadaki yönlendirme linklerinin nerelere yönlendirdiğini inceliyorum daha sonra ise ulaşabildiğim sayfaların kaynak kodlarına göz gezdiriyorum. Sayfa içerisinde /download/files.zip
dizini altındaki dosyanın sitenin pazarlamaya çalıştığı ürün olan Auth API
uygulamasına ait kaynak kodlar olduğunu görüyorum. Dosyayı indiriyorum ve incelemeye başlıyorum.
Dosyayı incelediğim esnada website üzerinde daha fazla bilgi edinebilmek için gobuster
aracılığıyla dizin taraması yapıyorum. dir
argumanı ile dizin taraması yapmasını söylüyorum. -u
parametresiyle üzerinde tarama işlemini gerçekleştireceği url’i belirtiyorum. -w
parametresiyle kullanacağı wordlist’i veriyorum. -x
parametresiyle olası dosya uzantıları verip, wordlistteki her kelime için verdiğim uzantıları kullanarak dosya araması da yapmasını istiyorum. -t
parametresiyle varsayılan olarak 10 olan thread sayısını arttırıp taramanın hızlanmasını sağlıyorum. -o
parametresiyle tarama işlemi sonuçlandığında çıktısını bir dosyanın içine yazmasını istiyorum.
gobuster dir -u http://<IP>/ -w common.txt -x db,bak,php,txt -t 30 -o secret.buster
İndirdiğim dosyada .env
dosyası içerisinde TOKEN_SECRET
isminde bir değer buluyorum. Bu değer secret
olduğu için gerçek bir değer mi yoksa kullanıcılar doğru değere erişemesin diye öylesine mi yazılmış emin olamıyorum. index.js
dosyasını okuduğumda çalışan app’in makinedeki 3000 portunu dinlediğini görüyorum. Daha fazla bilgiye ulaşabilmek için diğer kod dosyalarını okumadan önce .git
dizinini incelemeye karar veriyorum.
.git
dizini içerisinde git log
komutunu kullanarak repoya önceden girilmiş commitleri görebiliyorum ve burada .env'
in silindiğine dair bir commit ile karşılaşıyorum.

Bu dosyanın silinmediği haline erişebilmek için git checkout $commitId
komutunu kullanarak dosyanın silinmesinden bir önceki commit’e gidiyorum ve dosyaya erişebiliyorum.

Burada bulduğum token’i uygulamanın neresinde kullanacağımı anlamak için 3000 portunda çalışan servisi incelemeye başlıyorum. Bu portta da 80 portunda çalışan websitenin aynısının çalıştığını görüyorum. Biraz daha inceliyorum ve bir fark göremeyince denemelerime 80 portunda devam etmeye karar verip geri dönüyorum.
Anasayfada bulunan yönlendirmeleri takip ederek docs
dizini altına gelip uygulamanın dökümantasyonunu okumaya başlıyorum. Burada kullanıcının kayıt olup auth-token
‘e erişmesinden sonra /api/priv
dizinine header’larına auth-token’i koyup GET
request atarak panele erişebileceği söyleniyor. Bu yöntem ile hem 80 portundaki uygulamaya hem 3000 portundaki uygulamaya bağlanmaya çalışıyorum fakat Invalid Token
uyarısını alıyorum.

Dokümanı tekrar ve daha dikkat ederek okuyorum. Anlıyorum ki elimdeki auth-token .
ile ayrılan 3 temel kısımdan oluşuyor ve benim elimdeki token muhtemelen bu tokenin data
kısmını oluşturan bölüm. Sisteme kendi kullanıcı adım ile kayıt olup tam bir auth-token
aldıktan sonra data kısmına elimdeki token’i girerek yetki yükseltebileceğimi düşünüyorum.
cURL
aracını kullanarak /api/user/register
adresine gerekli POST
request’i gönderebiliyorum. -X
parametresiyle request metodunu POST olarak belirtiyorum. -H
parametresine Content-Type
header’ını vererek göndereceğim bilginin JSON
olduğunu server’a anlatıyorum. -d
parametresiyle request’in body’sinde iletmem gereken JSON datayı iletiyorum.
curl -X POST http://$IP/api/user/register -H "Content-Type: application/json" -d '{"name":"$name","email":"$email","password":"$password"}'
Kayıt olduğum bilgilerle /api/user/login
dizinine request atarak kullanıcıma ait auth-token’i alıyorum.
curl -X POST http://$IP/api/user/login -H "Content-Type: application/json" -d '{"email":"$email","password":"$pass"}'

Kayıt olup elde ettiğim auth-token
‘in data
kısmıyla elimdeki token’i kıyasladığımda aynı tipte olmadıklarını anlıyorum. Kaynak koddaki dosyaları biraz daha inceleyip sistemin tam olarak ne yaptığını anlamaya çalışıyorum. Kaynak kodda routes
isimli dizindeki auth.js
dosyasında auth-token’i oluşturmak için jwt
isminde bir değişken kullandığını görüyorum. Dosyanın ilk satırlarında ise bu değişkenin jsonwebtoken
‘in yerine kullanıldığını görüp googleda arama yapıyorum. Elimdeki secret-token’i kullanarak auth-token üzerinde oynama yapabileceğim bir websitesi buluyorum.
Gain Shell
Token üzerinde ne gibi oynama yapmam gerektiği ve bu tokeni nerelerde kullanabileceğime dair daha fazla bilgiye erişmek için kodları okumaya devam ediyorum. routes
dizini altındaki dosyalarda kullanıcı adının theadmin
olması durumunda farklı çıktılar alacağımı görüp token üzerinde name
kısmını theadmin
olacak şekilde değiştirip yeni bir auth-token elde ediyorum.

Bu tokeni kullanarak /api/priv
dizinine request attığımda server’ın beni admin olarak gördüğüne dair bir response alıyorum.

Fakat hala admin yetkisiyle ne yapabileceğimi bilmiyorum bu yüzden kodları incelemeye devam ediyorum. Uzun süre kodlara baktıktan sonra, baktığım kodların server’da çalışan uygulamanın son hali olmadığını hatırlıyorum. .env
dosyasındaki secret-token
‘i almak için eski bir commit’e gittiğimi ve hala bu commit’in içerisinde olduğumu hatırlayarak okuduğum local-web
dizinini silerek daha önce indirdiğimiz files.zip
dosyasından uygulamanın son halini çıkartıyorum.
private.js
dosyası içerisinde, /logs
adresinin file
isminde bir query alıp bu query’nin değerini git log --oneline $file
komutu ile çalıştırdığını görüyorum. Gönderdiğim requestteki query’i, ; id
şeklinde vererek git log --oneline ; id
komutunu server’a yollayıp id
‘nin çıktısını almayı umuyorum. cURL aracılığıyla request’i kolay bir şekilde yollamak için gireceğim parametreyi URL Encode ile encode ederek gönderiyorum.
curl http://$IP/api/logs?file=%3B%20id -H "auth-token: $auth-token"

Serverda komut çalıştırabiliyorum ve reverse shell alabilmek için file parametresiyle bir payload yolluyorum.

Daha stabil bir shell’e erişebilmek için dasith kullanıcısının id_rsa
dosyasını bulmak amacıyla .ssh dizinine bakıyorum fakat bulamıyorum. Kendi makinemde ssh-keygen
ile bir id_rsa
dosyası oluşturup id_rsa.pub
‘ı dasith’in authorized_keys
dosyasına ekliyorum ve kendi dosyamla SSH üzerinden bağlantı kurabiliyorum.
Privilege Escalation
sudo -l
komutuyla dasith kullanıcısının sudo yetkisini kontrol etmek istiyorum fakat kullanıcının şifresini istediği için edemiyorum. find / -perm -4000 2>/dev/null
komutuyla SUID
dosyalarını kontrol ediyorum ve /opt/count
dosyasının SUID dosyası olduğunu görüyorum.
count
binary’sini strings komutuyla inceleyip ne yaptığını anlamaya çalışıyorum. Bir dosya veya dizin adresini input olarak alıp dosya veya satır sayısını veren bir C
programı gibi görünüyor. Programı çalıştırıp deniyorum.

root
kullanıcısının .ssh
dizini altındaki id_rsa
dosyası için de kodu çalıştırıyorum fakat bu seferde dosya içerisindeki satır sayısı gibi bilgilerden başka bir şey elde edemiyorum. Aynı dizinde yer alan code.c
dosyasının count binary’sinin compile edilmemiş hali olduğunu anlıyorum ve incelemeye başlıyorum. Kodu uzun süre inceledikten sonra //Enable coredump generation
yorum satırının olduğu yere odaklanmaya ve core dump’ı araştırmaya karar veriyorum.

Öncelikle Arch Wiki‘de gördüğüm bir yöntem ile count binary’sini çalıştırıp CTRL+Z
ile arka plana aldıktan sonra core dump
yapmayı deniyorum fakat başaramıyorum.

ptrace: Operation not permitted
hatası ile başarısız oluyorum. Red Hat‘in bulduğum bir kaynağındaki gcore yöntemini deniyorum fakat onda da aynı hata nedeniyle başarısız oluyorum.

Stack Overflow‘dan bulduğum kill -ABRT $pid
yöntemiyle core dump yapmayı başarıyorum. Crash raporlarının saklandığı dizin olan /var/crash dizinine baktığımda dosyaya ait hata raporunu görüyorum.
Dosyayı incelemeye çalışıyorum fakat büyük bir bölümü encoded olan dosyanın okunabilir kısmından elle tutulur bir şey elde edemiyorum. Crash
dosyalarının nasıl incelenebileceğine dair araştırma yaptığımda AskUbuntu‘da konuyla ilgili bir başlık buluyorum. Burada gördüğüm gibi apport-unpack
komutunu kullanarak raporu incelemeyi deniyorum.

Çıkan dizindeki dosyaları sırasıyla incelemeye başlıyorum. CoreDump
‘ı okumaya çalıştığımda önemden akan çoğu anlamsız karakterler arasında root
kullanıcısına ait id_rsa
dosyasının çıktısını görüyorum ve strings CoreDump
komutuyla tekrar okuyup çıktıyı alıyorum.

Buradan elde ettiğim id_rsa
dosyasını kullanarak secret
makinesinin root
kullanıcısına bağlanabiliyorum.
