PixelSmash:一个50KB的视频文件,如何让全球数百万服务器沦陷?

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

文章总结: PixelSmash是FFmpegMagicYUV解码器中的高危漏洞(CVE-2026-8461),攻击者通过50KB恶意视频文件可在Jellyfin、Nextcloud等媒体服务器实现远程代码执行。漏洞根因为色度平面行数计算不一致导致堆越界写入,进而劫持AVBuffer函数指针。建议立即升级FFmpeg或禁用MagicYUV解码器。 综合评分: 87 文章分类: 漏洞分析,WEB安全,应用安全,供应链安全,云安全


cover_image

PixelSmash:一个50KB的视频文件,如何让全球数百万服务器沦陷?

原创

利刃信安 利刃信安

利刃信安

2026年6月24日 10:30 北京

在小说阅读器读本章

去阅读

PixelSmash:一个50KB的视频文件,如何让全球数百万服务器沦陷?

摘要:2026年6月,JFrog安全研究团队披露了一个名为 PixelSmash(CVE-2026-8461,CVSS 8.8)的FFmpeg高危漏洞。攻击者只需上传一个精心构造的50KB AVI视频文件,即可在Jellyfin、Nextcloud等媒体服务器上实现远程代码执行,Kodi、mpv、OBS等桌面应用亦受波及导致崩溃。漏洞根因是MagicYUV解码器中一个看似微小的取整误差——帧分配器与解码器对色度平面行数的计算不一致,导致堆越界写入,进而劫持AVBuffer函数指针执行任意系统命令。


一、一个解码器Bug,打穿整个媒体生态

FFmpeg是全球部署最广泛的媒体处理框架。从桌面播放器(mpv、VLC)、自建媒体服务器(Jellyfin、Emby),到云转码管线(AWS MediaConvert)、Linux桌面环境(GNOME缩略图生成器),几乎所有涉及视频处理的应用都链接了FFmpeg的 libavcodec

PixelSmash正是寄生在libavcodec的MagicYUV解码器中的一个堆越界写入漏洞。MagicYUV是一个面向高性能视频剪辑工作流的无损编码器,虽然不如H.264知名,但它的解码器默认编译进每一个FFmpeg构建,注册在AVI、MKV、MOV三种容器格式下。这意味着,任何能打开视频文件的应用,都可能触发这个解码器。

这是一起典型的软件供应链安全事件:一个底层依赖库中某个冷门编解码器的Bug,通过依赖链向上传播,波及数百个下游项目。Jellyfin、mpv、Nextcloud、Immich、OBS、vLLM等项目没有引入这个Bug,却因为依赖FFmpeg而被迫继承——且绝大多数项目缺乏独立检测或缓解该漏洞的能力。

受影响的不仅限于服务器

| 场景 | 触发方式 | | — | — | | 桌面端 | 用户打开恶意视频文件,或仅浏览到包含该文件的文件夹(缩略图生成器即触发) | | 服务端 | 上传恶意文件至Jellyfin、Nextcloud、Discord等平台的媒体处理管线 | | 嵌入式/IoT | NAS设备(群晖、QNAP)、智能电视等自动生成视频缩略图的场景 |

无需认证、无需特权、无需预先访问——只需要交付一个媒体文件。


二、根因分析:差一行导致的堆溢出

2.1 背景知识:Slice与YUV色彩空间

在视频压缩中,Slice(切片) 是一帧内水平分割出的独立解码区域。数字视频不使用标准RGB,而是采用 YUV色彩空间

  • • Y(亮度平面):图像的明暗细节,人眼对此极其敏感;
  • • U/V(色度平面):颜色信息,人眼对色度细节的敏感度远低于亮度。

在YUV420P等亚采样格式下,色度平面的垂直分辨率是亮度平面的一半。解码器需要将亮度行的Slice高度转换为色度行高度——这里用到了向上取整的右移运算AV_CEIL_RSHIFT)。

而这个看似合理的取整,正是漏洞的根源。

2.2 致命的不一致

问题出在两个计算之间的分歧:

第一步:帧分配器计算色度缓冲区大小

// update_frame_pool (get_buffer.c)
allocated chroma rows = AV_CEIL_RSHIFT(FFALIGN(32, 32), 1) = 16

色度缓冲区只分配了 16行

第二步:解码器从攻击者控制的比特流中读取slice_height

s->slice_height = bytestream2_get_le32u(&gb); // 攻击者填入 31

当 slice_height = 31coded_height = 32 时:

nb_slices = (32 + 31 - 1) / 31 = 2;          // 2个切片
int sheight = AV_CEIL_RSHIFT(31, 1) = 16;     // 每个切片占用16色度行

第二个切片的目标地址:

dst = p->data[1] + 1 * 16 * stride;  // 写入第16行(缓冲区只有0-15行!)

色度缓冲区只有行0-15(共16行),解码器却向第16行写入攻击者控制的数据——整行越界。

2.3 为什么校验没拦住?

现有校验代码(magicyuv.c:566-568)仅覆盖了隔行扫描模式

if (s->interlaced) {
&nbsp; &nbsp;&nbsp;if&nbsp;((s->slice_height >> s->vshift[1]) <&nbsp;2)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 仅隔行模式才有此校验
}

非隔行模式——也就是我们利用的路径——完全没有对齐检查。补丁仅需7行代码即可修复。


三、从堆溢出到远程代码执行

堆溢出本身能造成拒绝服务(DoS),但JFrog研究团队将其升级为可靠的任意命令执行

3.1 攻击目标:AVBuffer结构体

FFmpeg的堆布局中,每个平面的像素数据之后紧邻着 AVBuffer——引用计数的缓冲区管理结构。当FFmpeg完成一帧解码后,调用 av_frame_unref → av_buffer_unref,引用计数归零时触发:

buf->free(buf->opaque, buf->data); &nbsp;// 通过堆上的函数指针间接调用

这是一个间接调用。如果能覆盖 buf->free 为 libc 的 system() 地址、buf->opaque 为shell命令字符串指针,那么:

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

3.2 精确堆布局

640字节的越界写入恰好落在Cb色度平面的AVBuffer上(Jellyfin捆绑的jellyfin-ffmpeg 7.1.3):

OOB + 0: &nbsp; [88字节零值 —— 命令字符串槽位]
OOB + 88: &nbsp;[glibc堆块头部 —— 必须原样保留]
OOB + 256: AVBuffer结构体:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.data &nbsp; &nbsp; = Cb数据指针
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.size &nbsp; &nbsp; = 0x284f
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.refcount = 1 &nbsp; &nbsp; &nbsp; &nbsp;← 写入1,令引用计数归零
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.free &nbsp; &nbsp; = &system &nbsp;← 覆盖为system地址
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.opaque &nbsp; = &cmd &nbsp; &nbsp; ← 覆盖为命令字符串地址

当帧清理流程触发 av_buffer_unref 时,间接调用变成 system("攻击者命令")。fork出的shell子进程在执行命令后,父进程才因后续堆损坏崩溃——但攻击已经完成。

3.3 三个工程难题

  1. 1. 堆布局校准:利用GDB自动捕获越界前的精确堆状态,提取所有堆块元数据,生成”外科手术级”的利用文件。
  2. 2. 保留glibc堆完整性:640字节越界区域内包含33个glibc堆块头部(空闲链表指针、块大小、PREV_INUSE标志),任何一个损坏都会触发glibc完整性检查导致进程终止,必须逐字节原样保留。
  3. 3. Cr平面越界保护:Cr色度平面同样存在越界写入,其越界区域包含tcache条目和glibc top chunk,top chunk大小若被破坏,system()内部的fork()/exec()会失败,因此必须编码保留Cr平面的堆元数据。

四、真实攻击演示:Jellyfin服务器沦陷

JFrog团队在 Jellyfin 10.11.9(仅次于Plex的第二大自建媒体服务器)上实现了完整的远程代码执行:

已关注

关注

重播 分享 赞

关闭

观看更多

更多

退出全屏

切换到竖屏全屏退出全屏

利刃信安已关注

分享视频

,时长00:52

0/0

00:00/00:52

切换到横屏模式

继续播放

[ ]

进度条,百分之0

播放

00:00

/

00:52

00:52

倍速

全屏

倍速播放中

0.5倍 0.75倍 1.0倍 1.5倍 2.0倍

超清 流畅

 您的浏览器不支持 video 标签

继续观看

PixelSmash:一个50KB的视频文件,如何让全球数百万服务器沦陷?

观看更多

原创

,

PixelSmash:一个50KB的视频文件,如何让全球数百万服务器沦陷?

利刃信安已关注

分享点赞在看

已同步到看一看写下你的评论

视频详情

  • • 攻击路径:通过Jellyfin的媒体库自动扫描功能,上传一个50KB的恶意AVI文件;
  • • 结果:Jellyfin后台FFmpeg进程自动解码该文件 → 触发越界写入 → 劫持AVBuffer → 执行反向Shell命令;
  • • Nextcloud 上同样验证了通过视频预览提供者的RCE攻击。

关于ASLR的说明:演示中关闭了ASLR。在默认启用ASLR的环境下,由于需要硬编码system()地址,该利用无法直接落地。研究团队同时发现FFmpeg的FlashSV解码器存在一个未初始化堆内存泄露(自2022年7月存在至今),理论上可配合PixelSmash绕过ASLR,但完整链路尚未演示。


五、检测与修复

检测是否受影响

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

若输出包含 VFS..D magicyuv,说明你的FFmpeg构建存在漏洞。MagicYUV解码器在所有主流发行版(Ubuntu、Debian、Fedora、Arch、Alpine)的FFmpeg包中默认启用。

修复方案一:升级

升级至FFmpeg官方修复版本。

修复方案二:禁用解码器

./configure --disable-decoder=magicyuv [其他参数]
make && make install

修复方案三:最小补丁

在 libavcodec/magicyuv.c 中增加7行校验,拒绝非法的 slice_height 值。正常MagicYUV编码器始终产生对齐的Slice高度,此补丁仅拦截恶意输入。


六、结语

PixelSmash再次印证了一个安全铁律:底层基础设施中一行代码的疏忽,足以摧毁整个上层应用生态的安全假设。 FFmpeg作为互联网媒体处理的基石,其代码质量直接影响数亿终端和百万服务器的安全边界。

对于安全从业者,这个案例提醒我们关注四件事:供应链依赖中冷门组件的攻击面、编解码器解析外部输入路径的覆盖度、堆元数据在利用中的关键角色、以及纵深防御中ASLR等缓解措施的实际价值。

对于运维和开发者,一句话建议:检查你的FFmpeg版本,立刻升级。


参考来源:JFrog Blog – PixelSmash: Critical FFmpeg Vulnerability Turns Media Files into Weapons[1]

引用链接

[1] JFrog Blog – PixelSmash: Critical FFmpeg Vulnerability Turns Media Files into Weapons: https://jfrog.com/blog/pixelsmash-critical-ffmpeg-vulnerability-turns-media-files-into-weapons/


免责声明:

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

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

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

本文转载自:利刃信安 利刃信安 利刃信安《PixelSmash:一个50KB的视频文件,如何让全球数百万服务器沦陷?》

评论:0   参与:  0