スラッシュの有無だけでセキュリティにとんでもない大穴が空いてしまうNginxのありがちな設定ミスについて実例を踏まえて専門家が解説

GIGAZINE



多機能なウェブサーバーとして2004年に登場したNginxは、2023年6月時点では業界トップシェアとなるほど人気を集めるサーバーです。そんなNginxの設定において、スラッシュを一つ付けるか付けないかの差で大きなセキュリティホールができてしまう問題について、大手パスワードマネージャーやGoogle製のツールの例をとりあげてセキュリティアナリストのダニエル・マツモトさんがブログで解説しています。

Hunting for Nginx Alias Traversals in the wild
https://labs.hakaioffsec.com/nginx-alias-traversal/

Nginxの設定には、特定のURLへのアクセスをどう処理するべきかを記述できる「location」というディレクティブが存在しており、URLをサーバー内のファイルに対応させるのによく利用されています。例えば下記のように記述すると、サーバーの「/opt/production/assets/」の中身に「/assets/」以下のURLからアクセスできるようになります。

location /assets/ { # URLの「/assets/」に対するアクセスの処理を定義 alias /opt/production/assets/; # サーバーの「assets」へ転送
}


このlocationをaliasと組み合わせて使用するパターンにおいて、「locationで指定したURLの末尾にスラッシュを入れない」かつ「aliasで指定したパスの末尾にスラッシュを入れる」という2つの条件がそろったときに重大な脆弱(ぜいじゃく)性が発生してしまうとのこと。


locationのURL末尾にスラッシュがない場合、nginxは「/img」で始まるURLを全て「/var/images/」へ転送してしまいます。例えば「/img/profile.jpg」にアクセスした場合、「/var/images//profile.jpg」に転送されるわけですが、パスの中の連続スラッシュは無視されて「/var/images/profile.jpg」のデータが返ります。一方、「/imgprofile.jpg」にアクセスした場合は「/var/images/profile.jpg」に転送され……というように、2つのURLで同じデータにアクセスできることになります。


さらに、「/img..」というURLにアクセスすることで、「/var/images/..」というパスで指定されるデータにアクセス可能です。パスにおいて「/..」というのは親のディレクトリを指すため、「/var/images/..」は「/var/」と同じものであり、本来公開されていないはずのディレクトリまでさかのぼって閲覧することができます。例えば「/img../log/nginx/access.log」というURLにアクセスすると、「/var/log/nginx/access.log」のデータが閲覧できてしまいます。個人情報など、機密を守る必要があるデータを扱っている際には特に注意が必要です。


aliasのパスの指定において末尾のスラッシュがない場合では、URLの「/img..」にアクセスしても「/var/images..」という名前のディレクトリを探すだけなので親ディレクトリのデータにアクセスされることはありません。しかし、機密データが「/var/images_confidential」のようなディレクトリに保存されている場合は「/img_confidential」というURLでアクセスされてしまいます。結局のところ、locationとaliasの両方において末尾にスラッシュを含めるべきというわけです。


マツモトさんはこの問題を含んだコードがどれくらいあるのかを調査するため、下記の正規表現を用いてGitHubを検索してみたそうです。この正規表現では、locationのパスの末尾にスラッシュがなく、aliasのパスの末尾にスラッシュが付いているコードを検索可能です。

/location \/[_.a-zA-Z0-9-\/]*[^\/][\s]\{[\s\n]*alias \/[_.a-zA-Z0-9-\/]*\/;/


GitHubでは1900件のファイルが検索に引っかかったとのこと。コードに含まれているコメントが検索された場合など、必ずしも全てのコードに問題があるとは言えませんが、それでも多くのプロジェクトに脆弱性が発生しているのは間違いありません。


この脆弱性を実際に発生させてしまった例として、マツモトさんはオープンソースのパスワードマネージャー「Bitwarden」をとりあげています。Bitwardenはパスワードの生成・入力・デバイス間の同期などの機能を持つパスワードマネージャーで、WindowsやmacOS、Linux、Android、iOSといった多数のプラットフォーム向けのアプリに加えてブラウザの拡張機能も用意されています。過去にGIGAZINEでもレビュー済み。

無料で使えてデバイス間での自動同期にも対応しているパスワードマネージャー「bitwarden」を使ってみた – GIGAZINE


Bitwardenは、独自のサーバーを利用したい人向けにセルフホストする方法を提供しており、そのセルフホストの方法の一つとしてDockerイメージが用意されています。記事作成時点で10万ダウンロードを記録しており、かなり多くのユーザーに利用されていることがうかがえます。


BitwardenのDockerイメージの内部のコードに、下記のコードが含まれているのをマツモトさんは発見したとのこと。locationのパスが「/attachments」となっており末尾にスラッシュがなく、一方aliasの方は末尾のスラッシュが付いています。この状態では/etc/bitwarden/以下のファイル全てがアクセス可能になってしまいます。


とはいえ、/etc/bitwarden/以下に重要なデータが何も保存されていないのであれば深刻な問題には至りません。ということで、マツモトさんはどんなデータが保存されているのかを調べてみたとのこと。するとDockerfileに下記のコードが記述されているのが見つかりました。

ENV BW_DB_FILE="/etc/bitwarden/vault.db"


ユーザーがデータベースとしてSQLiteを利用する場合、Bitwardenは「/etc/bitwarden/vault.db」にデータベースを保存します。したがって、「http://<instance>/attachments../vault.db」にアクセスすることでユーザーのデータベースをまるごとダウンロードできてしまうことに。また、多数のログファイルや証明書ファイルもダウンロードできてしまったとのこと。


Bitwardenはこのバグ報告に対して、同社の中では最高額となる6000ドル(約85万円)を報奨金として支払いました。

また、マツモトさんがGitHub上のコードを調べていたところ、「Google HPC-Toolkit」というリポジトリに同様の脆弱性が含まれているのを発見したとのこと。このリポジトリでは、Google Cloudのハイ パフォーマンス コンピューティングへのデプロイを容易にするツールが提供されています。

問題となったのは下図の部分。ここでもlocationのパス末尾にスラッシュがなく、aliasのパス末尾にスラッシュが含まれています。


この脆弱性を通して、SQLiteデータベース全体やDjangoの秘密鍵を盗み取ることが可能で、SQLiteデータベースに保存されているGoogle Cloudの認証情報にアクセスされる危険があるとのこと。Googleはこのバグ報告に対して500ドル(約7万円)の報奨金を支払いました。

スラッシュの有無一つで重大な危険が生じることがあるため、Nginxの設定には徹底的な理解と慎重な実装が必要です。なお、今回の脆弱性を外部からブラックボックステストできるツールをマツモトさんが公開しているので、気になる人は確認してみてください。

この記事のタイトルとURLをコピーする

Source

タイトルとURLをコピーしました