HTML во вложении — это программа. Почему почтовые фильтры его пропускают и как SOC его ловит

от автора

Материал написан для SOC-аналитиков, blue team и тех, кто проводит awareness-тренинги у себя в компании. Цель — научить отличать вредоносный HTML от безобидного и показать, какие детекты реально работают. Никаких готовых пейлоадов ниже не будет.

Почему вообще про это стоит писать

Когда сотрудник открывает письмо и видит вложение invoice.pdf он знает, что это документ. Когда он видит setup.exe большинство уже насторожится. А когда он видит scan_12.html — он, скорее всего, подумает, что это “какая-то страничка” и кликнет без задней мысли.

Хотя на самом деле .html это программа. Маленькая программа для браузера, которая может делать всё то, что умеет JavaScript на стороне клиента. В том числе собрать ZIP-архив прямо в памяти и скачать. Без единого запроса наружу.

Именно поэтому HTML-вложения стали любимой обёрткой у операторов Qakbot, IcedID, NOBELIUM и десятков менее известных групп. Microsoft зафиксировал всплеск ещё в 2021 году. С тех пор техника не ушла, а наоборот, она мутировала в SVG-варианты, в связки с ISO-контейнерами, в комбинации с thread hijacking. MITRE выделил её в отдельную подтехнику T1027.006 HTML Smuggling, а потом ещё и в T1027.017 SVG Smuggling.

Это работает. И будет работать дальше. Разбираемся почему.

Архитектурная дыра, а не баг

Почтовый шлюз SEG живёт в потоке писем. Он смотрит на вложения до того, как они попадут в почтовый ящик. Что он умеет:

  • Проверить MIME-тип и расширение.

  • Прогнать через сигнатурный антивирус.

  • Активировать вложение в sandbox и посмотреть, что оно делает.

И всё это отлично работает, если во вложении лежит .exe, .docm, .js или что-то похожее. Проблема в том, что HTML smuggling не доставляет исполняемый файл через почту. Вообще. В письме лежит текстовый файл, в нём — JavaScript и закодированные данные. Никакого ZIP, никакого EXE в момент прохождения через шлюз не существует.

Браузер жертвы своими руками декодирует данные из HTML-страницы, собирает из них бинарный блоб в памяти и инициирует диалог “сохранить файл”.

SEG этого момента не видит — он уже давно сделал своё дело и пропустил письмо дальше.

Sandbox? Песочница видит, что страница отрендерилась, что-то там скриптом сделала. Если пейлоад запускается с задержкой на 8 секунд, а сессия sandbox живёт 5, детонация закончится верди­ктом “чисто”. Это не гипотеза, это стандартный приём.

AMSI? AMSI сканирует PowerShell, VBScript, JScript через Windows Script Host. Браузерный JavaScript в Chrome или Edge через AMSI не проходит. Его никто не сканирует на уровне скрипт-движка.

Короче говоря, стандартный стек защит имеет слепую зону прямо в середине. И HTML smuggling заточен под эту зону.

Что там внутри этого HTML на самом деле

Разберём концептуально:

 Взять большую строку base64. Декодировать её в массив байт. Создать Blob, получить blob-URL, подсунуть <download> и кликнуть.

И всё. Это полностью легальные возможности браузера — те же, которые использует Gmail, когда вы “скачиваете” письмо в .eml, или Google Docs, когда вы экспортируете документ. Никаких эксплойтов, никаких уязвимостей. Всё по стандарту HTML5.

Ключевые API, которые участвуют в цепочке:

  • atob() — декодирует base64 в строку байт.

  • Uint8Array.from(...) — превращает строку в массив байт.

  • new Blob([...], { type: '...' }) — создаёт файловый объект в памяти.

  • URL.createObjectURL(blob) — получает blob:-ссылку на этот объект.

  • <a href="blob:..." download="filename.zip"> + .click() — запускает диалог сохранения.

И вариант для старых сред — window.navigator.msSaveOrOpenBlob(blob, name). Это уже legacy, но в корпоративных сетях legacy живёт долго.

Никаких внешних запросов. Payload целиком зашит в HTML-файле. Это значит — URL-фильтры не помогают, блокировка доменов не помогает, TLS-инспекция не видит ничего подозрительного.

Обфускация — второй слой, который обходит сигнатуры

Если бы атакующие клали base64-блоб как есть — его бы давно научились ловить все SEG мира. Поэтому поверх базовой схемы всегда есть обфускация. Концептуально — вот что встречается:

  • Вложенные декодеры. atob(atob(atob(...))) — три слоя кодирования, поверх ещё и XOR с константным ключом.

  • Разбиение блоба на куски. Одна большая строка режется на сотни маленьких, склеивается в массив, потом конкатенируется перед декодированием. Это ломает сигнатуры, которые ищут длинные непрерывные base64.

  • String.fromCharCode по массиву чисел. Payload пересобирается побайтово из JavaScript-массива.

  • document.write(atob(...)). Весь HTML-документ переписывается декодированным контентом уже в рантайме. Исходник в письме — маленький и невинный.

  • Задержка через setTimeout. 5–10 секунд — достаточно, чтобы пережить детонацию в sandbox.

  • Коммерческие обфускаторы JavaScript. Имена переменных в _0xABCD, строки зашифрованы, поток управления размазан.

Исследователи из xorlab в своё время замеряли: document.write встречается в 39% вредоносных HTML-вложений против 0,3% в легитимных. Декодирующие функции (atob, unescape, String.fromCharCode) — 26% против 2%. Цифры старые, но направление не поменялось: это статистически аномальный код для нормальной корпоративной переписки.

Вот этот дисбаланс — и есть точка опоры для детекта.

SVG та же идея, только “картинка”

Про SVG надо сказать отдельно. Потому что SVG это XML, а не бинарник. И по стандарту W3C внутри SVG можно класть <script>. То есть SVG-файл одновременно является и “картинкой”, и страницей с JavaScript.

Для SEG это катастрофа. Потому что SVG исторически классифицируется как графический формат. Многие шлюзы его вообще не сканируют на предмет JS зачем, это же картинка. А когда сотрудник открывает .svg двойным кликом, Windows по умолчанию отдаёт его браузеру. Браузер исполняет <script>. Дальше та же схема с Blob.

В декабре 2023 через SVG ездил Agent Tesla, ходил XWorm. KnowBe4 зафиксировал рост использования SVG в фишинге на 245% за 2024 год. Mimecast добавил специальный “HTML Attachment Deep Scanning” только в декабре 2023, то есть больше года после того, как техника пошла в массовое использование.

Вывод простой и неприятный: .svg во входящей почте это не картинка. Это потенциальная программа. И обращаться с ней надо как с .html.

Три кейса из реального мира

Чтобы не звучало как теория, вот три кампании, где это всё работало на продакшене.

NOBELIUM и EnvyScout (2021)

Май 2021 года. Группа, стоящая за SolarWinds, рассылает фишинг через Constant Contact — легальный сервис email-маркетинга. Цель — дипломатические миссии, госструктуры, НКО. Примерно 3000 аккаунтов в 150 организациях.

Письма прошли SPF, DKIM и DMARC. Потому что они действительно отправлены через Constant Contact у него нормальные подписи. Вложение — HTML-файл NV.html (позже получил имя EnvyScout). Внутри большой base64-блоб, JavaScript, сборка ISO в памяти, предложение сохранить.

ISO содержал LNK, PDF-приманку и NativeZone кастомный Cobalt Strike loader. Цепочка выглядела так: EnvyScout → BoomBox → NativeZone → VaporRage.

Microsoft разобрал кампанию подробно. Важный вывод: все галочки почтового антиспама были зелёными. SPF/DKIM/DMARC не гарантия безопасности. Это гарантия, что письмо действительно пришло оттуда, откуда заявлено. А там может быть что угодно.

Qakbot после похорон макросов (2022–2023)

В 2022 году Microsoft наконец сделал то, что все хотели десять лет заблокировал макросы Office по умолчанию в файлах из интернета. Операторы Qakbot за две недели мигрировали на HTML smuggling.

Новая цепочка: HTML-вложение → запароленный ZIP (пароль в теле письма) → ISO → LNK → regsvr32 с вредоносной DLL → Qakbot DLL уже в памяти процесса.

Пароль в теле письма это не “для защиты пользователя”. Это чтобы SEG не смог распаковать архив для сканирования. Антивирус утыкается в пароль архив для него чёрный ящик. Сотрудник же читает пароль глазами и вводит руками.

Отдельный трюк Qakbot thread hijacking. На зараженных машинах троян воровал целые email-треды с Outlook. Потом рассылал фишинг как ответ в уже существующей переписке. Вы переписываетесь с бухгалтером контрагента неделю, он присылает вам вложение. Вложение — HTML. Доверие максимальное, подозрения минимальные.

IcedID и тот же приём

IcedID (он же Bokbot) банкер, который превратился в дроппер для ransomware-бригад. Использовал ровно ту же схему: thread hijacking + HTML smuggling + ZIP/ISO. В 2022–2023 годах IcedID и Qakbot шли параллельно, сменяя друг друга в кампаниях доступа для Conti, BlackBasta и Royal.

Паттерн один и тот же. И он работает до сих пор уже в исполнении тех, кто занял нишу после операции по ликвидации Qakbot в августе 2023 года.

Что искать: структурные индикаторы в HTML

Перейдём к практике blue team. Если у вас есть возможность сканировать HTML-вложения статически (YARA на SEG, ClamAV-правила, собственный парсер в Sublime/PMail) вот на что смотреть.

Почти точно вредоносно:

  • Строка base64 длиной больше 10 КБ в одной переменной. Легитимные HTML-письма такого практически не содержат. Исключения: встроенные картинки как data:image/..., и они детектируются по MIME-префиксу.

  • atob() в одной цепочке с new Blob( и createObjectURL(.

  • eval(atob(...)) или document.write(atob(...)).

  • a.download = ... + a.click() без пользовательского клика.

  • msSaveOrOpenBlob — часто встречается практически в смуглинге, легитимный веб его не использует.

  • setTimeout на несколько секунд перед созданием Blob-а.

Подозрительно:

  • Вложенные декодеры (atob(atob(...)), unescape(unescape(...))).

  • Пустой <body> + жирный <script> в <head>.

  • MIME-тип в Blob: application/octet-stream, application/zip, application/x-msdownload.

  • Большие JavaScript-массивы из чисел ([77, 90, 144, ...]), потом String.fromCharCode.apply.

  • Классический javascript-obfuscator: имена _0x..., строки через индекс массива.

YARA-правило для базового случая будет выглядеть примерно так:

rule HTML_Smuggling_Blob_Auto_Download {    meta:        description = "HTML attachment with auto-download via Blob API"        mitre = "T1027.006"    strings:        $atob        = "atob(" nocase        $blob        = "new Blob(" nocase        $createObj   = "createObjectURL" nocase        $download    = ".download" nocase        $click       = ".click()" nocase        $msblob      = "msSaveOrOpenBlob" nocase        $big_b64     = /[A-Za-z0-9+\/]{1000,}={0,2}/        $html_marker = "<html" nocase    condition:        $html_marker and $big_b64 and        (            ($atob and $blob and $createObj and $download and $click) or            ($atob and $msblob)        )}

Это не серебряная пуля. Но на практике такое правило ловит базовые варианты, а более обфусцированные образцы всё равно оставляют часть следов — их ловит следующий слой, behavior-детект.

Что искать на endpoint: поведенческие индикаторы

Самое надёжное место для детекта это не почтовый шлюз, а рабочая станция. Потому что после HTML smuggling всегда идёт файловая активность, а она видна в Sysmon и в EDR.

Sysmon Event ID 15 Zone.Identifier на созданных файлах. Ключевое поле содержимое Zone.Identifier. Ищем:

  • HostUrl=about:internet — редкий и подозрительный. Нормальная загрузка из интернета пишет реальный URL.

  • HostUrl=blob:... — практически всегда HTML smuggling.

Этот индикатор подробно описал SecurityJosh ещё в январе 2021. Работает до сих пор.

Sigma-правило:

title: HTML Smuggling via Blob URI - Zone.Identifierstatus: stabledescription: File downloaded with blob URI or about:internet host urllogsource:    product: windows    category: file_eventdetection:    selection:        TargetFilename|endswith: ':Zone.Identifier'        Contents|contains:            - 'HostUrl=about:internet'            - 'HostUrl=blob:'    condition: selectionfalsepositives:    - Некоторые расширения браузераlevel: mediumtags:    - attack.defense_evasion    - attack.t1027.006

Sysmon Event ID 11 браузер создал архив/образ. Корреляция: процесс с именем chrome.exe, msedge.exe, firefox.exe создаёт файл с расширением .zip, .iso, .img, .vhd, .vhdx в Downloads или %TEMP%. Само по себе это не 100% атака — так же скачивают легитимные дистрибутивы. Но в связке с другими индикаторами в том же процессе высокая достоверность.

Цепочка “браузер → ZIP → ISO → монтирование → запуск”. Это практически уникальный поведенческий паттерн, который детально расписал Micah Babinski. Если у вас в EDR есть корреляционный язык правило простое:

  1. Браузерный процесс создал ZIP/RAR.

  2. explorer.exe извлёк из него ISO/IMG.

  3. explorer.exe смонтировал образ (появляется новая буква диска).

  4. Из точки монтирования запустился процесс — cmd.exe, wscript.exe, rundll32.exe, regsvr32.exe, или даже легитимный подписанный EXE (для DLL sideloading).

Все четыре события на одном хосте за 30 минут это практически гарантированная компрометация.

Что закрывать на уровне конфигурации

Если бюджет на детекты ограничен начните с превентивных мер. Они проще и часто эффективнее.

1. Transport Rule в Exchange Online, который блокирует .html, .htm, .svg во вложениях.

Да, это агрессивно. Да, кто-то пожалуется — “мне присылали отчёт в HTML”. Но честно: сколько раз за квартал к вам в легитимной почте приходит HTML-вложение? У большинства организаций ноль. Правило ничего не ломает, зато отрезает целый класс атак в один клик.

Пример на PowerShell:

New-TransportRule -Name "Block HTML and SVG Attachments" `    -AttachmentExtensionMatchesWords "html","htm","shtml","svg","svgz" `    -RejectMessageReasonText "HTML/SVG вложения заблокированы политикой безопасности. Обратитесь в IT." `    -RejectMessageEnhancedStatusCode 5.7.1

Инструкция полностью в документации Microsoft.

2. ASR-правило “Block JavaScript or VBScript from launching downloaded executable content”.

GUID: D3E037E1-3EB8-44C8-A917-57927947596D. Это правило из Defender for Endpoint оно блокирует запуск исполняемых файлов, запущенных из JS/VBScript, которые сами пришли из интернета. Режимы Audit и Enforce. Начните с Audit, посмотрите на фолсы (обычно их нет), включите Enforce.

Гайд по раскатке через Intune/GPO — у Microsoft.

3. Блокировка монтирования ISO/IMG/VHD рядовым пользователям.

Через GPO можно запретить двойной клик по .iso/.img для обычных пользователей ассоциация файла снимается. Админам оставить, остальным нет. Это закрывает целый класс атак с контейнерами разом. Подробно в гайде Huntress.

Что говорить сотрудникам на awareness-тренинге

Это самое короткое и самое важное. В голове у сотрудника должен осесть примерно такой список.

.html во вложении это не документ. Это программа. Если у вас нет конкретной причины ждать HTML-файл не открывайте. Вообще. Если есть подозрение отправьте в ИБ, пусть разбираются.

.svg то же самое. Несмотря на иконку картинки. Внутри может быть JavaScript, который сделает всё, что сделает HTML.

Архив с паролем, где пароль указан прямо в письме это красный флаг, а не забота о безопасности. Пароль там не для вас. Пароль там для того, чтобы антивирус не смог проверить содержимое. Если прислали запароленный архив — зовите ИБ.

Если после открытия вложения у вас в системе “появился диск” (новая буква, Explorer открыл окно флешки) это атака. Немедленно отключитесь от сети и зовите ИБ. ISO или IMG, смонтированный из почтового вложения сценарий Qakbot, IcedID и десятка других троянов.

Ответ на ваш собственный рабочий тред не индульгенция. Если вы неделю переписываетесь с контрагентом и вдруг в треде прилетает вложение, которого вы не ждали — осторожнее. Thread hijacking работает именно на том, что вы привыкли доверять этому треду.

Зелёные галочки антиспама не значат ничего. SPF/DKIM/DMARC это про “оно действительно оттуда, откуда сказано”. Не про “оно безопасно”. NOBELIUM слал фишинг через Constant Contact с идеальными подписями. Qakbot рассылал через реальные взломанные корпоративные ящики — там тоже всё зелёное.

Короткое замечание напоследок

HTML smuggling не про уязвимости. Там нет zero-day. Там нет эксплойтов браузера. Это про то, что стандартные, документированные возможности веб-платформы используют в комбинации, на которую почтовые шлюзы архитектурно не рассчитаны.

Это значит две вещи. Первая — техника не “пофиксится” патчем. Браузерам Blob API и <a download> нужны для нормальной работы Gmail, Jira, Confluence, Google Drive и сотен других сервисов. Никто это не уберёт. Вторая — защита строится не на одном продукте, а на наложенных слоях: политика на SEG, ASR на endpoint, поведенческий детект в SIEM, awareness у пользователей. Каждый слой пропускает часть атак. Вместе ловят большинство.

Если у вас в компании ещё нет Transport Rule на блокировку HTML-вложений, то поставьте его сегодня. Пять минут работы. Это, пожалуй, самый высокий ROI из всех защитных мер, которые есть в 2026 году в корпоративной почте.


Полезные ссылки

ссылка на оригинал статьи https://habr.com/ru/articles/1027556/