一个GET请求拿下服务器:CVE-2026-29058AVideo命令注入漏洞分析

admin 2026-03-18 17:40:09 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档分析了CVE-2026-29058AVideo命令注入漏洞,漏洞位于getImage.php,因URL参数未过滤Shell元字符直接拼接执行,导致未授权攻击者通过GET请求实现RCE。文章从四个层次剖析成因,指出格式校验无法替代安全过滤,并提供了升级至7.0版本、配置访问控制及WAF检测等修复建议,强调开发中应使用escapeshellarg或参数数组调用外部程序。 综合评分: 95 文章分类: 漏洞分析,代码审计,漏洞预警,WEB安全


cover_image

一个 GET 请求拿下服务器:CVE-2026-29058 AVideo 命令注入漏洞分析

原创

CVE-SEC CVE-SEC

CVE-SEC

2026年3月8日 11:00 四川

一个 GET 请求拿下服务器:CVE-2026-29058 AVideo 命令注入漏洞分析

发布日期:2026-03-07 CVE 编号:CVE-2026-29058 CVSS v3.1 评分:9.8(Critical)


背景

AVideo,前身是 YouPHPTube,是一套由 WWBN 开源社区维护、基于 PHP 开发的自托管音视频平台。许多教育机构、企业和独立站点用它搭建私有视频系统,支持视频上传、转码、直播、频道管理等功能。

它的转码组件 AVideo-Encoder 负责调用 ffmpeg 处理视频文件,部署在独立服务器上,对外暴露 HTTP 端点。这个组件在 GitHub 上有 157 个 Star、192 个 Fork,许可证为 AGPL-3.0。

这次出问题的,就是 AVideo-Encoder。


漏洞在哪里

问题出在 objects/getImage.php

这个文件的功能是根据传入的视频 URL,调用 ffmpeg 提取缩略图。它接收一个叫做 base64Url 的 GET 参数,对其进行 Base64 解码,得到一个 URL 字符串,然后把这个 URL 拼进 ffmpeg 的命令里执行。

修复前的核心代码大致如下:

$url = base64_decode($_GET['base64Url']);

// ...

$exec = get_ffmpeg()." -i \"{$url}\" -f image2 -vframes 1 -y {$destination}";

execAsync($exec);

$url 直接被双引号包裹,拼进了 Shell 命令字符串,然后通过 execAsync() 执行。

execAsync() 内部是这样的:

$newCmd = "nohup " . $command . " > /dev/null 2>&1 & echo $!;";
$pid = shell_exec($newCmd);

也就是说,命令最终由 shell_exec() 在后台异步执行。


问题的关键

代码里确实有一道校验,在 objects/security.php 中:

if (!filter_var(base64_decode($scanThis['base64Url']), FILTER_VALIDATE_URL)) {
    error_log('base64Url attack ' . json_encode($_SERVER));
    exit;
}

看起来做了验证。但问题在于:FILTER_VALIDATE_URL 只判断字符串格式上像不像一个 URL,也就是检查它有没有合法的 scheme、host、path 结构。它从来不承担过滤 Shell 特殊字符的职责。

这两个字符串都能通过 FILTER_VALIDATE_URL 的检查,因为它们在语法上都是合法的 URL:

http://x.x.x.x/$(id)
http://x.x.x.x/$(cat /etc/passwd)

通过校验之后,$url 被拼进了双引号包裹的 Shell 命令字符串。Shell 在解析双引号字符串时,会将 $(...) 和反引号识别为命令替换语法,原地执行括号里的内容。于是攻击者注入的命令就在服务器上跑起来了。


这个漏洞特别在哪里

大多数命令注入漏洞,攻击者至少要登录账号,或者诱导受害者点击某个链接。这个漏洞不需要。

CVSS 向量 AV:N/AC:L/PR:N/UI:N 四个字母说明了一切:网络可达、低复杂度、无需权限、无需用户交互。一次 GET 请求,不需要账号,服务器就会执行你指定的命令。

还有一个细节让防御更难:攻击 Payload 本身经过了 Base64 编码。WAF 如果只对参数的原始值做关键字检测,看到的是一段 Base64 字符串,恶意内容隐藏在编码里,常见的明文检测规则会失效。必须在 WAF 层解码后再检测,才能识别注入内容。

命令通过 nohup ... & echo $! 异步在后台执行,HTTP 响应里不包含命令的输出,攻击行为在日志里更难被即时发现。


成因的四个层次

这不是一个偶然的低级错误,是四个决策叠加的结果。

第一层:信任边界模糊。base64Url 是外部用户完全可控的参数,但代码在简单校验后直接使用了它,没有把它当作不可信数据处理。

第二层:校验语义误解。 开发者用 URL 格式校验代替了安全校验。格式合法只说明字符串结构符合规范,与内容是否安全是两件完全不同的事。这是一种很常见的认知偏差。

第三层:Shell 插值未转义。 外部数据以双引号插值方式拼进了 Shell 命令,没有调用 escapeshellarg() 或 escapeshellcmd()。双引号内 Shell 的命令替换语法是无条件生效的基础特性,不是漏洞,是规范。

第四层:执行函数选择不当。shell_exec() 把整个命令字符串交给 Shell 解释器处理。如果改用 proc_open() 配合参数数组的形式,就不经过 Shell,命令替换语法根本不会被解析,注入面彻底消失。


攻击者能做什么

命令执行成功后,攻击者获得的是 Web 服务进程的权限,通常是 www-data 或 apache。在此基础上可以:

读取服务器上的配置文件、数据库凭据、API 密钥;向 Web 可访问目录写入 Webshell,建立长期后门;发起反弹 Shell,获得完整的交互式控制能力;以当前服务器为跳板,向内网其他系统横向移动。


时间线

| 日期 | 事件 | | — | — | | 2026-03-02 17:57 UTC | 修复 commit 提交(SHA: 78178d1),版本更新到 7.0 | | 2026-03-02 18:56 UTC | AVideo-Encoder 7.0 正式发布 | | 2026-03-02 19:03 UTC | GitHub Security Advisory(GHSA-9j26-99jh-v26q)发布 | | 2026-03-03 | CVE-2026-29058 由 MITRE 收录,编号由 GitHub_M 分配 | | 2026-03-06 | NVD 正式发布漏洞详情,评分 9.8 Critical |

漏洞由安全研究员 arkmarta 发现,项目维护者 DanielnetoDotCom(Daniel Neto)接收报告后完成修复,并通过 GitHub Security Advisory 机制进行了负责任披露。修复完成后约四天,漏洞信息才对外公开。


官方如何修复

修复方式写在提交信息里:”enhance security by validating and sanitizing URLs across multiple files”。

核心改动是在 objects/getImage.php 中,Base64 解码之后、拼进命令之前,增加了两步处理:

第一步,先过滤 shell 元字符:

$url = str_replace(
&nbsp; &nbsp;&nbsp;array('"',&nbsp;"'",&nbsp;'`',&nbsp;'$',&nbsp;'\\',&nbsp;';',&nbsp;'|',&nbsp;'&',&nbsp;'(',&nbsp;')',&nbsp;'{',&nbsp;'}',&nbsp;'<',&nbsp;'>',&nbsp;"\n",&nbsp;"\r",&nbsp;"\0"),
&nbsp; &nbsp;&nbsp;'',
&nbsp; &nbsp; $url
);

第二步,用 escapeshellarg() 转义:

$urlEscaped = escapeshellarg($url);

然后把所有命令里的 "{$url}" 替换为 {$urlEscaped}

escapeshellarg() 的作用是用单引号包裹字符串,并对内部的单引号进行转义,使 Shell 将其视为一个完整的字面量参数,而不是可解析的命令语法。

同一批次修复还覆盖了 objects/getSpiritsFromVideo.phpobjects/FTPDownloader.phpview/watermark.php 等文件中类似的 shell 注入点,并修复了 objects/security.php 中 str_replace 被误用作正则过滤的独立 bug。

立即升级至 AVideo-Encoder 7.0 是消除该漏洞的根本措施。

如果暂时无法升级,可在 Web 服务器层对 getImage.php 端点做访问控制:

Nginx:

location ~ /objects/getImage\.php {
&nbsp; &nbsp; allow 192.168.1.0/24;
&nbsp; &nbsp; deny all;
}

Apache:

<Files "objects/getImage.php">
&nbsp; &nbsp; Require ip 192.168.1.0/24
</Files>

WAF 规则需要对 base64Url 参数值进行 Base64 解码后再做内容检测,仅对原始值做明文关键字匹配是无效的。


如何判断是否已受到攻击

在访问日志中检索:

grep&nbsp;"getImage.php"&nbsp;access.log | grep&nbsp;"base64Url"

对命中记录提取 base64Url 的值并做 Base64 解码,检查结果中是否出现 $(、反引号、wgetcurlbashnc 等 Shell 元字符或命令关键词。

在主机层,关注 Web 服务进程是否存在异常的子进程创建行为,特别是由 PHP 进程派生的系统命令调用。auditd 或 eBPF 工具可以提供进程级别的监控。


给开发者的提醒

这个漏洞揭示了一个很普遍的问题:格式校验和安全校验是两件独立的事,不能相互替代。FILTER_VALIDATE_URL 的文档从未声称自己能防止命令注入,但开发者在潜意识里把”URL 格式合法”等同于”可以安全使用”。

凡是需要把外部输入传给系统命令的场景,三条原则:

优先使用参数数组形式调用外部程序,完全绕过 Shell 解析层;如果必须用 shell_exec(),所有外部输入都必须经过 escapeshellarg() 处理;格式校验通过不代表内容安全,两件事要分开做。


参考资料

NVD 漏洞详情:https://nvd.nist.gov/vuln/detail/CVE-2026-29058

GitHub 官方安全公告:https://github.com/WWBN/AVideo-Encoder/security/advisories/GHSA-9j26-99jh-v26q

CVE 官方记录:https://www.cve.org/CVERecord?id=CVE-2026-29058

修复 commit:https://github.com/WWBN/AVideo-Encoder/commit/78178d11541d44b238c4dfd9241cacb031db3765

AVideo-Encoder 7.0 Release:https://github.com/WWBN/AVideo-Encoder/releases/tag/7.0


免责声明:

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

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

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

本文转载自:CVE-SEC CVE-SEC CVE-SEC《一个 GET 请求拿下服务器:CVE-2026-29058 AVideo 命令注入漏洞分析》

    评论:0   参与:  0