GitLab 未认证 RCE 应急实战CVE-2026-97229(CVSS 10.0)

真机环境:GitLab CE 19.5.3 / Rocky Linux 9.8

2026 年 11 月

目 录

一、漏洞速览

二、漏洞原理

[2.1 为什么运维必须当天响应](#2.1 为什么运维必须当天响应)

三、真机实测环境

[四、30 秒自查:版本三连](#四、30 秒自查:版本三连)

[4.1 方法一:读版本文件(最快,1 秒)](#4.1 方法一:读版本文件(最快,1 秒))

[4.2 方法二:查 RPM 包(同时确认安装形态)](#4.2 方法二:查 RPM 包(同时确认安装形态))

[4.3 方法三:Web 页面(无服务器登录权限时)](#4.3 方法三:Web 页面(无服务器登录权限时))

[4.4 判定](#4.4 判定)

五、排查是否已经被打过

[5.1 日志排查](#5.1 日志排查)

[5.2 项目侧排查](#5.2 项目侧排查)

[5.3 时间线对照](#5.3 时间线对照)

六、修补流程:从旧版本升到安全版

[6.1 第一步:先备份](#6.1 第一步:先备份)

[6.2 第二步:升级](#6.2 第二步:升级)

[6.3 第三步:验证](#6.3 第三步:验证)

[七、加固建议与应急 SOP](#七、加固建议与应急 SOP)

[7.1 立即加固](#7.1 立即加固)

[7.2 若确认已被攻破](#7.2 若确认已被攻破)

[7.3 通用 SOP:满分漏洞当天处置流程](#7.3 通用 SOP:满分漏洞当天处置流程)

一、漏洞速览

2026 年 10 月 12 日,GitLab 发布紧急补丁版本,修复了一个 CI/CD 正则编译器中的整数溢出漏洞 CVE-2026-97229。该漏洞允许未经身份验证的攻击者在服务器上执行任意代码,CVSS 3.1 评分 10.0 满分。10 月 20 日至 21 日,安全人员观测到攻击者对 Alpine Linux 的 GitLab 实例发起真实攻击;10 月 29 日 CISA 将其列入已知被利用漏洞(KEV)目录;10 月 30 日 Metasploit 合并了公开利用模块------从补丁发布到武器化不到 20 天,属于典型的「满分漏洞 + 已武器化」组合,必须当天处置。

|------------|--------------------------------------------------------------------------------------------------------|
| 项目 | 内容 |
| CVE 编号 | CVE-2026-97229 |
| severity | CVSS 3.1 10.0(Critical) |
| 漏洞类型 | Onigmo 正则引擎整数溢出 → 堆越界写 → 未认证 RCE |
| 受影响版本 | CE/EE:19.2 < 19.2.8;19.3 < 19.3.5;19.4 < 19.4.2;19.5.0 |
| 修复版本 | 19.2.8 / 19.3.5 / 19.4.2(10-12);19.5.1 / 19.4.3 / 19.3.6 / 19.2.9 / 19.1.9 / 19.0.10 / 18.11.13(10-21) |
| 在野利用 | 已确认(Alpine Linux 事件、CISA KEV、Metasploit 模块) |
| 利用前提 | 部署构造的 CI/CD 配置;投递请求本身无需认证 |

二、漏洞原理

这个问题不在 GitLab 的上层业务代码,而在其底层依赖的 Ruby 正则表达式编译器 Onigmo。GitLab 在校验 CI/CD 配置中的正则表达式时,直接调用打包的 Ruby 3.3/3.4 的 Regexp 编译接口,对模式长度与重复计数没有任何限制。

Onigmo 在编译量词(重复)节点时,用有符号 32 位整数计算「编译长度 × 重复次数」,并拿这个乘积与固定上限比较来决定是否展开重复。这个比较没有溢出保护:当乘积越过 32 位整数上限发生回绕,变成一个很小的值甚至负值时,负值同样能通过上限检查------本应拦截超大重复的保护逻辑被它自己要拦的溢出绕过了。编译器随后按回绕后的小值分配缓冲区,却写入完整的指令流,跳转偏移同样回绕,最终形成堆越界写。

攻击者把构造好的正则写进 CI/CD 配置(.gitlab-ci.yml 的 rules/only/except 等位置),触发 GitLab 服务进程编译该正则,即可在服务进程内执行任意代码。正因漏洞出在 2014 年起就存在的底层引擎,GitLab 10 月 21 日的补丁一口气回溯修复了 18.11 至 19.5 共七个版本线。

2.1 为什么运维必须当天响应

  • 10-12 补丁发布 → 10-20 实际攻击 → 10-29 进 KEV → 10-30 公开 Metasploit 模块,时间线一路压缩。
  • Metasploit 模块瞄准的是官方 Omnibus Docker 镜像(amd64),即自建实例的主流部署形态------照着文档装的实例就是靶子。
  • GitLab 通常承载全部源码与 CI/CD 流水线,一旦 RCE 等于供应链沦陷:源码、构建凭据、部署密钥全部暴露。

三、真机实测环境

本文所有命令均在以下真机环境实测执行:

|------------|------------------------------------------------------------|
| 项目 | 配置 |
| 主机 | 内网虚拟机 gitlab(10.10.10.76) |
| 操作系统 | Rocky Linux 9.8 |
| GitLab | CE 19.5.3(Omnibus RPM 安装,gitlab-ce-19.5.3-ce.0.el9.x86_64) |
| 服务形态 | gitlab-ctl 管理共 15 个 run 服务,非容器部署 |
| 资源 | 7 GB 内存,/ 分区 46G(已用 26%) |

先说实测结论:这台机器的 19.5.3 高于 10 月 21 日发布的修复版本 19.5.1,已包含 Onigmo 整数溢出补丁,不受 CVE-2026-97229 影响。因此本文演示的重点是「如何快速自查版本、如何确认没被打过、以及如果版本不对怎么补」------这正是大多数读者现在需要做的事。

四、30 秒自查:版本三连

判断是否受影响,本质就是确认当前版本号。Omnibus 部署有三种等价查法,按速度排序:

4.1 方法一:读版本文件(最快,1 秒)

Omnibus 安装把当前版本明文写在 VERSION 文件里,无需任何 GitLab 命令:

cat /opt/gitlab/embedded/service/gitlab-rails/VERSION

19.5.3

4.2 方法二:查 RPM 包(同时确认安装形态)

rpm -q gitlab-ce # CE 版;EE 环境换成 rpm -q gitlab-ee

gitlab-ce-19.5.3-ce.0.el9.x86_64

4.3 方法三:Web 页面(无服务器登录权限时)

浏览器访问 http://实例地址/help,页面右上角显示版本号;或用管理员 Token 调 API:

curl -s -H "PRIVATE-TOKEN: <token>" http://10.10.10.76/api/v4/version

{"version":"19.5.3","revision":"xxxxxxxxxxxx"}

4.4 判定

|---------------------------|----------------------------------------|
| 你的版本 | 结论 |
| 19.5.1 ~ 19.5.x(≥19.5.1) | 已修复,与实测机 19.5.3 同状态,无需升级 |
| 19.5.0 | 受影响,升到 19.5.1 以上 |
| 19.4 < 19.4.2 | 受影响,升到 19.4.2 以上(建议直接 19.4.3) |
| 19.3 < 19.3.5(含 19.3.4) | 受影响,升到 19.3.5 以上;19.3.4 另有缺陷,直接 19.3.6 |
| 19.2 < 19.2.8 | 受影响,升到 19.2.8 以上 |
| 18.x 旧版本线 | 受影响(Onigmo 缺陷可回溯至 7.0),升 18.11.13 |

五、排查是否已经被打过

版本没问题只是第一步。如果实例在补丁前长期暴露公网,还应做利用痕迹排查。Metasploit 模块需要一名能向公开项目提交代码的用户来布置攻击载荷,但真正触发漏洞的请求无需认证------所以日志里重点是「陌生来源的 CI 配置解析与推送」。

5.1 日志排查

GitLab 日志目录

ls /var/log/gitlab/gitlab-rails/

扫描主日志中的正则编译相关异常

grep -iE 'regexp|onigmo|compile' /var/log/gitlab/gitlab-rails/production.log

API 日志里找异常来源 IP(10-12 补丁之前的时段重点看)

grep -oE '"remote_ip":"\^"+"' /var/log/gitlab/gitlab-rails/api_json.log | sort | uniq -c | sort -rn | head

实测机上对 production.log 的正则/编译关键字扫描结果为空,无异常记录。读者按同样的关键字扫自己实例的日志,若发现陌生 IP 频繁触发 CI 配置解析类请求,需进一步核对对应项目的 .gitlab-ci.yml 是否被插入过可疑正则。

5.2 项目侧排查

  • 审计公开项目中 .gitlab-ci.yml 的变更历史,重点看 rules、only、except 中的正则是否被改动过。
  • 核对系统用户列表有无陌生账号(利用模块需要可提交代码的账号)。
  • 检查 CI Runner 注册记录与流水线运行记录有无异常任务。

5.3 时间线对照

把「实例暴露公网的时间段」与攻击时间线对照:10-12 补丁发布前就暴露公网且从未打补丁的,按被攻破对待,处置见第七章;补丁后才上线的可以直接进入常规加固。

六、修补流程:从旧版本升到安全版

以一台受影响的 19.5.0 为例(实测机 19.5.3 已是安全版,以下为标准流程,已在实测机验证命令语法)。Omnibus 部署的升级就是换 RPM 包,但必须按顺序做。

6.1 第一步:先备份

本次补丁包含数据库迁移,单节点实例升级期间会停机。升级前必须做全量备份:

gitlab-backup create STRATEGY=copy

cp /etc/gitlab/gitlab-secrets.json /backup/

cp /etc/gitlab/gitlab.rb /backup/

gitlab-secrets.json 丢了备份等于数据全废(加密列无法解密),务必单独复制。

6.2 第二步:升级

Rocky/RHEL 系(实测环境)

dnf update gitlab-ce -y

或指定目标版本

dnf install gitlab-ce-19.5.3-ce.0.el9 -y

Debian/Ubuntu 系对应 apt install gitlab-ce=版本号。升级过程 GitLab 自动执行 reconfigure 与数据库迁移,单节点停机时间取决于数据量,一般 10 到 30 分钟。

6.3 第三步:验证

gitlab-ctl status # 15 个服务应全部 run

cat /opt/gitlab/embedded/service/gitlab-rails/VERSION # 确认新版本号

gitlab-rake gitlab:check SANITIZE=true # 全面体检(耗时较长,耐心等)

run: gitaly: (pid 11337) ...; run:

run: gitlab-workhorse: (pid 11279) ...; run:

run: nginx: (pid 63647) ...; run:

(实测机 15 个 run 服务全部正常)

最后用浏览器登录确认:仓库可访问、流水线可运行、合并请求正常------补丁含数据库迁移,业务验证不能省。

七、加固建议与应急 SOP

7.1 立即加固

  • GitLab 管理界面与 SSH 不暴露公网:远程访问走 VPN 或 IP 白名单,这是比任何补丁都靠前的防线。
  • 开启自动安全更新或订阅 GitLab 官方安全公告,Critical 级公告当天响应。
  • 最小权限:减少能向项目提交代码的账号,关闭闲置账号,开启 2FA。
  • 备份常态化:gitlab-backup 定时任务 + 异机存放, secrets.json 单独保管。

7.2 若确认已被攻破

  1. 立即断网隔离,保留日志与现场。
  2. 按第六章完成升级后再恢复服务,防止二次沦陷。
  3. 轮换全部凭据:GitLab root 与用户密码、Runner Token、CI/CD 变量中存放的部署密钥、SSH 私钥、云 AccessKey------GitLab 沦陷意味着这些密钥全部视为泄露。
  4. 审计流水线历史,确认攻击者没有借 CI 通道横向渗透到部署目标。

7.3 通用 SOP:满分漏洞当天处置流程

  1. 看到 KEV / 官方 Critical 公告,先做资产清单比对:我有没有、什么版本、暴不暴露公网。
  2. 版本三连(VERSION 文件 / rpm / API)30 秒定性。
  3. 受影响 → 备份 → 升级 → 验证,当天完成;完成不了先断公网。
  4. 不受影响 → 记录证据(版本截图与命令输出),进入常规巡检。
  5. 事后按第五章补一遍利用痕迹排查。

一句话总结:CVE-2026-97229 的可怕之处不在技术多新,而在武器化速度------补丁发布到 Metasploit 模块公开只用 18 天。自建 GitLab 的版本自查是 30 秒的事,别让它变成 18 天的事。

相关推荐
陈希12310 分钟前
Linux 网络诊断工具实战:ping、curl、tcpdump、mtr、dig 用法详解
linux·网络·tcpdump
进击的荆棘14 分钟前
Linux系统——线程同步与互斥之线程池和安全
linux·运维·服务器·安全·单例模式·线程
KCENN1 小时前
安全地毯压敏传感防护在工业流水线与机器人作业区的耐腐蚀材质及紧急停机机制
安全
北城笑笑1 小时前
Vue 109 ,从零搭建 Vue3 + Electron 工程:生态、安全桥接与打包选型( Vue + Electron )
前端·javascript·vue.js·安全·electron·vue
草莓熊Lotso2 小时前
【C++ 基于微服务的即时通讯系统】文件存储子服务实战:UUID生成、文件IO封装与全接口单元测试
开发语言·网络·数据库·c++·微服务·架构·单元测试
wuyk5554 小时前
Spider-第03讲-HTTP速通与读懂响应
网络·爬虫·网络协议·http
默|笙13 小时前
【Linux网络】网络层协议 IP(1)理解报头、网段划分
linux·网络·tcp/ip
山东科恩光电14 小时前
安全触边在协作机器人工作站防碰撞防护中的安装方案与性能优化
安全
梦到啥说啥20 小时前
Linux网络编程:TCP网络协议
网络·网络协议·tcp/ip