Статья FFmpeg PixelSmash (CVE-2026-8461): от крафтованного AVI до reverse shell на медиасервере

Плата NAS-накопителя крупным планом на чёрном антистатическом коврике: выжженный чип декодера с вздувшимся конденсатором, надпись CVE-2026-8461 на дорожках. Экран диагностики светится белым с пурпу...


Файл на 50 КБ в формате AVI, загруженный в медиатеку Jellyfin 10.11.9, запускает reverse shell от имени сервисного пользователя. Без аутентификации. Без единого клика админа. Просто файл попал в папку - и всё.

Heap out-of-bounds write в декодере MagicYUV, CVSS 8.8 HIGH, вектор AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H. Одна ошибка в расчёте высоты chroma-плоскости - и всё, что автоматически обрабатывает медиафайлы через libavcodec, превращается в поверхность атаки. Ниже - полный разбор корневой причины, цепочки эксплуатации, поверхности атаки и практические шаги для верификации и устранения.

Бизнес-логика атаки: зачем злоумышленнику PixelSmash​

Прежде чем лезть в байты - зачем это атакующему. Подробнее - в нашем статье о cve эксплойт разработка.

Медиасерверы (Jellyfin, Nextcloud, Emby) часто крутятся на NAS-устройствах или VPS с доступом к внутренней сети. Получив шелл от имени сервисного пользователя, атакующий получает точку опоры для латерального движения, доступ к медиатеке (а там нередко валяются корпоративные файлы и бэкапы) и возможность закрепления. Учётные данные не нужны - достаточно доставить малформированный медиафайл туда, где FFmpeg его обработает автоматически.

По MITRE ATT&CK цепочка выглядит так: Exploit Public-Facing Application (T1190, Initial Access) при загрузке на сервер, либо Exploitation for Client Execution (T1203, Execution) на десктопе, далее - Unix Shell (T1059.004, Execution) через перехваченный вызов system().

Корневая причина: рассогласование высоты слайсов в MagicYUV​

MagicYUV - lossless видеокодек, не такой раскрученный как H.264 или VP9, но он скомпилирован в дефолтные upstream-сборки FFmpeg и зарегистрирован для контейнеров AVI, MKV и MOV. По данным JFrog, любое приложение, открывающее файл в этих контейнерах, может маршрутизировать поток к декодеру MagicYUV, если файл декларирует соответствующий кодек.

Видеокадры в MagicYUV хранятся в формате YUV - яркостная плоскость (Y) и две цветовые (U, V). В субдискретизированных форматах типа YUV420P цветовые плоскости имеют вдвое меньшее разрешение по высоте, чем яркостная. Кадр разбивается на горизонтальные слайсы, которые декодируются независимо.

А теперь - суть бага. Аллокатор фреймов и декодер MagicYUV по-разному вычисляют высоту chroma-плоскостей при нечётном значении slice_height, которое контролируется атакующим из битового потока:
Код:
Аллокатор:  coded_height=32, chroma_height=16, буфер: строки 0..15
Декодер:    slice_height=31 (из битстрима), slices=2
            chroma строк/слайс = ceil(31/2) = 16
            Второй слайс: start_row = 1*16 = 16  <- за пределами буфера
Потолочное округление при делении нечётного slice_height на фактор субдискретизации добавляет одну лишнюю chroma-строку на слайс. При двух и более слайсах эти строки накапливаются и выходят за границы выделенного буфера. Результат - запись за пределы кучи (CWE-787, Out-of-bounds Write).

Патч в FFmpeg 8.1.2 добавляет проверку выравнивания slice_height относительно вертикальной субдискретизации chroma, отклоняя некорректные значения на этапе разбора.

Баг выглядит тривиально - одна пропущенная проверка границ. Но такие проверки охраняют trust-границы: любой путь, по которому недоверенный MagicYUV-поток попадает к декодеру, становится вектором атаки.

Цепочка эксплуатации: от heap overflow до вызова system()​

1784271586810.webp

Место в цепочке атаки​

Полный kill chain:
  1. Delivery - атакующий формирует малформированный MagicYUV-файл в контейнере AVI/MKV/MOV (~50 КБ)
  2. Initial Access (T1190) - файл загружается на медиасервер, попадает в папку медиатеки через торрент, или открывается через генератор миниатюр
  3. Execution (T1203) - FFmpeg/ffprobe автоматически декодирует файл, срабатывает OOB write
  4. Post-exploitation - reverse shell, загрузка инструментов (T1105, Ingress Tool Transfer), закрепление

Перехват AVBuffer.free​

В FFmpeg после каждого блока пиксельных данных плоскости в куче размещается объект AVBuffer - структура управления буфером с подсчётом ссылок. Одно из её полей - указатель на функцию free(), вызываемую при освобождении буфера. Запись за границы chroma-буфера попадает на соседний AVBuffer и перезаписывает этот указатель.

По данным JFrog, продемонстрированная цепочка эксплуатации работает так: NUL-терминированная shell-команда размещается по определённому OOB-смещению, указатель AVBuffer.free перенаправляется на адрес system(), и при последующем освобождении буфера команда атакующего выполняется. Шелл срабатывает до того, как процесс FFmpeg упадёт на последующем повреждении кучи.

Красиво, но есть нюансы.

Ограничения: ASLR и реальная модель угроз​

Без оговорок картина будет неполной:
  • ASLR - главный барьер. Для надёжного RCE нужно знать адрес system() в памяти. На системах с включённым ASLR (а это все современные дистрибутивы GNU/Linux, macOS, Windows) адресное пространство рандомизировано, и прямой перехват не пройдёт без утечки информации. JFrog подтверждает: их RCE-демонстрация проводилась с отключённым ASLR.
  • Потенциальная цепочка с FlashSV. Исследователи упоминают, что отдельная ошибка раскрытия информации в декодере FlashSV в FFmpeg теоретически может быть использована в цепочке с PixelSmash для обхода ASLR. Деталей и публичного PoC для этой цепочки на момент написания нет.
  • DoS - надёжен всегда. Даже когда RCE невозможно, OOB write гарантированно роняет процесс FFmpeg. На серверах с автоматической обработкой это означает отказ в обслуживании медиасервиса.
  • EPSS = 0.0048 (перцентиль 0.38). По данным FIRST.org, вероятность эксплуатации в течение 30 дней ниже медианы. CISA SSVC: exploitation=none, automatable=no, technical impact=total. Подтверждённых случаев эксплуатации в дикой природе на момент написания нет.
Для пентест-отчёта: DoS через PixelSmash - стабильная находка. RCE подтверждается только на системах с отключённым ASLR или при наличии дополнительного info leak. Не завышайте severity без подтверждения условий - это портит репутацию быстрее, чем кажется.

Поверхность атаки: где FFmpeg принимает недоверенный контент​

FFmpeg - не просто утилита для конвертации видео. Это фреймворк из нескольких библиотек, главная из которых - libavcodec с сотнями кодеков. Приложения линкуются к ней напрямую, вызывают ffmpeg/ffprobe через shell, используют обёртки (PyAV, python-ffmpeg) или бандлят кастомные сборки. Когда уязвимый компонент - декодер внутри libavcodec, поверхность атаки следует за зависимостью.

Медиасерверы​

Как это выглядит на практике:
  • Jellyfin - монитор файловой системы обнаруживает новый файл в медиатеке и автоматически запускает сканирование метаданных через ffprobe. Эксплойт предположительно срабатывает во время сканирования - reverse shell от имени сервисного пользователя. Вектор через торрент: файл скачивается прямо в папку медиатеки, нулевое взаимодействие.
  • Nextcloud - при включённом Movie preview provider загрузка видеофайла запускает генерацию миниатюры через системный FFmpeg. Достаточно, чтобы файл отобразился в списке папки.
  • Emby, Immich, PhotoPrism - архитектурно уязвимы, поскольку используют FFmpeg для обработки медиа, но независимое тестирование не подтверждено публично.
Интересный момент: Plex, по имеющимся данным, использует кастомный форк FFmpeg с ограниченным набором декодеров. Если MagicYUV не включён в этот набор, поверхность атаки PixelSmash для них минимальна. Хороший пример того, как минимизация сборки реально уменьшает риск.

NAS-устройства​

Synology и QNAP поставляют FFmpeg в составе медиаиндексаторов. Генерация миниатюр при обзоре файловой системы через веб-интерфейс или мобильное приложение запускает декодирование. На ARM-архитектуре NAS-устройств ASLR-энтропия ниже, чем на x86\_64, что потенциально упрощает брутфорс адресов - но конкретных публичных исследований по этому вектору пока нет.

Десктоп и облако​

Генераторы миниатюр GNOME, KDE, XFCE (через ffmpegthumbnailer) срабатывают при простом открытии папки с малформированным файлом. OBS Studio, Kodi, mpv - потенциально уязвимы, поскольку используют libavcodec с включённым MagicYUV.

Облачные сервисы транскодирования (AWS MediaConvert, Cloudflare Stream) потенциально уязвимы, но JFrog их не тестировал. Мессенджеры Slack, Discord, Telegram, WhatsApp используют FFmpeg для серверных превью видео - тоже не тестировались, но архитектурно вектор есть.

Практическая проверка: определяем уязвимость в инфраструктуре​

1784271749067.webp

Требования к окружению​

  • ОС: любой GNU/Linux-дистрибутив с установленным FFmpeg (Debian, Ubuntu, RHEL, Arch)
  • RAM: достаточно 512 МБ для проверки, 2+ ГБ для воспроизведения в лабе с Jellyfin
  • FFmpeg: уязвимы все версии до 8.1.2 (Debian зафиксировал в DSA-6361-1, пакет ffmpeg 7:7.1.5-0+deb13u1 для trixie)
  • Сеть: offline-проверка возможна, для теста на медиасервере нужен доступ к его интерфейсу

Шаг 1: проверить наличие декодера MagicYUV​

Bash:
ffmpeg -version | head -1          # версия FFmpeg
ffmpeg -decoders 2>/dev/null | grep magicyuv
Если в выводе есть строка с magicyuv и версия ниже 8.1.2 - система уязвима к DoS. Для RCE нужно дополнительно проверить статус ASLR: cat /proc/sys/kernel/randomize_va_space (0 = отключён, 1 = частичный, 2 = полный).

Шаг 2: инвентаризация зависимостей​

PixelSmash - это проблема цепочки поставок. Недостаточно проверить /usr/bin/ffmpeg. Нужно искать все бинари и библиотеки, линкующиеся к libavcodec: ldd /path/to/binary | grep avcodec для динамически слинкованных бинарей. Для каждой найденной копии - ./ffmpeg -decoders 2>/dev/null | grep magicyuv. Это единственный надёжный способ.

Дополнительно: strings /path/to/binary | grep -i magicyuv и find / -name "ffmpeg*" -executable 2>/dev/null с последующим ./ffmpeg -version для каждой найденной копии. Jellyfin, к примеру, поставляет собственный бинарь FFmpeg, который не обновляется через пакетный менеджер дистрибутива. Я на это натыкался не раз - обновляешь системный FFmpeg, а Jellyfin продолжает использовать свой древний.

Шаг 3: оценка достижимости​

Наличие уязвимого декодера != эксплуатируемость. Нужно ответить на вопросы: может ли недоверенный пользователь загрузить медиафайл? Запускается ли автоматическая обработка (генерация превью, сканирование метаданных, транскодирование)? Работает ли процесс FFmpeg с привилегиями, которые представляют интерес?

Сканер уязвимостей типа Nessus обнаружит версию (плагин для CVE-2026-8461 основан на self-reported version), но не ответит на эти вопросы - это ручная работа пентестера.

Детектирование PixelSmash в логах​

Для blue team и SOC-инженеров - что искать:
  • Аварийные завершения ffmpeg/ffprobe с сигналами SIGSEGV или SIGABRT сразу после обращения к файлу. Паттерн: процесс FFmpeg стартует, падает в течение секунд, в coredump виден адрес в районе heap.
  • Аномальные медиафайлы. AVI/MKV/MOV размером менее 100 КБ с кодеком MagicYUV - подозрительны по определению. MagicYUV - lossless кодек для профессионального видеомонтажа. Файл в 50 КБ с этим кодеком в медиатеке домашнего сервера - красный флаг.
  • Повторные краши медиасервисов. Если Jellyfin или аналогичный сервис перезапускается несколько раз подряд после добавления нового контента - возможна попытка эксплуатации (или уже успешная, если между крашами проходил вызов system()).
  • Подозрительные процессы от сервисного пользователя. Reverse shell от пользователя jellyfin или nextcloud - прямой IoC. Мониторьте сетевые соединения от сервисных аккаунтов, которые обычно не инициируют исходящие подключения.

Чеклист устранения CVE-2026-8461​

Формат для передачи сисадмину или включения в пентест-отчёт:
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

PixelSmash вскрыл проблему, которую индустрия предпочитает не замечать: FFmpeg компилируется с сотнями декодеров по умолчанию, и практически никто не собирает его с белым списком. Plex, предположительно, это сделал - и потенциально оказался защищён. Все остальные унаследовали риск молча, через зависимость, которой доверяют безоговорочно.

Одна ошибка в расчёте высоты chroma-слайса - и сотни проектов получают запись за пределы кучи в каждом пайплайне, где обрабатывается недоверенный медиаконтент.

На практике я вижу эту картину постоянно: медиаобработка воспринимается как безопасная операция. "Мы просто генерируем превью" - говорят разработчики, не задумываясь, что за этой генерацией стоит парсинг бинарного потока на C, с ручным управлением памятью, без песочницы. PixelSmash - не аномалия, а закономерный результат. Формула проста: сложный парсер + недоверенный вход + отсутствие изоляции = стабильный поток уязвимостей класса memory corruption.

Вместо того чтобы гнаться за каждым CVE, разумнее менять архитектурный подход. Медиа-парсинг нужно трактовать как десериализацию - никогда не доверять, всегда изолировать, всегда минимизировать поверхность. Собирать FFmpeg с --disable-decoders и явным --enable-decoder= для каждого нужного формата. Запускать обработку в одноразовых контейнерах с seccomp-профилем. Это не параноидальный hardening - это базовая гигиена для любого сервиса, принимающего файлы из внешнего мира.

Проверьте свой медиасервер прямо сейчас: ffmpeg -decoders 2>/dev/null | grep magicyuv. Если строка есть, а версия ниже 8.1.2 - у вас та же проблема, что и у всех.
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🧭 Навигатор · ИБ 2026
Не знаешь, какой трек твой?
5 направлений ИБ, реальные зарплаты и точка входа для каждого — в одном треде.
JuniorSenior+
100K → 600K+ ₽ /мес
Открыть навигатор →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab