Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Сегодня мы поработаем с токенами JWT, проэксплуатируем LFI в обход фильтра и разреверсим ELF-файл, написанный на Python 3.9. Все это поможет нам пройти среднюю по сложности машину Unicode с площадки Hack The Box.
warning
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Сканирование портов
Добавляем IP-адрес машины в /etc/hosts
:
10.10.11.126 unicode.htb
И запускаем сканирование портов.
Справка: сканирование портов
Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.
Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта.
#!/bin/bashports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr 'n' ',' | sed s/,$//)nmap -p$ports -A $1
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A
).
Результат работы скрипта
Мы нашли два открытых порта:
Начнем с исследования сайта.
Главная страница сайта
На первой же странице видим открытый редирект. Это стоит отметить, так как редиректы можно использовать для обхода ряда фильтров и проверок. Также на сайте есть возможность зарегистрироваться и авторизоваться. Сделаем и то и другое. Работу желательно вести в Burp Proxy, чтобы у нас оставались все записи.
Burp Proxy
После логина видим редирект с присвоенным идентификатором сессии auth
. И сразу подмечаем несколько новых возможностей после авторизации.
Главная страница сайта после авторизации
Удалось найти форму загрузки файлов, но ее тестирование ни к чему не привело. Вернемся к идентификатору сессии — это JWT. JSON Web Token состоит из трех частей: заголовка (header), полезной нагрузки (payload) и подписи. Заголовок и полезная нагрузка представляют собой объекты JSON, при этом нагрузка может быть любой, это именно те критически важные данные, которые передаются приложению. Заголовок содержит определенные поля:
alg
— алгоритм, используемый для подписи/шифрования. Это обязательный ключ;
typ
— тип токена. Это поле должно иметь значение JWT
.
Третий элемент вычисляется на основании первых и зависит от выбранного алгоритма. Токены могут быть перекодированы в компактное представление: к заголовку и полезной нагрузке применяется алгоритм Base64-URL, после чего добавляется подпись и все три элемента разделяются точками. К примеру, можно с помощью Burp Inspector декодировать заголовок.
Декодированный заголовок
Попробуем разобрать эти данные. Для этого нам понадобится либо приложение jwt_tool, либо онлайновый ресурс jwt.io. Я буду использовать второй вариант. В заголовке у нас присутствует параметр jku
. Он определяет URI, который указывает на ресурс, где находится ключ проверки подписи в представлении JWKS (JSON Web Key Set). В качестве подписанных данных используется имя пользователя.
Декодирование JWT
Вернемся к параметру jku
, там мы находим еще один домен, который допишем в файл /etc/hosts
.
10.10.11.126 hackmedia.htb unicode.htb
JSON Web Key Set (JWKS) — это набор открытых ключей, которые используются для проверки веб‑токена, выпущенного сервером авторизации и подписанного с использованием алгоритма подписи RS256. RS256 генерирует асимметричную подпись. Чтобы подписать JWT, должен использоваться закрытый ключ, а для проверки подписи нужен другой открытый ключ. Просмотреть структуру JWKS мы можем, обратившись к URL, указанному в jku, — http://hackmedia.htb/static/jwks.json
.
Используемый JWKS
Дальнейший вектор очевиден: необходимо изменить имя пользователя на admin
, что даст нам привилегированный контекст, подписать новые данные, сгенерировать новый JWT и заменить старый на веб‑сервисе.
Теперь разберемся с подписью. В заголовке указан адрес JWKS, что дает нам следующую идею: сгенерировать свою пару ключей для подписи токена и соответствующий им JWKS. Мы поместим JWKS на своем веб‑сервере и затем в заголовке пропишем адрес, указывающий на этот сервер. Для генерирования ключей воспользуемся сайтом mkjwk.org. Выставим используемые параметры и получим ключи.
Генерирование ключей
Теперь вернемся к токену на jwt.io. Изменим имя пользователя на admin
, в параметре jku
укажем файл на своем сервере (веб‑сервер запускаем командой python3 -m http.server 80
). Файл должен содержать данные из формы Public Key. Для подписи используем пару ключей из форм Private Key (X.509 PEM Format) и Public Key (X.509 PEM Format).
Создание JWT-токена
Вставляем данный токен в Burp и после запроса получаем ответ об ошибке проверки jku
.
Ответ от сервера
При этом на наш веб‑сервер запрос не пришел. Значит, есть проверка того, какой сервер указан в jku
. Тогда используем открытый редирект! Он будет перенаправлять на наш сервер запросы, совершаемые для проверки jku
:
http://hackmedia.htb/static/../redirect/?url=10.10.14.73/jwks.json
Новые параметры JWT
При использовании нового JWT видим, что на наш сервер пришел запрос.
Логи веб‑сервера
Но доступ мы не получаем. Скорее всего, это связано с данными в файле JWKS. Просмотрим тогда файл с сервера и изменим в нем только параметр n
(e
и так совпадает). Вновь посылая запрос через Burp, получаем новый ответ. Переходим в браузер и, используя расширения вроде Cookie Editor, вставляем новый JWT и обновляем страницу.
Панель администратора
В итоге получаем административную панель.
Изучая сайт, сразу натыкаемся на страницу, которая передает контент в параметре.
Страница /display
Попробуем указать там какой‑нибудь файл, например /etc/passwd
. Но получаем ошибку и сообщение о том, что используется фильтр.
Сообщение, что обнаружена атака
Тогда я применил словарь, в котором содержатся разные способы обхода фильтров для LFI, и получил отличную от остальных реакцию сервера.
Содержимое файла /etc/hosts
Источник: xakep.ru