Bitwardenの保管庫を漏えいさせるNginxの脆弱性
(labs.hakaioffsec.com)- 2004年以降、支配的な市場シェアを持つ汎用WebサーバーであるNginx
- Nginxの誤った設定は、セキュリティ脆弱性とデータ漏えいにつながる可能性がある
- Nginxの脆弱性を検出するための自動化ツール、NavGixを紹介
- この脆弱性により、意図しない範囲のファイルやディレクトリにアクセスできる可能性がある
- BitwardenとGoogleのHPC Toolkitに関するケーススタディは、この脆弱性の深刻さを示している
1件のコメント
Hacker Newsのコメント
参考までに、gixy(nginx設定チェッカー)はこの問題を検出する: https://github.com/yandex/gixy/blob/master/docs/en/plugins/a...
そしてNixOSは、自身を通じて生成された設定に対してgixyを自動実行し、問題があればシステムビルドを拒否する
$uriを使っていたただ、もっと良いオプション検索ツールがあるのか気になる。数千個ある全オプションを検索するやり方はいまいちで、
sshのようなパッケージだけを見て、それに対応するオプションだけを見たいのに、無関係な結果が多すぎるばかげた質問かもしれないが、nginxがURLパスで
..による親ディレクトリへの移動を許可すべき、もっともな理由はあるのだろうか? ただ問題を待っているような挙動に見える修正: 元の脆弱性で何が起きているのか少し混乱している。http://localhost/foo../secretfile.txt が
/var/www/foo/../secretfile.txtのように解釈されるようだが、脆弱性のないサーバーなら、なぜ http://localhost/foo/../secretfile.txt も同じように解釈しないのだろう? パス中の..がなぜある場合にだけ機能するのか分からないこのケースでは、URLの一部が設定内でローカルファイルシステムへマッピングされる方法のせいで、nginxによってディレクトリ(http://localhost/foo)として解釈される。ディレクトリを指しているように見えるため、nginxが要求されたリソースの完全パスを組み立てると
"${mapped_path}/../secretfile.txt"になり、URLの観点では意味をなさなくても、ローカルファイルシステム上では有効になる。URLは実際のパス要素ではなく単なる文字列なので、スラッシュの位置も本質的には重要ではないWebが登場して以来、Webサーバー全般で非常によく見られてきた問題だ。URLをファイルパスに直接マッピングする方式は、インデックスを持つ単純なファイルサーバーから始まったため人気があったが、すぐにURLがパスではなくアプリケーション識別子になる混在環境へ移っていった。パスの一部でアプリを指定し、残りをパラメータや引数として扱うような形だ
そして一般に、ファイルシステムオブジェクトに対してURLの
.や..を尊重するのはたいてい意味がない。私のアプリは、正しくマッピングされるようにリクエストパスを正規化している。ブラウザは相対リンクを作る際にURLをパスのように扱うので、末尾の/をいつどう使うかにも注意が必要だ。サーバー側の意味では別のリソースを指してしまうことがあるlocationにallow_parent_traversal on;のようなフラグを用意して、明示的に有効化する挙動にするのが妥当に思える"/foo/bar/.."を検査して禁止するか、"/foo/"に正規化するのだろう。しかし"/foo/bar.."は完全に有効なファイル名なので、こうした検査をすり抜けて検出されないのだと思う..がいつ機能するかは、完全にファイル権限に依存するこの場合、Webインデックスディレクトリ(
../index.html)からルートディレクトリ(/)までファイルを読める権限があると仮定すると、ルートまでたどれるので、以後はルートからアクセス可能なすべての world-readable なファイル、たとえば/etc/passwdも見られるようになる三つ又のフォークを思い浮かべると、Webサーバーは一番右の枝にいるようなものだ。枝が合流する持ち手の部分をファイルシステムだとすると、Webサーバーがいる右の枝から持ち手まで続くファイルやディレクトリにアクセス権がある場合、持ち手に到達したあとで他の枝のファイルにもそのままアクセスできる
これがなぜnginxの脆弱性に見えないのか分からない。この挙動は完全に不合理で、有益な目的もなさそうだし、即座に悪用可能だ
NginxがApache2よりも“Webスケール”だというベンチマークで人気を得たことも思い出すべきだ
こうしてはどうかと思う。Linuxカーネルのファイル名パーサーに、
..オプションを除去する Linux capability に似たオプション を設けるということ。ウェブアプリでは、電話モデムを使っていた時代から、ドット2つをどうにかして紛れ込ませるさまざまな回避策がずっと出てきた。Linuxカーネルが他のさまざまなユーザー空間バグの類型に対してやってきたように、この問題もそろそろ一括で塞ぐ方法を見つけるべき時だ
RESOLVE_BENEATHがあるFreeBSD では通常の
openat(2)にO_RESOLVE_BENEATHとしてこの機能があるnginx を権限がかなり制限された別ユーザーで実行するか、Docker で実行すればよい。そこに定期アップデートまで加えれば、たいてい セキュリティ問題の90% は解決する
/some/../pathはほぼ100%禁止されるべきだ。「誰かが見苦しいコードを書いた」以外に合理的なユースケースはない。../some/pathは少なくともたまには意味があるただ、思うほど有用ではなさそうだ。多くのアプリは OS に渡す前に
..を先に解釈してしまうからだフォルダからウェブ向けにファイルを配信するなら、ウェブフレームワークが担当する公開ルートフォルダの外へ出ないように処理すべきだ。自作しているなら、こうしたことも含めてあらゆる状況を考慮しなければならない
「Google VRP Team はこの脆弱性を見つけた功績に対して500ドルの報奨を支払った。アプリケーションへの影響は、より高い報奨を出すほど深刻ではないと判断した」とのことだが、GCP アカウントのメールアドレスと非公開鍵の露出 が500ドルしかないのか? いったいどういうことだ。いかにも Google らしい
流出したものがまだ 暗号化 されていたのは幸いだ。この分野を専門とする会社ですら流出を避けられないのだから、正直これなら最善のシナリオだ
タイトルがかなり編集されている。元のタイトルは Hunting for Nginx Alias Traversals in the wild だ。
HN の投稿タイトルは Bitwarden の脆弱性を強調しているが、記事内では Google の事例も一緒に扱われている
リソース使用を最小限に抑えつつ、安定して安全な 静的ファイル配信 だけが必要なら、今どきの最善は何だろう? 昔なら Nginx を選んでいただろうが、セキュリティの観点では、もっと目的が絞られて設定の余地が少ないツールのほうがよいのではと気になる
クロスプラットフォームで Rust 製、設定はシンプルで、安全なデフォルトを備えている。強化されたコンテナイメージや強化済みの NixOS モジュールもある
Caddy は勧めない。公式 Docker イメージがデフォルトで root で動作し [1]、適切にサンドボックス化された systemd ユニットファイルも提供していない [2]
[1]: https://github.com/caddyserver/caddy-docker/issues/104
[2]: https://github.com/caddyserver/dist/blob/master/init/caddy.s...
修正: 表現を整えた
file_serverモジュールがある間抜けな質問かもしれないが、Bitwarden はなぜそもそも
/attachmentsへの 未認証リクエスト を許可していたのだろう? Nginx のバグがあっても、その URL に認証が必要だったならリクエストは失敗しなかったのでは?それでも、Docker を通じて危険な設定を配布したのだから Bitwarden に責任があるのは確かだ。Bitwarden もこれを認めたようで、その後修正した
ばかげた質問ならご容赦を。適切な ディレクトリとファイルの所有権 があれば、こうした走査は防げるのでは?
nginx が root で動いていないなら、nginx ユーザーに明示的に割り当てられたファイル以外をどうやって読めるのか?
go-rwxをかけ、「static」ファイルのグループをwww-dataに設定したうえでg+rだけ与えれば、Web サーバーはアプリファイルにアクセスできない文字どおり アプリホスティング 101 で、20年前からみんなそうしていた
/home配下のような重要なディレクトリだけでもそうすべきグループメンバーシップをもう少し調整する必要はあるかもしれないが、その価値は十分にある
もしかすると本当に盛大にやらかしているのかもしれない。痛い
www-dataのようなユーザーに明示的に割り当てる必要すらない。アプリケーションが機密データを生成するなら、もちろん 077 umask を使うほうがよい残念ながら nginx や他の Web サーバーは、一般的な Web アプリケーションでは通常 root で実行される必要がある。80 や 443 番ポートで待ち受ける必要があるからだ。1024 未満のポートは root しか開けない
詳しい説明はこちら: https://unix.stackexchange.com/questions/134301/why-does-ngi...