よくある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 で固定されていない位置から文字列要素を抽出する方法

推薦する

JavaScript キャンバスで 9 マスのグリッドカットの効果を実現

この記事では、9グリッドカット効果を実現するためのキャンバスの具体的なコードを紹介します。具体的な内...

vue.js でよく使われる v 命令の解析

目次Vue でのモデルバインド表示の if の v-text の説明v-html: v-オンv-if...

Windows10にmysql5.7.18をインストールするチュートリアル

このチュートリアルでは、MySQL 5.7.18のインストールと設定方法を参考までに紹介します。具体...

mysql は sql ファイルを実行し、エラーを報告します エラー: 不明なストレージ エンジン 'InnoDB' ソリューション

問題を見つける最近、仕事で問題が発生しました。InnoDB タイプの SQL ファイルを実行すると、...

5分でReactルーティングについてお教えします

目次ルーティングとは純粋コンポーネントの基本的な使用純粋なコンポーネントの使用に関する注意事項ルーテ...

bashコマンドの使い方の詳細な説明

Linux では、基本的に vi エディタのように「.sh」拡張子を持つテキストの処理と実行を記述す...

フロントエンドAIカットのコツ(体験談)

AI 画像の切り取りは PS と連携する必要があります。まず、スライスするレイヤーを選択し、それを...

Tomcat で静的リソースを処理するチュートリアル

序文Tomcat 内のすべてのリクエストは Servlet によって処理され、静的リソースも例外では...

MySql ストアド プロシージャ パラメータの初歩的な使用法の詳細な説明

パラメータでのストアドプロシージャの使用IN パラメータは、プロシージャに情報を渡すためにのみ使用さ...

Win10にCentOS7仮想マシンをインストールする

1. VMware Workstation 64バージョンをダウンロードするhttps://www....

Vue再帰コンポーネントの簡単な使用例

序文多くの学生は既に再帰に精通していると思います。アルゴリズムの問​​題を解決するために再帰がよく使...

タブバーのいくつかの実装方法(推奨)

タブ: カテゴリ + 説明タグバー: カテゴリ => ユーザーに現在地と目的地を知らせる1. ...

CSS における px、rem、em、vh、vw の違いを簡単に分析します

絶対長さピクセルpx はピクセル値であり、メートルやセンチメートルのような固定の長さです。相対的な長...

CSSは下部のタップバー機能を実装します

現在多くの携帯電話には、下部のタブバーを切り替える機能があります。私も最近、同様の機能を見つけました...

MySQL での重複キー更新時の replace into と insert into の使用法と相違点の分析

この記事では、MySQL での重複キー更新時の replace into と insert into...