よくあるNginxの設定ミスの例

よくあるNginxの設定ミスの例

Nginx は現在主流の Web サービスです。 以下に、最も一般的な誤った構成をいくつか示します。

ルートの場所が見つかりません

サーバー{
  ルート /etc/nginx;

  場所 /hello.txt {
    try_files $uri $uri/ =404;
    プロキシパス http://127.0.0.1:8080/;
  }
}

rootディレクティブは、Nginx ルート ディレクトリを指定します。 上記の例では、ルート ディレクトリは /etc/nginx であるため、そのディレクトリの下のファイルにアクセスできます。 上記の構成では、 /の場所 ( location / {...} ) はなく、/hello.txt の場所のみが指定されています。 したがって、ルート ディレクティブはグローバルに設定され、/ へのリクエストはローカル パス /etc/nginx に移動することになります。

GET /nginx.confのような単純なリクエストは、/etc/nginx/nginx.conf に保存されている Nginx 構成ファイルの内容を表示します。 ルートが /etc に設定されている場合、/nginx/nginx.conf への GET リクエストにより設定ファイルが表示されます。 場合によっては、他の構成ファイル、アクセス ログ、さらには HTTP 基本認証の暗号化された資格情報にアクセスできる可能性があります。

私たちが収集した約 50,000 個の Nginx 構成ファイルの中で、最も一般的なルート パスは次のとおりです。

オフバイスラッシュ

サーバー{
  80 default_server をリッスンします。

  サーバー名_;

  場所 /static {
    エイリアス /usr/share/nginx/static/;
  }

  場所 /api {
    proxy_pass http://apiserver/v1/;
  }
}

Off-by-slash 構成エラーでは、/ が欠落しているためにパスを 1 ステップ上に移動できる可能性があります。この手法は、Orange Tsai 氏の Blackhat 講演「Breaking Parser Logic!」で広く知られるようになりました。 この講演では、location ディレクティブのスラッシュが欠落していることと alias ディレクティブを組み合わせることで、Web アプリケーションのソース コードを読み取ることができるようになる方法を説明します。 あまり知られていないのは、proxy_pass などの他のディレクティブと組み合わせて使用​​することもできるということです。 何が起こっているのか、そしてなぜそれが機能するのかを分析してみましょう。

  場所 /api {
    proxy_pass http://apiserver/v1/;
  }

次の構成が Nginx サーバーにアクセスできる場合は、http://apiserver/v1/ の下のパスのみがアクセス可能であると想定できます。

http://server/api/user -> http://apiserver/v1//user

http://server/api/user にリクエストが行われると、Nginx はまず URL を正規化します。 次に、プレフィックス /api が URL と一致するかどうかを確認します。一致する場合は一致します。 プレフィックスは URL から削除され、/user パスが残ります。 このパスはproxy_pass URL に追加され、最終的な URL は http://apiserver/v1//user になります。 location ディレクティブがスラッシュで終わっておらず、 proxy_pass URL パスがスラッシュで終わっているため、URL に二重のスラッシュがあることに注意してください。 ほとんどの Web サーバーは、http://apiserver/v1//user ユーザーを http://apiserver/v1/user に正規化します。つまり、構成エラーがあっても、すべてが期待どおりに動作し、気付かれない可能性があります。

この誤った構成は、http://server/api../ を要求することによって悪用される可能性があり、これにより Nginx は http://apiserver/v1/../ に正規化された URL http://apiserver/ を要求することになります。 これが及ぼす影響は、この誤った構成を悪用することで何を達成できるかによって異なります。 たとえば、これにより、Apache サーバーのステータスが URL http://server/api../server-status 経由で公開される可能性があり、また、パブリックにアクセスできないようにしたいパスにアクセス可能になる可能性があります。

Nginx サーバーが誤って構成されていることを示す兆候の 1 つは、URL 内のスラッシュを削除しても、サーバーが同じ応答を返すことです。 たとえば、http://server/api/user と http://server/apiuser が同じ応答を返す場合、サーバーは脆弱である可能性があります。 これにより、次のリクエストが送信されます。

http://server/api/user -> http://apiserver/v1//user
http://server/apiuser -> http://apiserver/v1/user

安全でない変数の使用

一部のフレームワーク、スクリプト、および Nginx 構成では、Nginx に保存された変数が安全でない方法で使用されます。 これにより、XSS、HttpOnly 保護のバイパス、情報漏洩、場合によっては RCE などの問題が発生する可能性があります。

スクリプト名

構成は次のとおりです。

  場所 ~ \.php$ {
    fastcgi_params を含めます。
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    127.0.0.1:9000; をデフォルトとして設定します。
  }

主な問題は、ファイルがディスク上に存在しない場合でも、Nginx が .php で終わるすべての URL を PHP インタープリターに送信することです。 これは、Nginx が作成した「落とし穴とよくある間違い」ドキュメントに記載されている、Nginx の多くの誤った構成の 1 つです。

PHP スクリプトが SCRIPT_NAME に基づいてベース URL を定義しようとすると、XSS が発生します。

<?php

if(basename($_SERVER['SCRIPT_NAME']) ==
ベース名($_SERVER['SCRIPT_FILENAME']))
 dirnameをエコーし​​ます($_SERVER['SCRIPT_NAME']);

?>

GET /index.php/<script>アラート(1)</script>/index.php
SCRIPT_NAME = /index.php/<script>alert(1)</script>/index.php

$uri を使用すると CRLF インジェクションが発生する可能性があります

Nginx 変数に関連するもう 1 つの誤った構成は、$request_uri の代わりに $uri または $document_uri を使用することです。 $uri と $document_uri には正規化された URI が含まれており、Nginx での正規化には URI の URL デコードが含まれます。 Volema は、Nginx 構成でリダイレクトを作成すると、多くの場合 $uri を使用して CRLF インジェクションが発生する可能性があることを発見しました。

脆弱な Nginx 構成の例は次のとおりです。

位置 / {
 302 https://example.com$uri を返します。
}

HTTP リクエストの改行文字は\r (キャリッジ リターン) と\n (ライン フィード) です。 改行文字を URL エンコードすると、次の文字%0d%0aが表現されます。 これらの文字がサーバーへの誤って構成されたリクエストに含まれている場合 (たとえば、http://localhost/%0d%0aDetectify:%20clrf)、URL デコード後の$uri変数に改行文字が含まれるため、サーバーは Detectify という名前の新しいヘッダーで応答します。

HTTP/1.1 302 一時的に移動しました
サーバー: nginx/1.19.3
コンテンツタイプ: text/html
コンテンツの長さ: 145
接続: キープアライブ
場所: https://example.com/
検出: clrf

任意の変数

場合によっては、ユーザー提供のデータを Nginx 変数として扱うことができます。 なぜこのようなことが起こるのかは明らかではありませんが、この H1 レポートに示されているように、これは珍しいことではなく、テストも容易ではありません。 エラー メッセージを検索すると、SSI フィルター モジュールで見つかることがわかります。つまり、これは SSI が原因であることがわかります。

テスト方法は次のとおりです。

$ curl -H 'Referer: bar' http://localhost/foo$http_referer | grep 'foobar'

生のバックエンド応答の読み取り

Nginx のproxy_passを使用すると、バックエンドによって作成されたエラーと HTTP ヘッダーをインターセプトできます。 これは、内部エラー メッセージとヘッダーを非表示にして、Nginx で処理できるようにする場合に便利です。 バックエンドがリクエストに応答できない場合、Nginx は自動的にカスタム エラー ページを提供します。 しかし、Nginx がこれが HTTP 応答であることを理解しない場合はどうなるでしょうか?

クライアントが無効な HTTP リクエストを Nginx に送信した場合、リクエストはそのままバックエンドに転送され、バックエンドは元のコンテンツで応答します。 Nginx は無効な HTTP 応答を理解できず、クライアントに転送します。 次のような uWSGI アプリケーションを想像してください。

defアプリケーション(environ、start_response):
 start_response('500 エラー', [('コンテンツタイプ',
'text/html'),('シークレットヘッダー','シークレット情報')])
 return [b"秘密情報なので、表示しないでください!"]

Nginx の設定は次のとおりです。

http {
 エラーページ 500 /html/error.html;
 proxy_intercept_errors がオン;
 proxy_hide_header シークレットヘッダー;
}

proxy_intercept_errors は、バックエンドの応答ステータスが 300 より大きい場合にカスタム応答を提供します。上記の uWSGI アプリケーションでは、500 エラーを送信しますが、これは Nginx によってインターセプトされます。

proxy_hide_header: 指定された HTTP ヘッダーをクライアントから非表示にできます。

通常の GET リクエストを送信すると、Nginx は次を返します。

HTTP/1.1 500 内部サーバーエラー
サーバー: nginx/1.10.3
コンテンツタイプ: text/html
コンテンツの長さ: 34
接続: 閉じる

ただし、次のような無効な HTTP リクエストを送信した場合、

GET /? XTTP/1.1
ホスト: 127.0.0.1
接続: 閉じる

次のような返答が届きます。

XTTP/1.1 500 エラー
コンテンツタイプ: text/html
シークレットヘッダー: secret-info

秘密情報なので、見られてはいけません!

merge_slashes がオフに設定されています

デフォルトでは、 merge_slashesディレクティブはonに設定されています。これは、2 つ以上のスラッシュを 1 つに圧縮するメカニズムであり、 ////になります。 Nginx がリバース プロキシとして使用されており、プロキシされたアプリケーションがローカル ファイルのインクルードに対して脆弱な場合、リクエストで余分なスラッシュを使用すると、悪用される余地が生じる可能性があります。 Danny Robinson 氏と Rotem Bar 氏がこれについて詳しく説明しています。

上記は、よくある Nginx の誤った設定の詳細です。Nginx の誤った設定の詳細については、123WORDPRESS.COM にアクセスして、その他の関連記事をご覧ください。

以下もご興味があるかもしれません:
  • nginxリバースプロキシサービスは、設定ファイルのエラーによりリソースにアクセスするときに404エラーを引き起こします。
  • 404 エラー ページをリダイレクトするように NGINX サーバーを構成する方法
  • Nginx キャッシュとエラーページの設定
  • Nginx サーバーでよくあるアップロードおよび接続エラーを解決するために設定を変更します
  • Nginx サーバーで 404 エラー ページを構成する際に注意すべき点
  • Nginx サーバーの 414 および 504 エラーの構成ソリューション
  • Nginx の worker_connections 設定が低すぎるため、500 エラーが発生します
  • Nginx で PHP-FPM を使用するときに PHP エラー ログを構成する方法
  • NGINX で 404 エラー ページを構成する方法

<<:  角丸四角形の HTML+CSS 実装コード

>>:  MySQL で固定されていない位置から文字列要素を抽出する方法

推薦する

Linux LVM 論理ボリューム構成プロセス (作成、増加、削減、削除、アンインストール) の詳細な説明

Linux LVM論理ボリューム構成プロセスの詳細な説明多くの Linux ユーザーは、オペレーティ...

MySql カンマ連結文字列クエリの 2 つの方法

次の2つの関数は、 FIND_IN_SETと同じように使用されます。使用する場合、 FIND_IN_...

DOCTYPE 文書型宣言 (Web ページ愛好家必読)

DOCTYPE 宣言 作成するすべてのページの先頭に、ドキュメント宣言が必要です。はい、そうでしょう...

Vueプロジェクトのパッケージ化の詳細な説明

目次1. 関連構成ケース1(使用ツールはvue-cil)ケース2(使用するツールはwebpack) ...

Apache FlinkCEP でタイムアウトステータス監視を実装するための詳細な手順

CEP - 複合イベント処理。ご注文後、一定期間内にお支払いの確認が取れませんでした。タクシーの配...

Linux は n 日前のログとサンプルコマンドを自動的に削除します

1. ファイル削除コマンド:対応するディレクトリを検索します -mtime + 日数 -name &...

Linux ソースコードからのソケット (TCP) バインドの詳細な説明

目次1. 最も単純なサーバー側の例2. バインドシステムコール2.1、inet_bind 2.2、i...

Zabbix はどのようにして ssh 経由でネットワーク デバイス データを監視および取得するのでしょうか?

シナリオシミュレーション:ある会社の運用保守担当者は、以前購入した一連のネットワーク機器の光ポートの...

強くお勧めします! Vue 3.2 でシンタックスシュガーを設定する

目次前の1. セットアップ構文シュガーとは何か2. セットアップコンポーネントを使用して自動的に登録...

CentOS 7 での Nginx ログタイミング分割の実装手順の詳細説明

1. 分割スクリプト (splitNginxLog.sh) を作成します。 * この例では、ログ分割...

JavaScript コードベースをよりクリーンにする 5 つの方法

目次1. 短絡や条件文の代わりにデフォルトのパラメータを使用する2. 複数の条件の処理3. スイッチ...

Linux での chmod コマンドの使用方法の詳細な説明

chmod コマンド構文chmod コマンドを使用する場合の正しい構文は次のとおりです。 chmod...

js を使ってシンプルな虫眼鏡効果を実現

この記事の例では、参考までに簡単な虫眼鏡効果を実現するためのjsの具体的なコードを共有しています。具...

Kylin V10 サーバーで Storm をコンパイルしてインストールする詳細なプロセス

1 はじめにApache Storm は、Hadoop と同様に、大量のデータを処理するために使用で...

Linux でのソース パッケージ インストールのサービス管理

目次1. ソースパッケージサービスの起動管理2. ソースパッケージサービスのセルフスタート管理3. ...