SVG как оружие: почему безобидная картинка может взломать сайт

Коротко. SVG - это не набор пикселей, а текстовый XML-документ, и внутри него может оказаться активный код. В 2025 году доля SVG во вложениях фишинговых писем выросла с 0,1% до 4,9%, в марте доходила до 15% (Hoxhunt). В статье разбираем, как SVG используют для XSS, фишинга и атак на серверные парсеры, и какие 6 мер закрывают этот риск на сайте.
Когда речь заходит о безопасности сайта, обычно вспоминают пароли, SQL-инъекции и DDoS. Про обычные картинки в формате SVG думают реже, хотя этот формат дизайнеры и верстальщики используют каждый день для иконок и логотипов. При неправильной обработке он становится каналом для XSS, фишинга и кражи данных.
Чем SVG отличается от JPG и PNG
JPG и PNG - это сетка пикселей с цветовыми значениями. Кроме цвета, браузеру из такого файла прочитать нечего.
SVG устроен иначе. Это текстовый XML-документ, который описывает графику через фигуры, линии и текст, а браузер интерпретирует эту разметку при каждом показе. Логотип в SVG - это, по сути, несколько строк кода: прямоугольник такого-то размера, круг такого-то цвета, надпись таким-то шрифтом.
Раз это документ, а не пиксели, в него можно вложить не только фигуры, но и элементы, которые браузер исполняет.
| JPG / PNG | SVG | |
|---|---|---|
| Что внутри | пиксели | текстовая XML-разметка |
| Может содержать скрипты | нет | да |
| Может содержать HTML и формы | нет | да, через <foreignObject>
|
| Обрабатывается XML-парсером на сервере | нет | да, при конвертации и генерации превью |
Как SVG превращается в атаку
Встроенный JavaScript
Стандарт SVG поддерживает собственный тег <script> и обработчики событий вроде onload. Выполнится ли код, зависит от способа подключения файла:
-
через
<img>или CSSbackground-image- современные браузеры скрипты внутри SVG не выполняют; -
при открытии файла напрямую по ссылке, через
<object>,<embed>,<iframe>или inline-вставке в HTML - выполняют.
Главный риск - SVG, загруженный пользователем на ваш же домен: аватар, логотип компании в личном кабинете, вложение в форме. Если такой файл открыть по прямой ссылке, скрипт выполнится в контексте вашего сайта. Это хранимая XSS: код может отправлять запросы от имени пользователя, читать данные страницы и cookie без флага HttpOnly.
HTML и формы через <foreignObject>
Тег <foreignObject> позволяет встроить в SVG произвольный HTML, в том числе форму ввода логина и пароля. Пользователь думает, что открыл документ, и вводит данные, а они уходят злоумышленнику.
Автоматические редиректы
Скрипт в SVG может сработать сразу при открытии файла и перенаправить браузер на фишинговую страницу или загрузчик вредоносного ПО. Сам SVG при этом может быть пустым - пользователь не видит ничего подозрительного.
Атаки на XML-парсер на сервере: XXE
SVG - полноценный XML и поддерживает DOCTYPE с объявлением сущностей. Если сайт обрабатывает загруженные SVG на сервере (генерирует превью, конвертирует в PNG или PDF) уязвимой библиотекой, злоумышленник может заставить сервер прочитать локальный файл или обратиться к внутреннему ресурсу. Это атака XXE (XML External Entity).
XSLT-преобразования
SVG может ссылаться на XSL-таблицу стилей, которая превращает документ в HTML со своим кодом при открытии файла напрямую. Этот вектор сужается: Chrome отключает XSLT начиная с версии 158 (17 ноября 2026), о планах удалить его сообщили также Firefox и WebKit. До обновления браузеров у пользователей вектор остается рабочим.
Обход фильтров через нестандартную разметку
Отдельный SVG-файл браузер разбирает как строгий XML. Но SVG, вставленный inline в HTML-страницу, разбирается HTML-парсером, который прощает пропущенные кавычки и незакрытые теги. Поэтому фильтры на регулярных выражениях для «отлова» опасных конструкций ненадежны: одну и ту же конструкцию можно записать десятками способов. Чистить SVG нужно парсером и белым списком разрешенных элементов, а не поиском по строке.
Реальные атаки через SVG
| Когда | Что произошло | Источник |
|---|---|---|
| Декабрь 2022 | Фишинг с вредоносом Qakbot: HTML-вложение со встроенным SVG, скрипт которого собирал ZIP-архив прямо на компьютере жертвы. Файл не передавался по сети, поэтому почтовые фильтры его не видели | Cisco Talos |
| Январь 2023 | Атака «Blank Image»: письмо от имени DocuSign, во вложении HTML с пустой SVG-картинкой в base64, скрипт внутри перенаправлял на фишинговый сайт | Avanan (Check Point) |
| Ноябрь 2024 | SVG-вложения, которые показывали имитацию таблицы Excel со встроенной формой входа | BleepingComputer |
| 2024-2025 | Доля SVG среди вредоносных вложений в письмах: 0,1% в 2024 году, 4,9% в первом полугодии 2025, пик около 15% в марте 2025 | Hoxhunt, отчеты 3 млн пользователей |
SVG удобен атакующим, потому что многие почтовые шлюзы по умолчанию считают его картинкой и не разбирают содержимое так тщательно, как исполняемые файлы или офисные документы с макросами.
Когда это касается вашего сайта
Риск реальный, если на сайте есть хотя бы одно из этого:
- пользователи загружают аватары, логотипы или вложения, и среди разрешенных форматов есть SVG;
- сайт принимает файлы через формы обратной связи, личный кабинет или медиатеку CMS;
- SVG-иконки вставляются в шаблон inline, а их источник - не только ваши разработчики (например, их может загрузить контент-менеджер);
- на сайте стоит плагин, который включает загрузку SVG. WordPress по умолчанию запрещает загружать SVG именно из-за этих рисков, и плагины вроде «разрешить SVG» снимают это ограничение.
Если SVG на сайте только ваши собственные иконки из верстки, а загрузки SVG от пользователей нет, риск минимальный.
Проверим, как ваш сайт обрабатывает файлы
Посмотрим, какие форматы принимают формы и CMS, как отдаются загруженные файлы, настроены ли заголовки безопасности. Найденные уязвимости закроем в рамках технической поддержки.
Как защитить сайт от SVG-атак
- Не принимать SVG, если он не нужен. Для аватаров и фото в формах достаточно JPG, PNG и WebP. Самая надежная защита - убрать SVG из списка разрешенных форматов.
-
Санитизация на сервере. Если SVG нужен, каждый загруженный файл очищается по белому списку: удаляются
<script>, обработчикиon*,<foreignObject>, внешние ссылки и DOCTYPE. Для PHP есть библиотека enshrined/svg-sanitize (на ней работает плагин Safe SVG для WordPress), для JavaScript - DOMPurify, которая работает и в браузере, и на сервере в Node.js. -
Правильные заголовки при отдаче файлов. Пользовательские SVG отдаются с
Content-Security-Policy: script-src 'none',X-Content-Type-Options: nosniffи, если файл не нужно показывать в браузере,Content-Disposition: attachment. В теге<img>такая картинка продолжит отображаться, а при прямом открытии код не выполнится. - Строгий Content-Security-Policy на сайте. Запрет inline-скриптов и загрузки ресурсов с посторонних доменов снижает ущерб, даже если инъекция прошла.
- Отдельный домен для пользовательских файлов. Загрузки хранятся и отдаются с отдельного домена (не поддомена основного сайта) без доступа к cookie. Даже если скрипт выполнится, он не получит доступа к сессии пользователя на основном сайте.
- Конвертация в растр и безопасный парсер. Если векторность не нужна, SVG конвертируется в PNG на сервере и весь код отбрасывается. Библиотека, которая это делает, должна быть обновлена и настроена без загрузки внешних сущностей - это защита от XXE.
Для большинства сайтов малого бизнеса хватает первого пункта плюс заголовков из третьего. Санитизация и отдельный домен нужны там, где SVG от пользователей - часть продукта: конструкторы, маркетплейсы, сервисы с загрузкой логотипов.
SVG - хороший формат для верстки, отказываться от него не нужно. Но относиться к нему стоит как к любому пользовательскому вводу, а не как к «просто картинке».



