SRC 挖洞:GitLab GraphQL 指令绕过深度复盘,CVE-2026-19478 未授权删项目怎么打穿代码托管平台

作者 akihi(白帽攻防录讲师),某甲方网络安全工程师,合集 SRC 年度第一、腾讯 SRC 连续三年前十,单漏洞赏金 4w+,擅长 Web/App/PC 客户端漏洞挖掘。专注 GraphQL 安全、API 越权、代码审计。本文基于公开 CVE 信息与技术原理深度复盘,供安全研究与防护参考。

一、漏洞时间线

2026 年 8 月 17 日,GitLab 紧急发布了安全补丁,修复了一个 Critical 级别的 GraphQL API 漏洞 CVE-2026-19478。这个漏洞允许未认证的远程攻击者修改或删除公开项目。watchTowr 在漏洞披露后 24 小时内就观测到了活跃利用。

时间 事件 影响版本
2026-08-17 GitLab 紧急发布补丁 18.11 / 19.0 / 19.1 / 19.2
2026-08-18 多家安全媒体报道 ------
2026-08-19 技术分析文章发布 ------
2026-08-29 确认活跃利用 ------
2026-09-14 安全厂商发布预警 ------

这个漏洞的 CVSS 评分为 9.4(Critical),攻击复杂度低,无需认证,无需用户交互,是典型的"一键利用"漏洞。

二、攻击链全景

让我们先用一张流程图还原完整的攻击路径:

复制代码
攻击者发现暴露在公网的 GitLab 实例
        │
        ▼
第一步:分析 GraphQL API
        │  GitLab 的 GraphQL 端点:/api/graphql
        │  公开项目可以未认证访问
        │  攻击者构造恶意 mutation
        ▼
第二步:构造恶意 GraphQL 查询
        │  使用 @gl_introduced 指令
        │  指令中注入恶意代码
        │  目标是 destroyProject mutation
        ▼
第三步:发送请求
        │  POST /api/graphql
        │  Body 包含恶意 GraphQL 查询
        │  不需要认证 Token
        ▼
第四步:GitLab 处理查询
        │  正常流程:先检查权限,再执行 resolver
        │  漏洞流程:指令先被解析执行
        │  权限检查还没开始,代码已经执行了
        ▼
第五步:恶意指令执行
        │  攻击者可以修改公开项目
        │  甚至删除整个项目
        │  篡改用户数据
        ▼
攻击者获得未授权操作能力
        │
        ├─ 删除公开仓库的代码
        ├─ 修改项目配置和设置
        ├─ 篡改用户资料
        └─ 利用公开项目作为跳板进一步渗透

**关键结论:**这个漏洞的核心是"顺序问题"------GraphQL 指令(directive)在权限检查之前就被解析执行了。就像进门之前先让你登记,但登记的笔是可以用来开门的------还没验证你的身份,你已经在屋里了。

三、GraphQL 原理

3.1 什么是 GraphQL

GraphQL 是一种 API 查询语言,由 Facebook 开发:

复制代码
// 基本查询
query {
  project(fullPath: "group/project") {
    name
    description
    visibility
  }
}

// mutation(修改数据)
mutation {
  updateProject(input: {
    projectId: "gid://gitlab/Project/1"
    description: "hacked"
  }) {
    project {
      description
    }
  }
}

3.2 GraphQL 指令(Directive)

指令是 GraphQL 中的注解,用于修改查询的执行方式:

指令 作用
@include(if: Boolean) 条件包含字段
@skip(if: Boolean) 条件跳过字段
@deprecated 标记字段已弃用
@gl_introduced GitLab 自定义指令,标记字段引入版本

3.3 GraphQL 执行流程

一个 GraphQL 查询的执行流程:

  1. 解析(Parse):将查询字符串解析为 AST
  2. 验证(Validate):检查查询是否符合 schema
  3. 执行(Execute):遍历 AST,调用 resolver 获取数据
  4. 权限检查:在 resolver 中检查用户权限

正常情况下,权限检查应该在 resolver 执行之前。但在这个漏洞中,指令的解析发生在权限检查之前。

四、漏洞深度分析

4.1 漏洞根因

根据 GitLab 安全公告和技术分析,漏洞的根本原因是 @gl_introduced 指令的处理顺序问题:

复制代码
// 有缺陷的执行流程(伪代码)
function executeGraphQLQuery(query, context) {
    // 1. 解析查询
    let ast = parse(query);
    
    // 2. 验证查询
    validate(ast, schema);
    
    // 3. 应用指令
    // 问题在这里!
    // 指令在权限检查之前就被处理了
    ast = applyDirectives(ast);  // @gl_introduced 在这里执行
    
    // 4. 执行 resolver
    // 权限检查在 resolver 内部
    // 但指令已经在第3步执行完了
    let result = executeResolvers(ast, context);
    
    return result;
}

// 正常的执行流程应该是:
// 1. 解析
// 2. 验证
// 3. 权限检查
// 4. 应用指令
// 5. 执行 resolver

// 但 GitLab 的实现是:
// 1. 解析
// 2. 验证
// 3. 应用指令(这里出问题)
// 4. 权限检查
// 5. 执行 resolver

4.2 为什么指令会导致代码注入

@gl_introduced 是 GitLab 的自定义指令,用于标记某个字段是在哪个版本引入的:

复制代码
// 正常用法
query {
  project {
    name
    createdAt @gl_introduced(version: "13.0")
  }
}

// 漏洞利用方式
// 攻击者在指令参数中注入恶意代码
// 指令处理时会执行这段代码
// 但此时还没有做权限检查

4.3 攻击利用示例

攻击者如何利用这个漏洞删除公开项目:

复制代码
// 恶意 GraphQL 查询
mutation {
  destroyProject(input: {
    projectId: "gid://gitlab/Project/TARGET_ID"
  }) @gl_introduced(version: "1.0'; system('rm -rf /'); --") {
    errors
  }
}

// 攻击过程:
// 1. 发送 POST /api/graphql
// 2. Body 是上面的恶意查询
// 3. 不需要认证 Token
// 4. GitLab 解析查询时
// 5. @gl_introduced 指令被处理
// 6. 恶意代码被执行
// 7. 项目被删除

// 实际影响:
// - 删除公开项目
// - 修改项目配置
// - 篡改用户数据
// - 可能进一步执行命令

4.4 影响范围

产品 影响版本 影响程度
GitLab CE 18.11 及更早 未授权修改/删除
GitLab EE 19.0 / 19.1 / 19.2 未授权修改/删除
修复版本 18.11.11 / 19.0.8 / 19.1.6 / 19.2.4 ------
GitLab.com 已修复 ------

五、修复方案分析

GitLab 在 2026 年 8 月 17 日紧急发布了补丁:

修复项 修复方式
指令处理顺序 将指令处理移到权限检查之后
指令参数验证 严格验证指令参数,防止代码注入
公开项目访问控制 加强公开项目的写操作权限检查
mutation 权限 所有 mutation 都需要认证

5.1 GraphQL 安全最佳实践

复制代码
// GraphQL 安全检查清单

// 1. 所有 mutation 都需要认证
// 不要让未认证用户执行修改操作
if (mutation && !user.authenticated) {
    throw new AuthError();
}

// 2. 权限检查在最前面
// 先检查权限,再执行任何逻辑
function executeQuery(query, context) {
    if (!checkPermission(query, context.user)) {
        throw new AuthError();
    }
    // 然后才执行其他逻辑
}

// 3. 禁用 introspection(生产环境)
// 防止攻击者获取 schema 信息
introspection: false

// 4. 限制查询复杂度
// 防止深度嵌套查询导致 DoS
maxDepth: 10

// 5. 严格验证指令参数
// 不要在指令中执行用户输入的代码

5.2 GitLab 加固措施

复制代码
// GitLab 安全加固

// 1. 及时更新
// 安装最新的 GitLab 版本

// 2. 限制注册
// 不要开放公开注册
// 只允许邀请注册

// 3. 公开项目保护
// 公开项目也应该有写权限控制
// 不要让未认证用户修改公开项目

// 4. 监控告警
// 监控异常的 GraphQL 请求
// 监控大量的 delete/update 操作

// 5. 备份
// 定期备份 GitLab 数据
// 备份文件离线存储

六、SRC 审计启示录

6.1 GraphQL 安全审计清单

在 SRC 挖洞过程中,针对 GraphQL 的审计清单:

# 检查项 检测方法
1 是否启用了 introspection 发送 introspection 查询
2 未认证用户能否执行 mutation 不带 Token 发送修改请求
3 权限检查是否在最前面 测试各种指令和参数
4 是否有自定义指令 检查 schema 中的自定义指令
5 查询复杂度是否有限制 发送深度嵌套的查询

6.2 常见 GraphQL 漏洞

复制代码
// 常见 GraphQL 漏洞

// 1. 未认证 mutation
// 未登录就能修改数据

// 2. 过度泄露
// query 返回过多敏感字段

// 3. 批量查询攻击
// 一个请求执行多个操作

// 4. 深度嵌套 DoS
// 深度嵌套查询导致性能问题

// 5. 指令注入
// 自定义指令中有代码注入
// 就是本次漏洞的类型

6.3 API 安全

风险点 常见问题 防护建议
认证机制 未认证用户能执行修改操作 所有 mutation 强制认证
权限检查 权限检查顺序不对 权限检查在最前面
输入验证 指令参数没有验证 严格验证所有输入
信息泄露 introspection 暴露 schema 生产环境禁用 introspection

七、防护建议

  1. 及时更新:升级到 GitLab 18.11.11 / 19.0.8 / 19.1.6 / 19.2.4
  2. 认证强制:所有 mutation 都需要认证
  3. 权限前置:权限检查在所有逻辑之前
  4. 禁用 introspection:生产环境关闭 schema 暴露
  5. 监控告警:监控异常的 GraphQL 请求
  6. 定期备份:备份代码和配置数据

八、总结

CVE-2026-19478 是一个典型的"执行顺序错误"导致的严重漏洞。它提醒我们:在 API 设计中,安全检查的位置非常重要------必须先验证身份和权限,再执行任何业务逻辑。在 SRC 挖洞实践中,GraphQL 是一个高价值攻击面,特别是"指令处理顺序"这种隐蔽的逻辑错误,往往能造成严重的安全后果。


相关推荐
neo_will_mvp1 小时前
上海莫双一流211大学:实操安装HP1188pnw网络打印机
网络
Johny_Zhao9 小时前
FreeRADIUS + 华为AC/AP + 802.1X/WPA2-Enterprise 无线认证对接部署完整指南
网络·网络安全·信息安全·ldap·radius·huawei·系统运维·centos8
天远API10 小时前
零信任架构实战:基于天远人企关联构建自动化图谱网关
网络·人工智能·架构·自动化
vipjx112 小时前
百度网盘限速怎么破?2026实测PanDownload多线程提速方案
网络·智能路由器
锐速网络12 小时前
轻量化安全建设指南:无需硬件的SaaS化勒索病毒防御方案
网络安全·云备份·主机安全·saas安全·勒索病毒防护·轻量化安全·中小企业安全
不会就选b13 小时前
Linux之应用层协议HTTP(二)
网络·网络协议·http
hasty13 小时前
只监听本机为何仍需鉴权?Cline Hub 的 WebSocket 信任边界解析
网络·websocket·网络协议
小小小小钰儿14 小时前
1.5-Python网络编程
开发语言·网络·python·web安全·计算机·网络安全
vipjx114 小时前
2026最新PanDownload复活版评测:告别百度网盘限速实测可用
网络·智能路由器