1 ポイント 投稿者 GN⁺ 2023-07-04 | 1件のコメント | WhatsAppで共有
  • 2004年以降、支配的な市場シェアを持つ汎用WebサーバーであるNginx
  • Nginxの誤った設定は、セキュリティ脆弱性とデータ漏えいにつながる可能性がある
  • Nginxの脆弱性を検出するための自動化ツール、NavGixを紹介
  • この脆弱性により、意図しない範囲のファイルやディレクトリにアクセスできる可能性がある
  • BitwardenとGoogleのHPC Toolkitに関するケーススタディは、この脆弱性の深刻さを示している

1件のコメント

 
GN⁺ 2023-07-04
Hacker Newsのコメント
  • 参考までに、gixy(nginx設定チェッカー)はこの問題を検出する: https://github.com/yandex/gixy/blob/master/docs/en/plugins/a...
    そしてNixOSは、自身を通じて生成された設定に対してgixyを自動実行し、問題があればシステムビルドを拒否する

    • Webサーバーが、ユーザーがこうした落とし穴を避けるために追加ツールを必要とするなら、デフォルトを見直すべきなのかもしれない
    • gixyを知らなかったのでホームサーバーで走らせてみたら、脆弱性が1つ見つかった。301リダイレクト$uriを使っていた
    • Nixを一度使ってみたが、今のところかなり良さそうに見える
      ただ、もっと良いオプション検索ツールがあるのか気になる。数千個ある全オプションを検索するやり方はいまいちで、sshのようなパッケージだけを見て、それに対応するオプションだけを見たいのに、無関係な結果が多すぎる
    • NixOSはもうGixyを実行していない。https://github.com/NixOS/nixpkgs/pull/209075 を参照
  • ばかげた質問かもしれないが、nginxがURLパスで .. による親ディレクトリへの移動を許可すべき、もっともな理由はあるのだろうか? ただ問題を待っているような挙動に見える
    修正: 元の脆弱性で何が起きているのか少し混乱している。http://localhost/foo../secretfile.txt/var/www/foo/../secretfile.txt のように解釈されるようだが、脆弱性のないサーバーなら、なぜ http://localhost/foo/../secretfile.txt も同じように解釈しないのだろう? パス中の .. がなぜある場合にだけ機能するのか分からない

    • これはnginxでかなり昔から知られている問題で、CTFでは一般的な攻撃ベクトルだ: https://book.hacktricks.xyz/network-services-pentesting/pent...
    • 問題は、URLは実際のパスではないということだ。URLは、ディレクトリやファイル、実行ファイル、ストリームなどになりうるリソースの抽象的なアドレスである
      このケースでは、URLの一部が設定内でローカルファイルシステムへマッピングされる方法のせいで、nginxによってディレクトリ(http://localhost/foo)として解釈される。ディレクトリを指しているように見えるため、nginxが要求されたリソースの完全パスを組み立てると "${mapped_path}/../secretfile.txt" になり、URLの観点では意味をなさなくても、ローカルファイルシステム上では有効になる。URLは実際のパス要素ではなく単なる文字列なので、スラッシュの位置も本質的には重要ではない
      Webが登場して以来、Webサーバー全般で非常によく見られてきた問題だ。URLをファイルパスに直接マッピングする方式は、インデックスを持つ単純なファイルサーバーから始まったため人気があったが、すぐにURLがパスではなくアプリケーション識別子になる混在環境へ移っていった。パスの一部でアプリを指定し、残りをパラメータや引数として扱うような形だ
      そして一般に、ファイルシステムオブジェクトに対してURLの ... を尊重するのはたいてい意味がない。私のアプリは、正しくマッピングされるようにリクエストパスを正規化している。ブラウザは相対リンクを作る際にURLをパスのように扱うので、末尾の / をいつどう使うかにも注意が必要だ。サーバー側の意味では別のリソースを指してしまうことがある
    • “通常の”ユースケースでは必要ない。locationallow_parent_traversal on; のようなフラグを用意して、明示的に有効化する挙動にするのが妥当に思える
    • 推測するに、NginXはおそらく "/foo/bar/.." を検査して禁止するか、"/foo/" に正規化するのだろう。しかし "/foo/bar.." は完全に有効なファイル名なので、こうした検査をすり抜けて検出されないのだと思う
    • パス中で .. がいつ機能するかは、完全にファイル権限に依存する
      この場合、Webインデックスディレクトリ(../index.html)からルートディレクトリ(/)までファイルを読める権限があると仮定すると、ルートまでたどれるので、以後はルートからアクセス可能なすべての world-readable なファイル、たとえば /etc/passwd も見られるようになる
      三つ又のフォークを思い浮かべると、Webサーバーは一番右の枝にいるようなものだ。枝が合流する持ち手の部分をファイルシステムだとすると、Webサーバーがいる右の枝から持ち手まで続くファイルやディレクトリにアクセス権がある場合、持ち手に到達したあとで他の枝のファイルにもそのままアクセスできる
  • これがなぜnginxの脆弱性に見えないのか分からない。この挙動は完全に不合理で、有益な目的もなさそうだし、即座に悪用可能だ

    • 速度のためにそうしている。単純なテキスト置換は、パスがスラッシュで正しく終わっているか確認するよりずっと速い
      NginxがApache2よりも“Webスケール”だというベンチマークで人気を得たことも思い出すべきだ
  • こうしてはどうかと思う。Linuxカーネルのファイル名パーサーに、.. オプションを除去する Linux capability に似たオプション を設けるということ。
    ウェブアプリでは、電話モデムを使っていた時代から、ドット2つをどうにかして紛れ込ませるさまざまな回避策がずっと出てきた。Linuxカーネルが他のさまざまなユーザー空間バグの類型に対してやってきたように、この問題もそろそろ一括で塞ぐ方法を見つけるべき時だ

    • https://man7.org/linux/man-pages/man2/openat2.2.htmlRESOLVE_BENEATH がある
      FreeBSD では通常の openat(2)O_RESOLVE_BENEATH としてこの機能がある
    • そうすると壊れるものが多すぎて、まともな判断としてやることではない。
      nginx を権限がかなり制限された別ユーザーで実行するか、Docker で実行すればよい。そこに定期アップデートまで加えれば、たいてい セキュリティ問題の90% は解決する
    • /some/../path はほぼ100%禁止されるべきだ。「誰かが見苦しいコードを書いた」以外に合理的なユースケースはない。
      ../some/path は少なくともたまには意味がある
      ただ、思うほど有用ではなさそうだ。多くのアプリは OS に渡す前に .. を先に解釈してしまうからだ
    • 大差ない。コードはファイルシステム API に到達する前に パスを正規化 することが多い
    • カーネル側には別の仕組み、つまり私たちが依存している 権限システム がある
      フォルダからウェブ向けにファイルを配信するなら、ウェブフレームワークが担当する公開ルートフォルダの外へ出ないように処理すべきだ。自作しているなら、こうしたことも含めてあらゆる状況を考慮しなければならない
  • 「Google VRP Team はこの脆弱性を見つけた功績に対して500ドルの報奨を支払った。アプリケーションへの影響は、より高い報奨を出すほど深刻ではないと判断した」とのことだが、GCP アカウントのメールアドレスと非公開鍵の露出 が500ドルしかないのか? いったいどういうことだ。いかにも Google らしい

  • 流出したものがまだ 暗号化 されていたのは幸いだ。この分野を専門とする会社ですら流出を避けられないのだから、正直これなら最善のシナリオだ

  • タイトルがかなり編集されている。元のタイトルは Hunting for Nginx Alias Traversals in the wild だ。
    HN の投稿タイトルは Bitwarden の脆弱性を強調しているが、記事内では Google の事例も一緒に扱われている

    • よし、タイトルを戻しておいた。投稿タイトルは “Leaking Bitwarden's Vault with a Nginx vulnerability” だった
  • リソース使用を最小限に抑えつつ、安定して安全な 静的ファイル配信 だけが必要なら、今どきの最善は何だろう? 昔なら Nginx を選んでいただろうが、セキュリティの観点では、もっと目的が絞られて設定の余地が少ないツールのほうがよいのではと気になる

    • 私は https://static-web-server.net/ を使っている
      クロスプラットフォームで 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...
      修正: 表現を整えた
    • 少し宣伝すると、Caddy はここでは非常によくできている。自動 HTTPS を提供し、Go で書かれているのでメモリ安全性のバグを心配しなくてよく、堅実な file_server モジュールがある
    • 何年も Caddy を使ってきた。自動 SSL 証明書、ファイル配信、リバースプロキシを提供し、設定がとても簡単で明快だ。Go の単一バイナリなので「インストール」も簡単で、設定ファイルも1つだけだ
    • Caddy は設定して静的ファイルを配信するのがかなり簡単だ
    • Merecat: https://github.com/troglobit/merecat/
  • 間抜けな質問かもしれないが、Bitwarden はなぜそもそも /attachments への 未認証リクエスト を許可していたのだろう? Nginx のバグがあっても、その URL に認証が必要だったならリクエストは失敗しなかったのでは?

    • これはウェブサーバー設定を狙ったエクスプロイトなので、Bitwarden の認証コードも Bitwarden のコード自体もまったく実行されない。プロジェクトが Nginx やそのモジュールではなく独自認証を使うこと自体は、おかしいことでも間違いでもない
      それでも、Docker を通じて危険な設定を配布したのだから Bitwarden に責任があるのは確かだ。Bitwarden もこれを認めたようで、その後修正した
  • ばかげた質問ならご容赦を。適切な ディレクトリとファイルの所有権 があれば、こうした走査は防げるのでは?
    nginx が root で動いていないなら、nginx ユーザーに明示的に割り当てられたファイル以外をどうやって読めるのか?

    • もちろん防げる。アプリはあるユーザーで、nginx は別のユーザーで実行し、すべてのアプリファイルに go-rwx をかけ、「static」ファイルのグループを www-data に設定したうえで g+r だけ与えれば、Web サーバーはアプリファイルにアクセスできない
      文字どおり アプリホスティング 101 で、20年前からみんなそうしていた
    • ああ、022 umask の驚異よ。個人的には、常に他のユーザーがファイルを読めないようにすることを勧める。すべてのファイルが無理でも、少なくとも /home 配下のような重要なディレクトリだけでもそうすべき
      グループメンバーシップをもう少し調整する必要はあるかもしれないが、その価値は十分にある
    • 他の人はどうか知らないが、自分は今では個人用途で nginx をきちんとインストールしていない。Docker イメージを起動するだけ。そしてそれが root で動いているかどうかも実際には確認していない
      もしかすると本当に盛大にやらかしているのかもしれない。痛い
    • 一般的な umask は 022 なので、たいていは nginx ワーカーが読めるが書けはしない。www-data のようなユーザーに明示的に割り当てる必要すらない。アプリケーションが機密データを生成するなら、もちろん 077 umask を使うほうがよい
    • そのとおり
      残念ながら nginx や他の Web サーバーは、一般的な Web アプリケーションでは通常 root で実行される必要がある。80 や 443 番ポートで待ち受ける必要があるからだ。1024 未満のポートは root しか開けない
      詳しい説明はこちら: https://unix.stackexchange.com/questions/134301/why-does-ngi...