Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
Помогли мы вам |
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Добавляем IP-адрес машины в /
:
10.10.11.157 overgraph.htb
И запускаем сканирование портов.
Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.
Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта.
ports=$(nmap -p- --min-rate=500 $1 | grep^[0-9] | cut -d '/' -f 1 | tr 'n' ',' | sed s/,$//)nmap -p$ports -A $1
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A
).
Открыто два порта: 22 — служба OpenSSH 8.2p1 и 80 — веб‑сервер Nginx 1.18.0. Nmap показал нам, что выполняется редирект на адрес http://
. Тоже добавляем этот адрес в файл /
.
10.10.11.157 overgraph.htb graph.htb
Главная страница http://graph.htbСайт оказался одностраничным, поэтому нужно найти новые цели для тестирования.
Попробуем поискать скрытые каталоги и файлы при помощи ffuf.
Одно из первых действий при тестировании безопасности веб‑приложения — это сканирование методом перебора каталогов, чтобы найти скрытую информацию и недоступные обычным посетителям функции. Для этого можно использовать программы вроде dirsearch и DIRB.
Я предпочитаю легкий и очень быстрый ffuf. При запуске указываем следующие параметры:
-w
— словарь (я использую словари из набора SecLists);-t
— количество потоков;-u
— URL;-fc
— исключить из результата ответы с кодом 403.
ffuf -u 'http://graph.htb/FUZZ' -t 256 -wdirectory_2.3_medium_lowercase.txt
Результат сканирования каталогов с помощью ffufИ не находим ничего интересного, даже в файле server-status
. Поэтому попробуем просканировать поддомены, для чего снова будем использовать ffuf. К параметрам добавим заголовки -H
и --fs
, это поможет отсеять страницы по размеру.
ffuf -u 'http://graph.htb/' -t 256 -wsubdomains-top1million-110000.txt -H 'Host: FUZZ.graph.htb' --fs 178
Результат сканирования поддоменов с помощью ffufИ находим новый поддомен internal
. Добавляем его в файл /
.
10.10.11.157 overgraph.htb graph.htb internal.graph.htb
Но, открыв сайт в браузере, сразу натыкаемся на форму авторизации.
Так как всю работу проводим через Burp, то обнаружим в Burp History обращение еще к одному домену — internal-api.
.
Добавляем еще одну запись в файл /
и затем открываем страницу /
.
10.10.11.157 overgraph.htb graph.htb internal.graph.htb internal-api.graph.htb
Главная страница сайта http://internal-api.graph.htbНа странице используется GraphQL. Это язык запросов, с помощью которого клиентские приложения работают с данными. «Схемы» GraphQL позволяют организовывать создание, чтение, обновление и удаление данных в приложении. Давай получим данные __schema
и отфильтруем названия типов, это можно сделать, передав в параметре query
следующий запрос:
{__schema{types{name,fields{name}}}}
Ответ сервераОтвет сервера (продолжение)На этом пока все, но мы еще не сканировали каталоги на новом домене. Попробуем сделать это. Но, как только мы обратимся к любой странице, получим ответ, что запросы GET не поддерживаются. Поэтому будем сканировать запросом POST. А так как на домене крутится API, то и использовать будем соответствующий словарь.
ffuf -u 'http://internal-api.graph.htbFUZZ' -t 256 -XPOST -wapiscan.txt
Результат сканирования API с помощью ffufИ находим три новые страницы, с которыми начнем работу.
Итак, мы имеем следующие API:
register
— для регистрации пользователя;verify
— предположительно для проверки при регистрации;code
— пока непонятно, но, скорее всего, для проверки кода, отправленного на email.Я начал со страницы /
. Передаем наиболее вероятные параметры: имя пользователя, пароль и адрес электронной почты.
{
"username":"ralf",
"email":"ralf@graph.htb",
"password":"ralf"
}
Попытка регистрации пользователяНо в ответ нам говорят, что у нас неверный email или он не верифицирован. Это интересно, так как у нас остается всего две страницы для регистрации. Видимо, страница /
нужна для получения кода. Отправим туда свой email.
{
"email":"ralf@graph.htb"
}
Получение кодаИ нам сообщают, что четыре цифры были отправлены на указанный почтовый ящик. По тестовому сообщению на странице /
узнаем, что вместе с почтой нужно присылать и код.
Я попробовал перебрать этот код с помощью Burp Intruder, благо комбинаций всего 10 000. Но уже на одном из первых запросов все ломается, так как мы превысили количество попыток!
Я очень долго просидел на этом этапе — пришлось даже просить подсказки у друзей. Мне посоветовали углубиться в механизм проверки кода. Тогда, потратив еще немного времени, я нашел NoSQL-инъекцию, которая позволяет верифицировать почту, предоставляя неправильный код. В данном запросе мы получим положительный результат, если код не равен 0000.
"email":"ralf@graph.htb","code":{"$ne":"0000"}}
Верификация почтыПриходит подтверждение того, что почта верифицирована. Повторим регистрацию и получим сообщение, что пароль и его подтверждение не совпадают.
Тогда я перепробовал разные имена поля подтверждения пароля и определил, что в данном случае подходит confirmPassword
.
И аккаунт создан! Перейдем к форме авторизации на втором домене и авторизуемся.
А во входящих находим сообщение от пользователя Sally.
Нас просят прислать ссылку. Попробуем открыть локальный сервер и скинуть ссылку на него. В итоге приходит запрос.
Давай посмотрим, как это можно использовать.
Если еще раз взглянуть на страницу, можно заметить над меню надпись null
. В исходном коде есть отсылка к нашему пользователю. А в локальном хранилище браузера (F12 → Application) найдем запись, что это firstname
и lastname
.
Перейдем в настройки профиля и увидим то же самое, только с возможностью изменить эти значения.
Надпись null
натолкнула меня на мысль об использовании шаблонов. Давай проведем базовый тест.
Как можно увидеть, вместо введенной строки получаем результаты выражений, а значит, есть уязвимость в шаблонах! Вот только в локальном хранилище эти значения хранятся, как и вводились. Значит, шаблон работает на клиентской стороне, а это уже путь для CSTI — инъекции шаблонов на стороне клиента.
Также я обратил внимание на параметр admin
со значением false
. Я изменил на true
и перезагрузил страницу. В меню появилась графа Upload
.
Только вот форма загрузки не дает загрузить файл. Если вернемся к нашей схеме GraphQL, то можем посмотреть на необходимые параметры, к примеру adminToken
.
Таким образом, нам нужен adminToken
пользователя Sally. Но получить его непросто. Тут появился следующий план: если заставим целевого пользователя выполнить запрос на смену имени (по ссылкам же он переходит!), то в качестве нового имени установим нагрузку CSTI, передающую нам adminToken
. В исходниках видим использование AngularJS.
AngularJS — это популярная библиотека jаvascript, которая сканирует HTML на предмет тегов с атрибутом ng-app
(директива AngularJS). Когда директива добавляется в тег, появляется возможность выполнять выражения jаvascript в двойных фигурных скобках.
Уязвимость Template Injection возникает, когда приложение, используя какой‑нибудь шаблонизатор, динамически внедряет пользовательский ввод в веб‑страницу. Когда страница отображается, фреймворк ищет в странице шаблонное выражение и выполняет его. Основное отличие CSTI от SSTI заключается в том, что при CSTI мы можем добиться лишь выполнения произвольного кода на jаvascript. Две самые популярные нагрузки для CSTI в AngularJS:
{{$on.constructor('alert(1)')()}}
Новое имя пользователяОбновляем страницу и первым делом видим окошко алерта.
А теперь попробуем эксфильтровать токен, для чего создадим у себя в хранилище тестовый.
В качестве нагрузки будем использовать знаменитый стилер, который похищает данные через картинку, а доступ к хранилищу получим через window.
.
Обновляем страницу и в логах локального веб‑сервера находим значение тестового токена.
Нагрузка для эксфильтрации готова, теперь разберемся, как подсунуть пользователю наш код.
Я снова просмотрел все сайты и на самом главном домене нашел что‑то вроде редиректа.
Если существует GET-параметр redirect
, то функция window.
установит в качестве содержимого текущей страницы код, взятый по ссылке из redirect
. Благо мы можем вставить вместо URL код на jаvascript:
http://graph.htb/?redirect=jаvascript:alert(1)
Выполнение кода через jаvascript URLОсталось разобраться с данными, которые отправляются для изменения имени пользователя.
В Burp History найдем запрос, которым мы изменили собственное имя.
Один из параметров — id
пользователя, а это немного усложняет задачу. Снова вернемся к GraphQL и посмотрим, какой из типов содержит поле Assignedto
.
Нас интересует тип task
, который мы можем получить запросом tasks
.
Таким образом, нам нужно выполнить запрос tasks
с параметром username
, в котором мы передадим имя пользователя Sally
. Нас интересует только поле Assignedto
.
|
|