文章总结: 研究团队公开GitLab远程代码执行漏洞链,串联Oj组件的越界写入与堆指针泄露两处内存缺陷。攻击者仅凭推送权限,通过构造恶意Jupyter笔记本差异渲染即可绕过ASLR,以git用户权限执行命令,导致源码泄露与内网移动。该潜伏近五年的漏洞虽已于6月修复但被误归为普通Bug。建议受影响版本用户立即升级至18.10.8、18.11.5或19.0.2,暂无配置缓解方案。 综合评分: 95 文章分类: 漏洞分析,漏洞预警,WEB安全,逆向分析
研究曝出可实现远程代码执行的严重漏洞利用链,GitLab 敦促用户尽快完成补丁升级
鹏鹏同学 鹏鹏同学
黑猫安全
2026年7月28日 08:54 湖北
在小说阅读器读本章
去阅读
Depthfirst 研究团队于 7 月 24 日公开了可正常利用的 GitLab 远程代码执行漏洞利用程序。攻击者可串联 Oj 组件内两处内存损坏漏洞实现攻击;Oj 是采用原生 C 语言编写的 Ruby JSON 解析器,漏洞组合利用后能在 GitLab 的 Puma 工作进程中完整执行系统命令。
具备代码推送项目权限、可查看提交差异的任意已认证用户,均可实施攻击。研究人员表示,攻击无需管理员权限、无需 CI 流水线访问权限,也不需要受害用户进行任何交互操作。GitLab 早在 6 月 10 日就完成漏洞修补,但本次修复被归类在普通功能 bug 修复列表,并未录入安全漏洞清单,运维人员在版本更新巡检时,无法意识到该补丁具备紧急修复必要性。
Depthfirst 发布的研究报告写道:“研究团队共梳理出 18 个高优先级漏洞,其中包含 7 处内存安全缺陷。有两处漏洞分别为越界写入、堆指针信息泄露,在 Oj 组件中潜伏时长接近五年。Oj 是 GitLab 底层依赖组件,我们将这两个漏洞组合,在 GitLab 默认安装环境下实现远程代码执行。”
两处漏洞于 2021 年 8 月 8 日被引入 Oj 解析器,存续共计 1753 天。包含漏洞的笔记本文件解析链路自 2022 年 7 月 GitLab 15.2.0 版本起随软件分发,直至 2026 年 6 月 10 日才完成修复。
攻击链路起始于 GitLab 的笔记本文件差异渲染模块。该模块为项目内置轻量 Ruby 组件 ipynbdiff,作用是将 Jupyter 的.ipynb 文件转换为便于阅读的代码差异内容。当用户查看笔记本文件的提交变更时,GitLab 会将仓库原始字节流传入 Puma 工作进程内的Oj::Parser.usual.parse方法,该解析调用就是漏洞攻击入口。
报告补充:“本次溯源采用逆向排查思路:Depthfirst 先定位到应用下层存在风险的解析器,再向上回溯调用链路,最终找到可由用户可控的业务边界。真实网络攻击则顺着链路正向传导,从 GitLab 提交差异入口一路下沉至 C 原生代码层。”
由于Oj::Parser.usual返回进程级全局解析器单例,该实例在同一个 Puma 工作进程的所有线程间共享。一旦解析器遭到内存破坏,该进程后续所有解析操作都会受影响。
第一个漏洞为未做校验的嵌套栈溢出。Oj 依靠解析器对象内一块固定大小 1024 字节的数组记录 JSON 嵌套层级。攻击者构造超过 1024 层嵌套数组时,Oj 会持续向缓冲区末尾之外写入单字节集合选择符,覆盖解析器相邻字段。攻击者无法精准控制每一字节内容(数组固定写入 0x01),但能够控制溢出覆盖的长度。嵌套层级足够多时,该单字节会修改缓冲区起始指针buf.head,将指针向后偏移 127 字节,指向解析器无权限访问的内存区域。后续强制内存重分配会固化这个篡改后的非法指针;一次 Ruby 数组内存复用接管该内存,数组元素取值受 Ruby 语法合法值限制但可被攻击者操控,最终将解析器回调指针p->start篡改为攻击者指定地址。
第二个漏洞用于获取目标内存地址。当对象键长度达到 65565 字节时,长度数据从无符号长整型(size_t)截断为有符号 16 位整型,数值发生整型回绕,最终变为 29。Oj 按照原始完整长度在堆上分配内存并保存堆指针,但截断后的长度让代码返回逻辑仅从行内缓冲区读取 29 字节。这 29 字节的第 6 至 13 位恰好包含堆指针,GitLab 在渲染文件差异时会把这段数据作为单元格 ID 输出。
报告原文说明:“返回的 0~5 字节为外部视图的对齐填充位;6~13 字节是当前有效键的堆指针;末尾 15 字节取自共用体存储空间,并未被外部视图写入,可能残留旧的键条目数据。该漏洞是固定 29 字节信息泄露,并非任意地址读取:仅泄露该键条目已存在的内存数据,不会访问攻击者任意指定的指针地址。上述偏移适配测试环境 x86_64 应用二进制接口(ABI),编译器内存排布是漏洞利用条件的组成部分。”
拿到堆内存地标地址后,攻击者将自循环指令地址写入p->start,通过观察解析进程是否卡死,暴力枚举 libc 基址。全新部署、仅开启两个 Puma 工作进程的 GitLab 环境下,地址空间布局随机化(ASLR)遍历耗时 5~10 分钟;长期稳定运行的成熟实例预估需要 1~2 小时。
拿到 libc 基址后,攻击者在单次diffs_stream请求中串联两处漏洞完成整套利用。同一次代码提交内放置两个词序有序的 Jupyter 笔记本文件,分两步完成攻击:第一个笔记本篡改回调指针并主动抛出异常,避免代码立刻执行,保证 GitLab 正常继续推送差异流;第二个笔记本的旧版本内容在同一个 Puma 工作进程中触发p->start回调,程序跳转调用两段 libruby 代码小工具(gadget),最终调用system()函数,将攻击者传入的系统命令置入对应寄存器完成执行。
命令以运行 Puma 的 git 系统账号权限执行,攻击者可触达源代码、Rails 密钥、各类服务凭证,以及 GitLab 应用能够访问的所有内网业务。
报告总结:“漏洞利用成功后,命令以运行 GitLab Puma 工作进程的 git 账号执行。实际可访问范围取决于部署环境的隔离程度,通常可获取仓库源码、Rails 密钥、各类服务凭证以及应用可连通的内网服务,进而造成源码泄露、凭证窃取、仓库篡改、权限持久化、内网横向移动等风险。”
受影响版本与修复方案
全功能套餐的 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 版本,而非 Helm Chart 版本。
推荐升级至修复版本:18.10.8、18.11.5、19.0.2。Depthfirst 与 GitLab 均未验证出仅靠配置修改即可规避漏洞的临时方案。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:黑猫安全 鹏鹏同学 鹏鹏同学《研究曝出可实现远程代码执行的严重漏洞利用链,GitLab 敦促用户尽快完成补丁升级》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论