Источник: https://kuldeep.io/posts/holiday-hunting-with-aquatone/
Перевод от: BLUA
Софт: https://github.com/michenriksen/aquatone
Прежде чем перейти к посту, я бы хотел немного рассказать о том, как это было. Я оправился на работу в апреле 2022 года со своими друганами хацкерами(@N0_M3ga_Hacks, @AyushBawariya1 и @x30r_). Днём мы хакали, а по вечерам устраивали тусу.
Однажды я расскаывал своему другу @N0_M3ga_Hacks о том, как легко было озотиться на конкретную цель в Synack Red Team. Что он был полностью уязвимым. Я рассказывал, что обнаружил много язвимостей, просто запустив Aquatone в скопе на HTTP-сервисы. Мне даже не пришлось выполнять сканирование портов, чтобы найти дургие HTTP-сервисы на разных портах, таких как 8443, 8080 и т.д.
Рассказывая ему об этом, я подумал: "Позволь мне показать тебе это на практике", и я пошёл и запустил httpx на всех IP-адресах в области видимости и нашёл живые HTTP-сервисы. Затем я запустил Aquatone по всем IP-адресам.
Тут мы обнаружиди в общей сложности 3 уязвимости, которые опиманы ниже:
- SSRF Allowing To Access Google VM Metadata ($2400)
- SSRF Allowing To Access Internal Ports ($500)
- Exposed XXXX Portal Revealing Tickets ($705)
# SSRF, позволяющий получить доступ к метаданным виртуальной машины Google
Что выделялось из результатов Aquatone, так это тестовое приложение для веб-страницы. Веб-корень приложения выглядел следующим образом:
Он запрашивал у нас URL сайта для "запуска теста". Я не знал, что это будет за тест. И для примера я дал ему url: https://example.com и видел следующее
Меня заинтересовало, скриншот https://example.com. Приложение отправило запрос на https://example.com и сделало его скриншот.
Это предполагаемое поведение приложения, и возможность запрашивать произвольные URL-адреса сама по себе не является уязвимостью. Уязмость возникает, когда приложение отправляет запросы к спрятанным URL-адресам, таким как URL-адреса облачных метаданных или localhost, на которых действительно доступна конфиденциальная информация.
Порадовался тому что я увидел и тут же написал https://127.0.0.1 и нажал - "начать тест".
Пришлось немного подождать перед тем как он выдал мне результаты. На этот раз результат меня разочаровал.
Он выдал сообщение - "Этот сайт недоступен".
Я отправил запрос в Burp Suite Intruder и начал выполнять сканироване top 1000 портов, но это отняло много времени. Выполнение всех этих тестов занимало 2-3 минуты. Даже если взять наилучший вариант 0 2 минуты, для завершения этого теста понадобилось бы 2000 минут, что составляет 33,33 часа для выполнения сканирования всех top 1000.
Это был неправильный путь. Чтобы найти обходной путь, я проиграл с настройками приложения и нашёл возможность отключить эти "тесты", которые, как мне казалось, занимали большую часть времени.
Я выключил тестирование и попробовал ещё раз. Но задержка в 2-3 минуты всё ещё была, несмотря на то, что тесты были выключены или включены. Я начал думать что проблема либо в интернете либо в браузере.
Однако тестируя это, я устроил беспорядок. Прежде чем отправлялся новый URL для тестирования, все тесты старых URL-лов должны были завершиться. Если они не будут завершены, то новые тесты останутся незвершёнными. А до этого я отрпавил 1000 запросов на свервер, сканируя порты.
Это означало что я не могу продолжать тестирование, не дождавшись 33,33 часов. Я хотел, чтобы кто-нибудь перезапустил сервер, чтобы мне не пришлось ждать так долго, но сервер, казалось , не использовался, так как никто не отправлял никаких тестов в течение этих 33,33 чаосв. Я также проверил старые тесты, но жо того, как я отправил свои, тестов не было.
Через два дня я проверил, все тесты были завершены. Я посмотрел результаты, нашёл все скриншоты и скачал их.
Проверив все скриншоты, я снова был разачарован, так как ни на одном из портов не были запущены HTTP-сревисы. Даже после двухдневного ожидания результатов ничего найдено не было.
Я попробовал использовать file:// чтобы извлечь /etc/passwd - но это не сработало.
Я пошёл дальше, чтобы получить метаданные облака. Это должно было быть самым очевидным выбором для меня, поскольку клиент размещал всю свою инфраструктуру на GCP. Но, взламывая это, я больше интересовался внутренними сервисами, чем обычными метаданными.
Чтобы получить метаданные Google, нам нужно запросить http://metadata.google.internal/computeMetadata/v1 с двумя пользовательскими заголовками, которые выглядят следующим образом:
- X-Google-Metadata-Request: True
- Metadata-Flavor: Google
К счастью, приложение также предоставило функиональность для добавления дполнительных заголовков перед запуском **webpagetest**.
Я добавил заголовки и запустил на http://metadata.google.internal/computeMetadata/v1/. На этот раз на финиш ушло больше 2-3 минут, так что я был взволнован. Но я снова был разочарован, так как в рещультате получился пустой скриншот.
Я отказался от облачных метаданных и попытался проверить несколько распространенных портов, таких как 8080, 8125, 80, 5000 и т.д. Это также привело к тому же результату, что и мои предыдущие попытки сканирования порта. Я решил отойти от этого и сделать небольшой перерыв.
Спустя 5 дней я снова вернулся к получению метаданных Google. На этот раз я попробовал с несколькими другими конечными точками, такими как:
- /computeMetadata/v1/instance/hostname
- /computeMetadata/v1/instance/id
- /computeMetadata/v1/instance/image
Список можно продолжать, но суть вы поняли. Я перепробовал много других конечных точек. Я также использовал очень полезный список **Cloud Metadata Wordlist Gist**. Однако ни одна из этих конечных точек, похоже, не сработала в моем случае.
Затем я просто погуглил “google cloud metadata”, и самым первым результатом стала официальная документация о том, как получить доступ к метаданным виртуальной машины. Когда я читал это, в нем упоминалась следующая конечная точка:
- /computeMetadata/v1/instance/tags
Я предоставил конечную точку приложению для тестирования, и, к моему удивлению, оно выдало мне результат!
Из-за того, что скриншот был слишком маленьким, чтобы получить из него какую-то полезную информацию, нам нужно найти дургой способ.
Покопавшись в различных функциях, я нашел один способ просмотра результирующего HTML-содержимого. Все, что мне нужно было сделать, это нажать на кнопку “Просмотреть результат JSON”. После нажатия приложение показало показатели производительности и всю остальную информацию в формате JSON.
Здесь я смог увидеть результирующий HTML-контент в поле JSON под названием “html”.
Я снова проверил Cloud Metadata Wordlist Gist и обнаружил, что я не проверил одну конечную точку, показанную в списке. Это была следующая конечная точка:
- /computeMetadata/v1/instance/disks/?recursive=true
Я быстро ввел эту конечную точку и проверил результат HTML в JSON и обнаружил, что в нем успешно перечислены все диски!
Сообщил об этом со всеми необходимыми доказательствами, и это было принято.
То же приложение предлагало другие функции, такие как запуск пользовательского сценария тестирования, массовое тестирование, массовое тестирование с использованием загрузки файла и т.д. И все они были уязвимы для такой атаки.
Я не буду объяснять каждый из них, но эксплойт, использующий пользовательский сценарий тестирования, выглядел следующим образом:
# SSRF, позволяющий получить доступ к внутренним портам
Корневой каталог веб-приложения с этим IP-адресом показал функцию поиска, как показано ниже.
Здесь вы можете видеть, что URL-адрес отображается рядом с раскрывающимся списком “кластер”. Мы можем изменить раскрывающийся список кластера на другие параметры, которые изменят URL. Мое лучшее предположение заключается в том, что мы можем изменить кластер для переключения между средами dev/prod.
При поиске строки “test” отправляется POST-запрос к конечной точке /search вместе с множеством других параметров.
Ниже приведена подробная разбивка нескольких важнейших параметров:
- url - Это был URL-адрес, на который был отправлен поисковый запрос. Если вы измените кластер с помощью выпадающего списка, этот URL-адрес изменится.
- sortby - Это был столбец/критерий, по которым должен был быть отсортирован результат.
- sortorder - По возрастанию или по убыванию в зависимости от значения.
- keyword - Ключевое слово для поиска в кластере.
- page - Это было использовано для разбивки на страницы.
- storeid - Идентификатор магазина, в котором мы должны были выполнить поиск.
Исходя из параметров, я предположил, что веб-приложение может использовать последовательность, подобную приведенной ниже:
Здесь параметр url напрямую щелкнул как SSRF в моей голове, но я сохранил его внутри и начал искать SQL-инъекции.
Я протестировал все параметры и все URL-адреса кластера, чтобы увидеть, уязвим ли какой-либо из них для SQL-инъекции или нет. Но все они были безопасными, и внедрение SQL было невозможно ни в одном из кластеров.
Теперь, возвращаясь к SSRF, я изменил параметр url на URL моей темы и увидел, что сервер теперь ответил JSONDecodeError и подробной трассировкой стека.
Возможно, вам интересно: “Почему возникает это исключение?” Это связано с тем, что веб-приложение пытается декодировать в JSON данные, возвращаемые с нашего URL-адреса TUPoC, но наш URL-адрес темы не отправляет действительные данные JSON. Он отправляет обычный HTML-код.
Воспользовавшись этой подробной ошибкой, мы можем перечислить открытые HTTP-службы на уязвимом сервере.
Мыслительный процесс, лежащий в основе этого, заключается в том, что если веб-служба запущена на сервере, она вернет некоторые HTML-данные. Веб-приложение попытается декодировать HTML-данные в формате JSON, и, следовательно, будет выдано исключение. Таким образом, мы можем перечислить открытые HTTP-порты.
Я быстро отправил запрос в Burp Suite Intruder и изменил параметр url на http://127.0.0.1:§1§ и запустил intruder от 1 до 5000, чтобы профазить верхние 5000 портов.
Как только атака была завершена, я обнаружил, что порт 5000 открыт и на нем запущена уязвимая служба.
Все остальные порты вернули исключение с ошибкой подключения.
# Открытый портал XXXX, раскрывающий тикеты
И снова веб-корень этого хостинга показал какую-то панель мониторинга, которая показалась мне интересной.
Он показывал различные функциональные возможности, такие как инциденты, тикеты, изменения и т.д. API ограничивал доступ к некоторым функциям. Однако только некоторые функции были защищены, и большинство функций было доступно без какой-либо аутентификации.
Здесь я смог просмотреть все открытые тикеты.
# Выводы
- Сотрудничайте с единомышленниками.
- Не сдавайтесь, если ваш способ эксплуатации не сработает. Сделайте перерыв и попробуйте еще раз.
- Взломать не так просто, как я описал в этом посте. Иногда я пытаюсь взломать более 12 часов, не находя уязвимости или даже чего-то, с чем можно поиграть. И иногда мне везет, и я нахожу множество уязвимостей с помощью чего-то такого простого, как aquatone.
- Возьмите отпуск/выходные.
Спасибо за чтение.
Если у вас есть какие-либо вопросы, вы можете связаться со мной в Twitter по адресу @kuldeepdotexe.
Happy hacking!
Перевод от: BLUA
Софт: https://github.com/michenriksen/aquatone
Прежде чем перейти к посту, я бы хотел немного рассказать о том, как это было. Я оправился на работу в апреле 2022 года со своими друганами хацкерами(@N0_M3ga_Hacks, @AyushBawariya1 и @x30r_). Днём мы хакали, а по вечерам устраивали тусу.
Однажды я расскаывал своему другу @N0_M3ga_Hacks о том, как легко было озотиться на конкретную цель в Synack Red Team. Что он был полностью уязвимым. Я рассказывал, что обнаружил много язвимостей, просто запустив Aquatone в скопе на HTTP-сервисы. Мне даже не пришлось выполнять сканирование портов, чтобы найти дургие HTTP-сервисы на разных портах, таких как 8443, 8080 и т.д.
Рассказывая ему об этом, я подумал: "Позволь мне показать тебе это на практике", и я пошёл и запустил httpx на всех IP-адресах в области видимости и нашёл живые HTTP-сервисы. Затем я запустил Aquatone по всем IP-адресам.
Тут мы обнаружиди в общей сложности 3 уязвимости, которые опиманы ниже:
- SSRF Allowing To Access Google VM Metadata ($2400)
- SSRF Allowing To Access Internal Ports ($500)
- Exposed XXXX Portal Revealing Tickets ($705)
# SSRF, позволяющий получить доступ к метаданным виртуальной машины Google
Что выделялось из результатов Aquatone, так это тестовое приложение для веб-страницы. Веб-корень приложения выглядел следующим образом:
Он запрашивал у нас URL сайта для "запуска теста". Я не знал, что это будет за тест. И для примера я дал ему url: https://example.com и видел следующее
Меня заинтересовало, скриншот https://example.com. Приложение отправило запрос на https://example.com и сделало его скриншот.
Это предполагаемое поведение приложения, и возможность запрашивать произвольные URL-адреса сама по себе не является уязвимостью. Уязмость возникает, когда приложение отправляет запросы к спрятанным URL-адресам, таким как URL-адреса облачных метаданных или localhost, на которых действительно доступна конфиденциальная информация.
Порадовался тому что я увидел и тут же написал https://127.0.0.1 и нажал - "начать тест".
Пришлось немного подождать перед тем как он выдал мне результаты. На этот раз результат меня разочаровал.
Он выдал сообщение - "Этот сайт недоступен".
Я отправил запрос в Burp Suite Intruder и начал выполнять сканироване top 1000 портов, но это отняло много времени. Выполнение всех этих тестов занимало 2-3 минуты. Даже если взять наилучший вариант 0 2 минуты, для завершения этого теста понадобилось бы 2000 минут, что составляет 33,33 часа для выполнения сканирования всех top 1000.
Это был неправильный путь. Чтобы найти обходной путь, я проиграл с настройками приложения и нашёл возможность отключить эти "тесты", которые, как мне казалось, занимали большую часть времени.
Я выключил тестирование и попробовал ещё раз. Но задержка в 2-3 минуты всё ещё была, несмотря на то, что тесты были выключены или включены. Я начал думать что проблема либо в интернете либо в браузере.
Однако тестируя это, я устроил беспорядок. Прежде чем отправлялся новый URL для тестирования, все тесты старых URL-лов должны были завершиться. Если они не будут завершены, то новые тесты останутся незвершёнными. А до этого я отрпавил 1000 запросов на свервер, сканируя порты.
Это означало что я не могу продолжать тестирование, не дождавшись 33,33 часов. Я хотел, чтобы кто-нибудь перезапустил сервер, чтобы мне не пришлось ждать так долго, но сервер, казалось , не использовался, так как никто не отправлял никаких тестов в течение этих 33,33 чаосв. Я также проверил старые тесты, но жо того, как я отправил свои, тестов не было.
Через два дня я проверил, все тесты были завершены. Я посмотрел результаты, нашёл все скриншоты и скачал их.
Проверив все скриншоты, я снова был разачарован, так как ни на одном из портов не были запущены HTTP-сревисы. Даже после двухдневного ожидания результатов ничего найдено не было.
Я попробовал использовать file:// чтобы извлечь /etc/passwd - но это не сработало.
Я пошёл дальше, чтобы получить метаданные облака. Это должно было быть самым очевидным выбором для меня, поскольку клиент размещал всю свою инфраструктуру на GCP. Но, взламывая это, я больше интересовался внутренними сервисами, чем обычными метаданными.
Чтобы получить метаданные Google, нам нужно запросить http://metadata.google.internal/computeMetadata/v1 с двумя пользовательскими заголовками, которые выглядят следующим образом:
- X-Google-Metadata-Request: True
- Metadata-Flavor: Google
К счастью, приложение также предоставило функиональность для добавления дполнительных заголовков перед запуском **webpagetest**.
Я добавил заголовки и запустил на http://metadata.google.internal/computeMetadata/v1/. На этот раз на финиш ушло больше 2-3 минут, так что я был взволнован. Но я снова был разочарован, так как в рещультате получился пустой скриншот.
Я отказался от облачных метаданных и попытался проверить несколько распространенных портов, таких как 8080, 8125, 80, 5000 и т.д. Это также привело к тому же результату, что и мои предыдущие попытки сканирования порта. Я решил отойти от этого и сделать небольшой перерыв.
Спустя 5 дней я снова вернулся к получению метаданных Google. На этот раз я попробовал с несколькими другими конечными точками, такими как:
- /computeMetadata/v1/instance/hostname
- /computeMetadata/v1/instance/id
- /computeMetadata/v1/instance/image
Список можно продолжать, но суть вы поняли. Я перепробовал много других конечных точек. Я также использовал очень полезный список **Cloud Metadata Wordlist Gist**. Однако ни одна из этих конечных точек, похоже, не сработала в моем случае.
Затем я просто погуглил “google cloud metadata”, и самым первым результатом стала официальная документация о том, как получить доступ к метаданным виртуальной машины. Когда я читал это, в нем упоминалась следующая конечная точка:
- /computeMetadata/v1/instance/tags
Я предоставил конечную точку приложению для тестирования, и, к моему удивлению, оно выдало мне результат!
Из-за того, что скриншот был слишком маленьким, чтобы получить из него какую-то полезную информацию, нам нужно найти дургой способ.
Покопавшись в различных функциях, я нашел один способ просмотра результирующего HTML-содержимого. Все, что мне нужно было сделать, это нажать на кнопку “Просмотреть результат JSON”. После нажатия приложение показало показатели производительности и всю остальную информацию в формате JSON.
Здесь я смог увидеть результирующий HTML-контент в поле JSON под названием “html”.
Я снова проверил Cloud Metadata Wordlist Gist и обнаружил, что я не проверил одну конечную точку, показанную в списке. Это была следующая конечная точка:
- /computeMetadata/v1/instance/disks/?recursive=true
Я быстро ввел эту конечную точку и проверил результат HTML в JSON и обнаружил, что в нем успешно перечислены все диски!
Сообщил об этом со всеми необходимыми доказательствами, и это было принято.
То же приложение предлагало другие функции, такие как запуск пользовательского сценария тестирования, массовое тестирование, массовое тестирование с использованием загрузки файла и т.д. И все они были уязвимы для такой атаки.
Я не буду объяснять каждый из них, но эксплойт, использующий пользовательский сценарий тестирования, выглядел следующим образом:
Код:
addHeader Metadata-Flavor: Google
navigate http://metadata.google.internal/computeMetadata/v1/instance/disks/?recursive=true
# SSRF, позволяющий получить доступ к внутренним портам
Корневой каталог веб-приложения с этим IP-адресом показал функцию поиска, как показано ниже.
Здесь вы можете видеть, что URL-адрес отображается рядом с раскрывающимся списком “кластер”. Мы можем изменить раскрывающийся список кластера на другие параметры, которые изменят URL. Мое лучшее предположение заключается в том, что мы можем изменить кластер для переключения между средами dev/prod.
При поиске строки “test” отправляется POST-запрос к конечной точке /search вместе с множеством других параметров.
Ниже приведена подробная разбивка нескольких важнейших параметров:
- url - Это был URL-адрес, на который был отправлен поисковый запрос. Если вы измените кластер с помощью выпадающего списка, этот URL-адрес изменится.
- sortby - Это был столбец/критерий, по которым должен был быть отсортирован результат.
- sortorder - По возрастанию или по убыванию в зависимости от значения.
- keyword - Ключевое слово для поиска в кластере.
- page - Это было использовано для разбивки на страницы.
- storeid - Идентификатор магазина, в котором мы должны были выполнить поиск.
Исходя из параметров, я предположил, что веб-приложение может использовать последовательность, подобную приведенной ниже:
Здесь параметр url напрямую щелкнул как SSRF в моей голове, но я сохранил его внутри и начал искать SQL-инъекции.
Я протестировал все параметры и все URL-адреса кластера, чтобы увидеть, уязвим ли какой-либо из них для SQL-инъекции или нет. Но все они были безопасными, и внедрение SQL было невозможно ни в одном из кластеров.
Теперь, возвращаясь к SSRF, я изменил параметр url на URL моей темы и увидел, что сервер теперь ответил JSONDecodeError и подробной трассировкой стека.
Возможно, вам интересно: “Почему возникает это исключение?” Это связано с тем, что веб-приложение пытается декодировать в JSON данные, возвращаемые с нашего URL-адреса TUPoC, но наш URL-адрес темы не отправляет действительные данные JSON. Он отправляет обычный HTML-код.
Воспользовавшись этой подробной ошибкой, мы можем перечислить открытые HTTP-службы на уязвимом сервере.
Мыслительный процесс, лежащий в основе этого, заключается в том, что если веб-служба запущена на сервере, она вернет некоторые HTML-данные. Веб-приложение попытается декодировать HTML-данные в формате JSON, и, следовательно, будет выдано исключение. Таким образом, мы можем перечислить открытые HTTP-порты.
Я быстро отправил запрос в Burp Suite Intruder и изменил параметр url на http://127.0.0.1:§1§ и запустил intruder от 1 до 5000, чтобы профазить верхние 5000 портов.
Как только атака была завершена, я обнаружил, что порт 5000 открыт и на нем запущена уязвимая служба.
Все остальные порты вернули исключение с ошибкой подключения.
# Открытый портал XXXX, раскрывающий тикеты
И снова веб-корень этого хостинга показал какую-то панель мониторинга, которая показалась мне интересной.
Он показывал различные функциональные возможности, такие как инциденты, тикеты, изменения и т.д. API ограничивал доступ к некоторым функциям. Однако только некоторые функции были защищены, и большинство функций было доступно без какой-либо аутентификации.
Здесь я смог просмотреть все открытые тикеты.
# Выводы
- Сотрудничайте с единомышленниками.
- Не сдавайтесь, если ваш способ эксплуатации не сработает. Сделайте перерыв и попробуйте еще раз.
- Взломать не так просто, как я описал в этом посте. Иногда я пытаюсь взломать более 12 часов, не находя уязвимости или даже чего-то, с чем можно поиграть. И иногда мне везет, и я нахожу множество уязвимостей с помощью чего-то такого простого, как aquatone.
- Возьмите отпуск/выходные.
Спасибо за чтение.
Если у вас есть какие-либо вопросы, вы можете связаться со мной в Twitter по адресу @kuldeepdotexe.
Happy hacking!