diff --git a/src/images/nginx_try_files.png b/src/images/nginx_try_files.png new file mode 100644 index 000000000..0c14e95c9 Binary files /dev/null and b/src/images/nginx_try_files.png differ diff --git a/src/network-services-pentesting/pentesting-web/nginx.md b/src/network-services-pentesting/pentesting-web/nginx.md index af9a6e07e..99fd8a5e2 100644 --- a/src/network-services-pentesting/pentesting-web/nginx.md +++ b/src/network-services-pentesting/pentesting-web/nginx.md @@ -16,21 +16,21 @@ proxy_pass http://127.0.0.1:8080/; } } ``` -この構成では、`/etc/nginx` がルートディレクトリとして指定されています。この設定により、指定されたルートディレクトリ内のファイル、例えば `/hello.txt` へのアクセスが可能になります。しかし、特定の場所(`/hello.txt`)のみが定義されていることに注意することが重要です。ルートロケーション(`location / {...}`)の設定はありません。この省略により、ルートディレクティブはグローバルに適用され、ルートパス `/` へのリクエストが `/etc/nginx` の下のファイルにアクセスできるようになります。 +この設定では、`/etc/nginx` がルートディレクトリとして指定されています。このセットアップにより、指定されたルートディレクトリ内のファイル、例えば `/hello.txt` へのアクセスが可能になります。しかし、特定の場所(`/hello.txt`)のみが定義されていることに注意することが重要です。ルートロケーション(`location / {...}`)の設定はありません。この省略により、ルートディレクティブがグローバルに適用され、ルートパス `/` へのリクエストが `/etc/nginx` の下のファイルにアクセスできるようになります。 -この構成から生じる重要なセキュリティ上の考慮事項があります。単純な `GET` リクエスト、例えば `GET /nginx.conf` は、`/etc/nginx/nginx.conf` にある Nginx 設定ファイルを提供することで、機密情報を露出させる可能性があります。ルートを `/etc` のようなあまり機密性の高くないディレクトリに設定することで、このリスクを軽減できますが、それでも他の重要なファイル、他の設定ファイル、アクセスログ、さらには HTTP ベーシック認証に使用される暗号化された資格情報への意図しないアクセスを許可する可能性があります。 +この設定から生じる重要なセキュリティ上の考慮事項があります。単純な `GET` リクエスト、例えば `GET /nginx.conf` は、`/etc/nginx/nginx.conf` にあるNginxの設定ファイルを提供することで、機密情報を露呈させる可能性があります。ルートを `/etc` のようなあまり機密性の高くないディレクトリに設定することで、このリスクを軽減できますが、それでも他の重要なファイル、他の設定ファイル、アクセスログ、さらにはHTTP基本認証に使用される暗号化された資格情報への意図しないアクセスを許可する可能性があります。 ## Alias LFI Misconfiguration -Nginx の設定ファイルでは、「location」ディレクティブを注意深く検査する必要があります。Local File Inclusion (LFI) として知られる脆弱性は、以下のような構成を通じて意図せず導入される可能性があります。 +Nginxの設定ファイルでは、「location」ディレクティブを注意深く検査する必要があります。Local File Inclusion (LFI) として知られる脆弱性は、以下のような設定を通じて偶発的に導入される可能性があります。 ``` location /imgs { alias /path/images/; } ``` -この設定は、サーバーが `/imgs../flag.txt` のようなリクエストを意図したディレクトリの外にあるファイルにアクセスしようとする試みとして解釈するため、LFI攻撃に対して脆弱です。これは実際には `/path/images/../flag.txt` に解決されます。この欠陥により、攻撃者はウェブ経由でアクセスできるべきではないサーバーのファイルシステムからファイルを取得することができます。 +この設定は、サーバーが `/imgs../flag.txt` のようなリクエストを意図したディレクトリの外にあるファイルにアクセスしようとする試みとして解釈するため、LFI攻撃に対して脆弱です。これは実際には `/path/images/../flag.txt` に解決されます。この欠陥により、攻撃者はウェブを介してアクセスできるべきではないサーバーのファイルシステムからファイルを取得することができます。 -この脆弱性を軽減するために、設定を次のように調整する必要があります: +この脆弱性を軽減するために、設定を次のように調整する必要があります: ``` location /imgs/ { alias /path/images/; @@ -62,7 +62,7 @@ deny all; ../../pentesting-web/proxy-waf-protections-bypass.md {{#endref}} -## Unsafe variable use / HTTP Request Splitting +## 不適切な変数の使用 / HTTPリクエストの分割 > [!CAUTION] > 脆弱な変数 `$uri` と `$document_uri` があり、これを `$request_uri` に置き換えることで修正できます。 @@ -75,13 +75,13 @@ deny all; > > `location ~ /docs/(.*)? { … $1 … }` - 脆弱でない -Nginx 設定の脆弱性は、以下の例で示されています: +Nginxの設定における脆弱性は、以下の例で示されています: ``` location / { return 302 https://example.com$uri; } ``` -HTTPリクエストにおいて、文字 \r (キャリッジリターン) と \n (ラインフィード) は新しい行の文字を示し、そのURLエンコード形式は `%0d%0a` で表されます。これらの文字をリクエストに含めると(例: `http://localhost/%0d%0aDetectify:%20clrf`)、誤って設定されたサーバーは `Detectify` という新しいヘッダーを発行します。これは、$uri 変数がURLエンコードされた新しい行の文字をデコードするため、レスポンスに予期しないヘッダーが含まれることになります。 +HTTPリクエストにおいて、文字 \r (キャリッジリターン) と \n (ラインフィード) は新しい行の文字を示し、そのURLエンコード形式は `%0d%0a` で表されます。これらの文字をリクエストに含めると(例: `http://localhost/%0d%0aDetectify:%20clrf`)、誤設定されたサーバーは `Detectify` という新しいヘッダーを発行します。これは、$uri 変数がURLエンコードされた新しい行の文字をデコードするため、レスポンスに予期しないヘッダーが含まれることになります。 ``` HTTP/1.1 302 Moved Temporarily Server: nginx/1.19.3 @@ -98,22 +98,22 @@ CRLFインジェクションとレスポンススプリッティングのリス - `https://example.com/%20X` - 任意のHTTPコード - `https://example.com/%20H` - 400 Bad Request -脆弱な場合、最初のリクエストは「X」として返され、任意のHTTPメソッドが使用され、2番目のリクエストはHが有効なメソッドではないためエラーが返されます。したがって、サーバーは次のようなものを受け取ります:`GET / H HTTP/1.1` これによりエラーがトリガーされます。 +脆弱な場合、最初のリクエストは「X」が任意のHTTPメソッドであるため返され、2番目はHが有効なメソッドでないためエラーが返されます。したがって、サーバーは次のようなものを受け取ります:`GET / H HTTP/1.1` これがエラーを引き起こします。 他の検出例は次のとおりです: - `http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x` - 任意のHTTPコード - `http://company.tld/%20HTTP/1.1%0D%0AHost:%20x` - 400 Bad Request -そのトークで示された脆弱な構成のいくつかは次のとおりです: +そのトークで示された脆弱な設定のいくつかは次のとおりです: -- **`$uri`** が最終URLにそのまま設定されていることに注意してください。 +- 最終URLで**`$uri`**がそのまま設定されていることに注意してください。 ``` location ^~ /lite/api/ { proxy_pass http://lite-backend$uri$is_args$args; } ``` -- 再度、**`$uri`** がURLに含まれていることに注意してください(今回はパラメータ内です)。 +- 再度、**`$uri`** がURLに含まれていることに注意してください(今回はパラメータ内にあります)。 ``` location ~ ^/dna/payment { rewrite ^/dna/([^/]+) /registered/main.pl?cmd=unifiedPayment&context=$1&native_uri=$uri break; @@ -129,17 +129,67 @@ proxy_pass https://company-bucket.s3.amazonaws.com$uri; **ユーザー提供データ**が特定の状況下で**Nginx変数**として扱われる可能性があることが発見されました。この挙動の原因はやや不明ですが、珍しいことではなく、確認するのも簡単ではありません。この異常はHackerOneのセキュリティレポートで強調されており、[こちら](https://hackerone.com/reports/370094)で見ることができます。エラーメッセージのさらなる調査により、[NginxのコードベースのSSIフィルターモジュール](https://github.com/nginx/nginx/blob/2187586207e1465d289ae64cedc829719a048a39/src/http/modules/ngx_http_ssi_filter_module.c#L365)内での発生が特定され、サーバーサイドインクルード(SSI)が根本的な原因であることが明らかになりました。 -この**誤設定を検出する**ために、変数の印刷をテストするためにリファラーヘッダーを設定するコマンドを実行できます: +この**誤設定を検出するために**、以下のコマンドを実行できます。これは、変数の印刷をテストするためにリファラーヘッダーを設定することを含みます: ```bash $ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’ ``` -この設定ミスに関するスキャンは、ユーザーによってNginx変数が印刷される複数のインスタンスを明らかにしました。しかし、脆弱なインスタンスの数の減少は、この問題を修正するための努力がある程度成功していることを示唆しています。 +この設定ミスに対するスキャンは、ユーザーによってNginx変数が印刷される複数のインスタンスを明らかにしました。しかし、脆弱なインスタンスの数の減少は、この問題を修正するための努力がある程度成功していることを示唆しています。 + +### $URI$ARGS変数を使用したtry_files + +次のNginxの設定ミスは、LFI脆弱性につながる可能性があります: +``` +location / { +try_files $uri$args $uri$args/ /index.html; +} +``` +私たちの設定では、指定された順序でファイルの存在を確認するために使用されるディレクティブ `try_files` があります。Nginx は、見つけた最初のファイルを提供します。`try_files` ディレクティブの基本的な構文は次のとおりです: +``` +try_files file1 file2 ... fileN fallback; +``` +Nginxは、指定された順序で各ファイルの存在を確認します。ファイルが存在する場合は、すぐに提供されます。指定されたファイルがどれも存在しない場合、リクエストはフォールバックオプションに渡されます。フォールバックオプションは、別のURIまたは特定のエラーページである可能性があります。 + +しかし、このディレクティブで`$uri$args`変数を使用する場合、NginxはリクエストURIと任意のクエリ文字列引数を組み合わせたファイルを探そうとします。したがって、この構成を悪用することができます: +``` +http { +server { +root /var/www/html/public; + +location / { +try_files $uri$args $uri$args/ /index.html; +} +} +} +``` +次のペイロードを使用して: +``` +GET /?../../../../../../../../etc/passwd HTTP/1.1 +Host: example.com +``` +私たちのペイロードを使用して、ルートディレクトリ(Nginxの設定で定義された)を脱出し、`/etc/passwd`ファイルを読み込みます。デバッグログでは、Nginxがファイルを試みる様子を観察できます: +``` +...SNIP... + +2025/07/11 15:49:16 [debug] 79694#79694: *4 trying to use file: "/../../../../../../../../etc/passwd" "/var/www/html/public/../../../../../../../../etc/passwd" +2025/07/11 15:49:16 [debug] 79694#79694: *4 try file uri: "/../../../../../../../../etc/passwd" + +...SNIP... + +2025/07/11 15:49:16 [debug] 79694#79694: *4 http filename: "/var/www/html/public/../../../../../../../../etc/passwd" + +...SNIP... + +2025/07/11 15:49:16 [debug] 79694#79694: *4 HTTP/1.1 200 OK + +``` +PoC againts Nginx using the configuration mentioned above: +![Example burp request](../../images/nginx_try_files.png) ## 生のバックエンドレスポンスの読み取り -Nginxは、バックエンドによって生成されたエラーやHTTPヘッダーを傍受するための機能を`proxy_pass`を通じて提供し、内部エラーメッセージやヘッダーを隠すことを目的としています。これは、Nginxがバックエンドエラーに応じてカスタムエラーページを提供することによって実現されます。しかし、Nginxが無効なHTTPリクエストに遭遇すると、問題が発生します。そのようなリクエストは、受信した通りにバックエンドに転送され、バックエンドの生のレスポンスはNginxの介入なしにクライアントに直接送信されます。 +Nginxは、バックエンドによって生成されたエラーやHTTPヘッダーを傍受することを可能にする`proxy_pass`を通じて機能を提供し、内部エラーメッセージやヘッダーを隠すことを目的としています。これは、Nginxがバックエンドエラーに応じてカスタムエラーページを提供することによって実現されます。しかし、Nginxが無効なHTTPリクエストに遭遇した場合、課題が生じます。そのようなリクエストは受信したままバックエンドに転送され、バックエンドの生のレスポンスはNginxの介入なしにクライアントに直接送信されます。 -uWSGIアプリケーションに関する例を考えてみましょう: +uWSGIアプリケーションを含む例のシナリオを考えてみましょう: ```python def application(environ, start_response): start_response('500 Error', [('Content-Type', 'text/html'), ('Secret-Header', 'secret-info')]) @@ -153,34 +203,34 @@ proxy_intercept_errors on; proxy_hide_header Secret-Header; } ``` -- [**proxy_intercept_errors**](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors): このディレクティブは、Nginxがステータスコードが300を超えるバックエンドレスポンスに対してカスタムレスポンスを提供できるようにします。これにより、例として挙げたuWSGIアプリケーションにおいて、`500 Error`レスポンスがNginxによって捕捉され、処理されることが保証されます。 +- [**proxy_intercept_errors**](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors): このディレクティブは、Nginxがステータスコードが300を超えるバックエンドのレスポンスに対してカスタムレスポンスを提供できるようにします。これにより、例として挙げたuWSGIアプリケーションに対して、`500 Error`レスポンスがNginxによって捕捉され、処理されることが保証されます。 - [**proxy_hide_header**](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header): 名前が示すように、このディレクティブは指定されたHTTPヘッダーをクライアントから隠し、プライバシーとセキュリティを向上させます。 有効な`GET`リクエストが行われると、Nginxは通常通り処理し、秘密のヘッダーを明らかにすることなく標準のエラーレスポンスを返します。しかし、無効なHTTPリクエストはこのメカニズムをバイパスし、生のバックエンドレスポンスが露出し、秘密のヘッダーやエラーメッセージが含まれる結果となります。 ## merge_slashesをオフに設定 -デフォルトでは、Nginxの**`merge_slashes`ディレクティブ**は**`on`**に設定されており、URL内の複数のスラッシュを1つのスラッシュに圧縮します。この機能はURL処理を簡素化しますが、特にローカルファイルインクルージョン(LFI)攻撃に対して脆弱なアプリケーションの背後にある脆弱性を隠す可能性があります。セキュリティ専門家の**Danny RobinsonとRotem Bar**は、このデフォルトの動作に関連する潜在的なリスクを指摘しています。特にNginxがリバースプロキシとして機能する場合です。 +デフォルトでは、Nginxの**`merge_slashes`ディレクティブ**は**`on`**に設定されており、URL内の複数のスラッシュを1つのスラッシュに圧縮します。この機能はURL処理を簡素化しますが、特にローカルファイルインクルージョン(LFI)攻撃に対して脆弱なアプリケーションの背後にある脆弱性を意図せず隠す可能性があります。セキュリティ専門家の**Danny RobinsonとRotem Bar**は、このデフォルトの動作に関連する潜在的なリスクを指摘しています。特にNginxがリバースプロキシとして機能する場合です。 -このようなリスクを軽減するために、これらの脆弱性に対して感受性のあるアプリケーションには**`merge_slashes`ディレクティブをオフにする**ことが推奨されます。これにより、NginxはURL構造を変更することなくアプリケーションにリクエストを転送し、基盤となるセキュリティ問題を隠さないようにします。 +このようなリスクを軽減するために、これらの脆弱性に対して感受性のあるアプリケーションには**`merge_slashes`ディレクティブをオフにする**ことが推奨されます。これにより、NginxはURL構造を変更することなくアプリケーションにリクエストを転送し、潜在的なセキュリティ問題を隠さないようにします。 詳細については、[Danny RobinsonとRotem Bar](https://medium.com/appsflyer/nginx-may-be-protecting-your-applications-from-traversal-attacks-without-you-even-knowing-b08f882fd43d)を確認してください。 -### **Macliciousレスポンスヘッダー** +### **Maclicious Response Headers** -[**この書き込み**](https://mizu.re/post/cors-playground)に示されているように、ウェブサーバーからのレスポンスに存在する場合、特定のヘッダーがNginxプロキシの動作を変更します。これらは[**ドキュメント**](https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/)で確認できます: +[**この書き込み**](https://mizu.re/post/cors-playground)に示されているように、ウェブサーバーからのレスポンスに存在する場合、特定のヘッダーがNginxプロキシの動作を変更します。これらは[**ドキュメントで確認できます**](https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/): -- `X-Accel-Redirect`: Nginxにリクエストを指定された場所に内部リダイレクトするよう指示します。 +- `X-Accel-Redirect`: Nginxにリクエストを指定された場所に内部的にリダイレクトするよう指示します。 - `X-Accel-Buffering`: Nginxがレスポンスをバッファリングするかどうかを制御します。 - `X-Accel-Charset`: X-Accel-Redirectを使用する際のレスポンスの文字セットを設定します。 - `X-Accel-Expires`: X-Accel-Redirectを使用する際のレスポンスの有効期限を設定します。 - `X-Accel-Limit-Rate`: X-Accel-Redirectを使用する際のレスポンスの転送レートを制限します。 -例えば、ヘッダー**`X-Accel-Redirect`**はNginx内で内部**リダイレクト**を引き起こします。したがって、**`root /`**のようなNginx設定と、ウェブサーバーからのレスポンスに**`X-Accel-Redirect: .env`**が含まれていると、Nginxは**`/.env`**の内容を送信します(パストラバーサル)。 +例えば、ヘッダー**`X-Accel-Redirect`**はNginx内で内部的な**リダイレクト**を引き起こします。したがって、**`root /`**のようなNginxの設定と、ウェブサーバーからのレスポンスに**`X-Accel-Redirect: .env`**が含まれていると、Nginxは**`/.env`**の内容を送信します(パストラバーサル)。 -### **マップディレクティブのデフォルト値** +### **Mapディレクティブのデフォルト値** -**Nginxの設定**において、`map`ディレクティブはしばしば**認可制御**の役割を果たします。一般的な誤りは**デフォルト**値を指定しないことで、これが無許可のアクセスにつながる可能性があります。例えば: +**Nginxの設定**において、`map`ディレクティブはしばしば**認可制御**の役割を果たします。一般的な間違いは**デフォルト**値を指定しないことで、これが無許可のアクセスにつながる可能性があります。例えば: ```yaml http { map $uri $mappocallow { @@ -201,7 +251,7 @@ return 200 "Hello. It is private area: $mappocallow"; ``` `default`がない場合、**悪意のあるユーザー**は`/map-poc`内の**未定義のURI**にアクセスすることでセキュリティを回避できます。[Nginxマニュアル](https://nginx.org/en/docs/http/ngx_http_map_module.html)では、そのような問題を避けるために**デフォルト値**を設定することを推奨しています。 -### **DNSスプーフィング脆弱性** +### **DNSスプーフィングの脆弱性** 特定の条件下でNginxに対するDNSスプーフィングは可能です。攻撃者がNginxが使用する**DNSサーバー**を知っていて、そのDNSクエリを傍受できる場合、DNSレコードをスプーフィングできます。ただし、NginxがDNS解決に**localhost (127.0.0.1)**を使用するように設定されている場合、この方法は効果がありません。Nginxでは、次のようにDNSサーバーを指定できます: ```yaml @@ -239,7 +289,7 @@ deny all; } ``` > [!WARNING] -> `proxy_pass` が `http://backend:9999/socket.io` のような特定の **path** を指していても、接続は `http://backend:9999` に確立されるため、**その内部エンドポイント内の他のパスに連絡することができます。したがって、proxy_pass の URL にパスが指定されていても関係ありません。** +> `proxy_pass` が `http://backend:9999/socket.io` のような特定の **path** を指していても、接続は `http://backend:9999` に確立されるため、**その内部エンドポイント内の他の任意のパスに連絡することができます。したがって、proxy_pass の URL にパスが指定されていても関係ありません。** ## 自分で試してみる @@ -251,7 +301,7 @@ Detectify は、この記事で説明したいくつかの誤設定を持つ脆 ### [GIXY](https://github.com/yandex/gixy) -Gixy は Nginx 設定を分析するツールです。Gixy の主な目的は、セキュリティの誤設定を防ぎ、欠陥の検出を自動化することです。 +Gixy は Nginx の設定を分析するツールです。Gixy の主な目的は、セキュリティの誤設定を防ぎ、欠陥の検出を自動化することです。 ### [Nginxpwner](https://github.com/stark0de/nginxpwner)