
2026年6月,网络安全研究团队depthfirst抛出了一枚重磅炸弹——他们成功构建了一套针对GitLab的远程代码执行(RCE)概念验证程序。这个漏洞的可怕之处在于,攻击者甚至不需要管理员权限,也不需要接触CI流水线,只要手里有一个能向项目推送代码的普通账号,就能在服务器上以git用户身份执行任意命令。
GitLab官方虽然在6月10日悄悄推送了补丁,但诡异的是,这次修复并没有挂上CVE编号。很多运维人员直到漏洞细节公开才意识到,自己管理的自托管GitLab实例可能早已暴露在风险之下。
为什么这个漏洞值得所有人警惕

往常见到的GitLab漏洞,要么需要管理员权限才能触发,要么得配合复杂的社工手段。但这次不一样。
depthfirst的研究人员明确指出,任何经过认证的普通用户,只要具备向仓库推送代码的权限,就能完整触发整个攻击链。成功利用后,恶意代码会在Puma工作进程背后的git账户上下文中运行。这意味着什么?攻击者可以顺手牵羊地窃取源代码、Rails应用密钥,甚至以此为跳板对内部服务发起横向渗透。
源代码泄露、凭证失窃、内网横向移动——这三重威胁叠加在一起,足以让任何依赖GitLab托管核心代码的企业夜不能寐。更麻烦的是,depthfirst已经在GitHub上公开了完整的PoC利用代码,技术门槛被大幅拉低。
漏洞根因:Jupyter Notebook差异渲染埋下的隐患

要理解这个漏洞是怎么形成的,得从GitLab处理Jupyter Notebook文件的方式说起。
当用户在GitLab中查看.ipynb文件的差异(diff)时,系统内置的ipynbdiff gem会介入处理。这个组件会把仓库中的原始字节直接喂给Puma工作进程里长期运行的Oj::Parser.usual.parse函数。而Oj,正是GitLab选用的原生Ruby JSON解析器,底层由C语言编写。
问题就出在这里:攻击者精心构造的恶意JSON数据,会绕过Ruby层的安全检查,直接进入C语言层面的内存空间。这就像在坚固的城墙上找到了一条通往地下暗河的密道,表面看起来风平浪静,实则暗流涌动。
两个看似无害的Bug,串联成致命一击

depthfirst发现的攻击链实际上由Oj解析器中的两个内存损坏漏洞共同驱动。单独看,这两个Bug都不足以造成实质性危害。
第一个漏洞藏在嵌套栈的处理逻辑里。Oj在解析深度嵌套的数组时,没有做好边界检查,导致数据可以越界写入一个固定大小为1024字节的缓冲区。攻击者利用这一点,能够反复向特定内存地址写入单个字节。
第二个漏洞则与键长度处理有关。当键名长度被截断到16位时,会意外泄露堆指针信息——具体来说,是一段固定29字节的数据切片。
一个只能重复写一个字节,一个只能泄露一小段内存数据。放在平时,安全研究员可能扫一眼就过去了。但depthfirst的精妙之处在于,他们把这两个"小毛病"串了起来:利用堆指针泄露绕过ASLR地址空间布局随机化,再借助可控的写操作篡改回调指针,最终调用本地函数完成命令执行。
这种"积小成大"的攻击思路,恰恰体现了高水平漏洞研究的精髓。
潜伏近五年的"定时炸弹"
让人后背发凉的是时间线。
depthfirst的技术文档披露,这两个Oj漏洞在解析器中已经沉睡了整整1753天——换算下来接近五年。上游修复之前,无数Ruby应用都在不知情的情况下运行着带病的Oj版本。而GitLab中存在漏洞的notebook渲染路径,更是从发布之日起就存在了将近四年。
四年时间,足够这个攻击面被各种自动化扫描工具反复掠过。幸运的是,depthfirst报告称目前尚未发现该漏洞在野被利用的迹象。GitLab方面也独立复现了RCE效果,确认了漏洞的真实性。
披露风波:为什么很多运维还没打补丁
这次事件还有一个值得玩味的细节。
GitLab在6月10日的更新中确实修复了问题,维护分支也迁移到了Oj 3.17.3。但《黑客新闻》的跟进报道发现了一个令人费解的操作:Oj 3.17.3的版本更新被列在了常规漏洞修复列表里,而不是安全更新列表。
没有CVE编号,没有安全公告的醒目标签,很多运维团队自然缺乏紧迫感。"反正不是安全补丁,晚点升级也无妨"——这种心态在缺乏明确安全标识的情况下极易蔓延。对于自托管GitLab的管理员来说,这无异于在雷区里散步却浑然不觉。
你的GitLab版本在不在"危险名单"上
笔记本渲染器同时存在于GitLab社区版和企业版中,订阅级别不影响漏洞是否存在。判断风险的核心标准是:实例是否走了Oj的notebook解析路径,并且捆绑的Oj版本落在3.13.0到3.17.1之间。
具体受影响的GitLab版本如下:
GitLab CE/EE 15.2.0 到 18.10.7 的版本存在漏洞,已在 18.10.8 中修复。
GitLab CE/EE 18.11.0 到 18.11.4 的版本存在漏洞,已在 18.11.5 中修复。
GitLab CE/EE 19.0.0 到 19.0.1 的版本存在漏洞,已在 19.0.2 中修复。
Oj gem 的 3.13.0 到 3.17.1 版本存在问题,已在 3.17.3 中修复。
值得一提的是,GitLab 15.1 及更早版本在这条路径上使用的是Ruby原生的JSON.parse,反而躲过了这一劫。
现在该做什么:修复与缓解建议

对于运行自托管GitLab的运维团队,最稳妥的做法就是立即升级到上述修复版本。6月10日的补丁已经将维护分支的Oj依赖升级到了3.17.3,详细的版本分支信息可以参考GitLab官方的补丁发布说明。
GitLab.com的托管服务已经完成修复,使用SaaS版本的用户无需额外操作。专用版(Dedicated)客户同样不受影响。
如果你是通过Helm Chart、Operator或者自定义镜像部署的GitLab,判断修复状态的关键指标是Puma Webservice镜像中内置的GitLab版本号,而不是看外层包装。
由于这次修复没有CVE编号,建议各团队直接以Oj gem的版本号作为追踪依据,而不是依赖传统的安全标签。可以在Gemfile.lock中确认Oj的版本是否已升级到3.17.3或更高。
写在最后

这个GitLab RCE案例给整个开源社区敲响了警钟。一个高性能的C语言扩展确实能显著提升Ruby应用的JSON解析效率,但当这些原生代码与Web应用的核心渲染路径直接挂钩时,任何微小的内存管理疏忽都可能被放大成致命的远程代码执行漏洞。
depthfirst的研究不仅展示了一次精妙的漏洞串联利用,更暴露了安全披露机制中的灰色地带——没有CVE编号、没有明确的安全标签,修复补丁很容易被淹没在常规更新中。对于依赖自托管GitLab的企业而言,建立主动的依赖组件版本监控机制,或许比等待官方的安全公告更为可靠。
网硕互联帮助中心





评论前必须登录!
注册