社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Git

潜伏5年!GitLab高危RCE漏洞爆发,低权限即可控服

FreeBuf • 3 月前 • 173 次点击  
FreeBuf

GitLab RCE漏洞链

Part01

漏洞概要

2026年7月24日,Depthfirst研究团队发布了一个针对GitLab的远程代码执行(RCE)漏洞利用工具。该漏洞链是将Ruby JSON解析器Oj(Oj使用原生C实现)中的两个内存损坏漏洞组合起来,最终在GitLab Puma worker进程中实现完整命令执行。


任何能够向项目推送代码并查看提交diff的已认证用户均可触发该漏洞。研究人员指出,无需管理员权限、无需CI访问权限,也无需受害者交互。GitLab已于2026年6月10日修补了这两个漏洞,但将其归类为“Bug修复”而非安全补丁,因此在评估该版本时,运维人员没有理由将其视为紧急事件。


Depthfirst发布的报告指出:“系统列出的18个优先处理漏洞中,包含7个内存安全漏洞。其中两个——越界写入和堆指针泄露——在Oj中已存在近五年。Oj是GitLab使用的底层依赖,我们将两个漏洞组合后,在默认GitLab安装上实现了远程代码执行。”


Part02

技术分析

这两个漏洞于2021年8月8日被引入Oj解析器,潜伏了1753天。易受攻击的notebook路径随GitLab 15.2.0版本(2022年7月发布)引入,直到2026年6月10日才被修复。


攻击路径始于GitLab的notebook diff渲染器——一个名为ipynbdiff的内嵌gem,它负责将Jupyter的.ipynb文件转换为人类可读的diff。当用户打开notebook文件的commit diff时,GitLab会将原始仓库字节传递给Oj::Parser.usual.parse,该调用发生在Puma worker进程中。这个parse调用就是攻击入口。


报告继续写道:“调查是反向进行的:Depthfirst首先发现了应用底层的脆弱解析器,然后通过调用链回溯到用户可操控的产品边界。真正的请求则沿着相反方向,从GitLab commit diff进入原生C代码。”


notebook diff攻击路径

由于Oj::Parser.usual返回的是进程级解析器单例,该单例在同一Puma worker中的所有线程间共享,因此一次损坏会影响该进程中后续的所有解析操作。


第一个漏洞是未校验的嵌套栈溢出。Oj在解析器对象内部使用一个固定大小的1024字节数组来跟踪JSON嵌套深度。当攻击者打开超过1024层嵌套数组时,Oj会持续向该缓冲区之后的一个字节集合选择器写入数据,覆盖相邻的解析器字段。攻击者无法精确控制每个字节(数组始终写入0x01),但可以控制写入的深度。当嵌套层数足够多时,这个单字节修改会改变buf.head(解析器内部缓冲区起始指针),将其向后移动127字节,落入解析器未拥有的内存区域。随后,强制调用realloc会缓存这个伪造的内部指针,而Ruby的Array分配会回收该区域,并且Array的元素内容(虽然被限制为有效的Ruby值,但仍受攻击者影响)会用一个选择的地址覆盖解析器的p->start回调指针。


第二个漏洞提供了所需的地址。一个超长的对象键(65565字节)的长度被从size_t截断为有符号16位整数,从而回绕为29。Oj为完整键分配堆内存并存储指向它的指针,但截断后的长度告诉返回路径从内联缓冲区读取29字节。巧合的是,这29字节的第6到第13字节恰好包含堆指针。GitLab在渲染diff时将其作为单元ID的一部分输出。


报告指出:“返回的字节0到5来自外部视图的对齐填充。字节6到13是活跃的key指针。最后15个返回字节来自联合存储区,该区域未被外部视图写入,可能包含陈旧的键条目内容。这是一种固定的29字节泄露,而非任意地址读取:它只暴露了该Key条目中已存在的字节,且从未解引用攻击者选择的指针。这些偏移量来自测试所用的x86_64 ABI,因此编译器布局是这一原语边界的一部分。”


获得堆指针后,攻击者通过将自循环指令地址写入p->start,并观察哪个解析操作会挂起,来探测候选的libc基址。在一个全新的双worker GitLab实例上,ASLR搜索耗时5到10分钟;在成熟的长运行实例上,预计时间为1到2小时。


一旦恢复库基址,利用程序会在单个diffs_stream请求中链式使用两个原语。同一个commit中的两个按字典序排列的notebook文件各自承载一个阶段:第一个notebook设置回调指针,抛出异常以避免立即执行,并让GitLab继续流式传输diff;第二个notebook的旧侧触发同一Puma worker中的p->start,通过两个libruby跳板进入system(),同时攻击者的命令处于正确的寄存器中。命令以git用户身份运行(即Puma所属账户),该账户可访问源代码、Rails密钥、服务凭证以及应用能触及的任何内部服务。


报告总结道:“成功利用后,攻击者可以以git(运行GitLab Puma worker的账户)身份执行命令。其实际影响范围取决于部署隔离程度,但可能包括仓库数据、Rails密钥、服务凭证以及应用可访问的内部服务。这可能导致源代码泄露、凭证窃取、代码库修改、持久化或横向移动。”


Part03

影响范围与修复建议

受影响的GitLab CE和EE版本包括:15.2.0至18.10.7、18.11.0至18.11.4以及19.0.0至19.0.1(所有层级)。15.2之前的版本在该路径中使用了不同的JSON解析器,因此不存在漏洞。15.2至18.9版本不在GitLab安全维护的补丁轨道内,不会收到后向移植——这些实例需要迁移到受支持的版本。对于Helm和Operator部署,相关版本是运行Puma的Webservice镜像内部GitLab的版本,而非chart版本。请升级至18.10.8、18.11.5或19.0.2。截至目前,Depthfirst和GitLab均未验证任何纯配置层面的缓解措施。


参考来源:

GitLab Users Urged to Patch After Research Reveals Critical RCE Chain

https://securityaffairs.com/196062/hacking/gitlab-users-urged-to-patch-after-research-reveals-critical-rce-chain.html


推荐阅读


电报讨论


扫码加入AI安全交流群

下载FreeBuf知识大陆APP

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/199281