Первым делом просканируем порты на 10.124.249.9 с помощью nmap.
Nmap scan report for 10.124.249.9
Host is up, received syn-ack (0.0074s latency).
Scanned at 2024-09-16 15:11:41 EDT for 17s
Not shown: 65531 closed tcp ports (conn-refused)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
80/tcp open http syn-ack nginx 1.25.1
3306/tcp open mysql syn-ack MySQL 5.7.43
8082/tcp open http syn-ack Apache httpd 2.4.57 ((Debian))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
На машинке 4 открытых порта ssh, вебчик, инстанс мускуля и phpmyadmin (админка для управления бд).
Information disclosure
После первичного изучения сайта corp-wiki.standalone.stf понимаем, что нам необходимо получить какую-то учетку. Так как свою создать пока не получается в связи с отсутствием invite code
, будем брутить чужие!) Посмотрев авторов статьей и побрутив учетки стандартным листом, находим первую точку входа - креды:
emiwil:1234
Перебрав параметр id (см. скриншот выше), выясняем, что у нас есть доступ к публикациям roblee
и michjohn
- У michjohn мы видим статью “Report about bug in software”
Внутри которой находится какой-то стектрейс с url-ом, видимо для какого-то локального сервиса: http://searchserver:8000/api/data
. Он нам понадобится чуть позже.
File "main.py", line 47, in <module>
data = fetch_data("http://searchserver:8000/api/data")
File "main.py", line 23, in fetch_data
response = requests.get(url)
File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 76, in get
return request('get', url, params=params, **kwargs)
File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 61, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 516, in request
prep = self.prepare_request(req)
- У roblee находим статью “Request: Get access back!“.
В ней лежит какой-то пароль:
Данный пароль к вики не подходит, но мы узнали ранее, что у сайта торчит phpmyadmin на 8082 порту.
Логинимся в phpmyadmin
Попробуем залогиниться в phpmyadmin с кредами, которые нашли у roblee.
Отлично! У нас получилось, теперь мы можем создать invite code, чтобы зарегистрировать своего пользователя. Здесь есть один момент, если у инвайта в поле isUsed значение 0 - его можно использовать, если 1 - использовать нельзя, логично. Поэтому новый инвайт лучше использовать как можно скорее, пока кто-то хитрый не стащил :)
Поиск дальнейших векторов
Пока первая половина нашей команды пыталась понять, как раскрутить инвайт коды, вторая во всю ломала интерфесйс вики.
Даже получилось залить php cmd shell, но он не отработал. А кто сказал, что будет легко?
Вики было чень плохо…
Также по пути встречались подозрительные XSSки других участников:
Практически все формы ввода на сайте были уязвимы к XSS’ам, но применить это так и не удалось. Когда-нибудь маленький XSS вырастет в большой Steal admin Cookie и станет полноценным вектором Киберполигона… Но не в этот раз.
В какой-то момент вики совсем поплохело.
WARNING! Видео небезопасно для людей, страдающих эпилепсией.
SSRF в подгрузке аватарок
Итак, возращаемся к решению. Мы обнаружили, что после создания инвайта появляется возможность регистрировать новых пользователей. У новых пользователей добавляется функционал изменения слогана, имени пользователя и картинки пользователя. Первые две функции оказались неуязвимы, а вот если при смене аватара обратиться на какой-то адрес, будь то http listener или внутренний адрес, сайт будет вести себя странно.
Поведение у этого сервиса такое:
- мы можем передать в поле url адрес, и сервис обратится к нему без фильтрации пользовательского ввода;
- отправится POST запрос на сервер;
- либо аватарка будет подгружена, либо мы получим ошибку “This is not a picture, check the link please.”
Оказалось, мы можем отправлять запросы локальной файловой системе и читать файлы:
На этом моменте можно быстренько реализовать SSRF
Идём дальше. Если мы обратимся ко внутреннему сервису searchserver
(адрес которого засветился в стектрейсе выше), то получим подсказку, что раскрутить вектор предстоит через API:
После чего пробуем побрутить пути для searchserver
и находим файлик openapi.json
, который расскажет нам, что этот сервис использует питоновский фреймворк Fast API и даже отдаст один путь!)
Когда мы направляемся по пути, который нам отдал openapi.json /api/articles/search/req
, нас встречает ошибка:
<span class="debug">
{"detail": [{"loc":["query","req"],"msg":"field required","type":"value_error.missing"}]}
</span>
Это дает нам понять, что не хватает одного query параметра req, передав в который подстроку, мы получаем лист из интов (правда нам всегда возвращается не полный ответ, а только кусок). Как мы выяснили позже, возвращается список id статей, в заголовках которых встречается подстрока из параметра req.
SQL injection в req параметре
Достаточно долго мы отчаянно пытались набрутить новый endpoint или вытащить что-то из существующего, пока не решили пихнуть кавычку во всё тот же req:)))
Жаль только корп-вики оказалась очень нежной, поэтому все попытки сканирования sqlmap’ом заканчивались падением сервера.
Пришлось крутить лапками ручками. Ну первым делом пробуем union based sql injection и пытаемся вытащить таблички. Предварительно дважды проэнкодив с помощью urlencoded наш payload:
' union select table_name from information_schema.columns -- -
Сначала мы можем реализовать уязвимость:
SQLi на узле corp-wiki.standalone.stf (10.124.249.9) Получите содержимое ячейки flag из таблицы secret.
Потому что она тоже в параметре req:
f'Union select FLAG from secret --;
Также отправляем в urlencoded на два раза:
Как и было описано ранее, мы видим не весь ответ сервера, а только его часть, а значит для получения названий нужных нам табличек можем воспользоваться OFFSET
и LIMIT
Найдя таблицу users и посмотрев, что в ней есть колонки name и pass, составим финальный запрос для извлечения кредов админа
' union select concat(name, ':', pass) from users limit 1 offset 0 --;
Заходим с этими кредами на аккаунт админа и видим, как в одной из статей будет лежать нужный нам флаг для критического события!
На этом мучения на wiki.standalone.stf закончились, всем спасибо!)