
Vaultwarden 1.37.3 のデフォルト X-Real-IP trusted-local 設定により、Docker NAT 環境でログイン試行回数制限がバイパスされる
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vaultwarden-ip-header-spoof
Vaultwarden 1.37.3 - dani-garcia
デフォルトの IP_HEADER=X-Real-IP と IP_HEADER_TRUSTED_PROXIES=local の組み合わせは、グローバルでない TCP ピアをすべてリバースプロキシとして扱う。標準の Docker 公開ポート NAT は RFC1918 である。クライアントが送信した X-Real-IP がレート制限のキーになる。一意な値はバーストを共有しない。
| ID | CVE 未採番 |
| CWE | CWE-307 / CWE-290 |
| CVSS | High: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 製品 | Vaultwarden |
| 影響を受けるバージョン | 1.37.3 (eb212e23)。イメージ vaultwarden/server:1.37.3。Docker 公開ポート / userland-proxy / Desktop NAT、または任意の RFC1918 ピア。 |
| 認証 | 不要 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ |
攻撃者は IP をキーとしたブルートフォース対策を無効化する。試行ごとに新しい X-Real-IP を送信する。ガバナはそのアドレスをキーとする DashMap であるため、バーストと期間が発動しない。
POST /identity/connect/token のパスワードグラント。デフォルトのバーストは IP ごとに 60 秒あたり 10 回。一意なヘッダーがバケットをリセットする。/api/two-factor/send-email-login、POST /admin、さらに未認証の hint / prelogin / delete-recover / auth-request / Send アクセスはすべて ClientIp をキーとする。docker run -p 80:80 および compose の 80:80 では、ピアはブリッジまたは Desktop NAT アドレスになる。trusted=local は !is_global(peer) である。これが一致する。X-Real-IP を実際のクライアントで 置き換える リバースプロキシ、およびピアがグローバルアドレスであるホストバインドは、どちらもガバナを正しく保つ。穴はデフォルトと、上書きのない公開ポートの組み合わせである。
1.35.x / 1.36.0 / 1.37.0 の GHSA の後、dani-garcia/vaultwarden 1.37.3 (eb212e23) を固定した。GHSA-c5rv は send-email-login を LIMITER_LOGIN に載せた。残ったのは ClientIp の選び方である。
config.rs は ip_header のデフォルトを X-Real-IP、ip_header_trusted_proxies のデフォルトを local にしている。auth.rs の ip_header_is_trusted は local を !is_global(remote) として扱う。ratelimit.rs は LIMITER_LOGIN をその IpAddr でキー付けする。Docker ブリッジ、Desktop VM NAT、ループバックはすべて非グローバルである。
標準の vaultwarden/server:1.37.3 をループバック 127.0.0.1:18170:80 で、上書きプロキシなしで立ち上げ、さらに 18171 で IP_HEADER=none の 2 つ目のインスタンスを立ち上げた。[email protected] を登録した。誤ったパスワードで、ヘッダー なし のパスワードグラントはリクエスト 11 で 429 になった (バースト 10)。同じグラントで X-Real-IP: 198.51.100.{n} を試行ごとに一意にすると、14 回 HTTP 400 のままで、429 はゼロだった。none インスタンスでは、一意な 203.0.113.{n} でも 11 で 429 になった。
SUCCESS VAULTWARDEN-IP-HEADER-SPOOF nohdr-429-at=11 spoof-400=14 spoof-429=0 none-429-at=11 VAULTWARDEN-IP-HEADER-SPOOF-WITNESS
すでに記録済みの回り道: 1.37.3 イメージがローカルになかったため、最初の compose は pull を待った。最初の /alive は Rocket のバインド中に空の応答で、待機 2 回目で 200 になった。ダミーの登録 JSON (masterPasswordHash + 短い key) で十分で、長いキーの再試行は不要だった。リバースシェル。芝居。オラクルは、ヘッダーなしで 429、一意なヘッダー付きで 400 である。
cd lab
./run.sh
対象は http://127.0.0.1:18170 (デフォルト) と http://127.0.0.1:18171 (IP_HEADER=none) のみ。イメージは vaultwarden/server:1.37.3。
IP_HEADER のデフォルトを none にするか、IP_HEADER_TRUSTED_PROXIES のデフォルトを空リスト / 明示的なプロキシ CIDR にする。local を「任意の RFC1918 ピア」とすることは、公開ポートの場合に該当する。転送ヘッダーの存在はプロキシの証明ではない。
src/config.rs (ip_header, ip_header_trusted_proxies)src/auth.rs (ip_header_is_trusted, ClientIp)src/ratelimit.rs