nginx
Security
SSRF

nginxの設定ミスで起こるSSRF

はじめに

この記事は下記リンクの日本語翻訳記事です

https://github.com/yandex/gixy/blob/master/docs/en/plugins/ssrf.md

翻訳が誤っている場合はコメントか@no1zy_secまでお知らせいただけると幸いです。

[SSRF] Server Side Request Forgery

Server Side Request Forgeryはサーバーに任意のリクエストの実行を強制する攻撃です。例えばnginxの場合、proxy_passディレクティブの第2引数を攻撃者が指定できる場合に攻撃が可能になります。

どうやって見つけるか

ここにサーバーを脆弱にする2種類のエラーがあります。

  • internalディレクティブの欠如。
    • これは内部リクエストにのみ使うことができることを示すために使用されます
  • 安全でない内部リダイレクト

internalディレクティブの欠如

internalディレクティブの欠如でSSRFをすることができる典型的な設定ミスです。

location ~ /proxy/(.*)/(.*)/(.*)$ {
    proxy_pass $1://$2/$3;
}

攻撃者はプロキシされたアドレスを完全に制御できるため、Nginxの代わりにリクエストを送信することが可能になります。

安全でない内部リダイレクト

サーバー設定に internal locationがあり、そのlocationがプロキシされたサーバーのアドレスとしていずれかのリクエストデータを使用しているとします。

例:

location ~* ^/internal-proxy/(?<proxy_proto>https?)/(?<proxy_host>.*?)/(?<proxy_path>.*)$ {
    internal;

    proxy_pass $proxy_proto://$proxy_host/$proxy_path ;
    proxy_set_header Host $proxy_host;
}

Nginxのドキュメントによると、内部リクエストは下記のようにあります。

  • requests redirected by the error_page, index, random_index, and try_files directives;
  • requests redirected by the “X-Accel-Redirect” response header field from an upstream server;
  • subrequests formed by the “include virtual” command of the ngx_http_ssi_module module and by the ngx_http_addition_module module directives;
  • requests changed by the rewrite directive

日本語訳

  • error_page, index, random_index, try_files によってリクエストはリダイレクトされます。
  • upstreamサーバーからのレスポンスのX-Accel-Redirectヘッダーフィールドによってリクエストはリダイレクトされます。
  • ngx_http_addition_moduleモジュールディレクティブとngx_http_ssi_moduleモジュールのinclude virtual コマンドによって形成されたサブリクエスト
  • rewriteディレクティブによって変更されたリクエスト

従って、安全でない書き換えは攻撃者が内部リクエストを行い、プロキシされたサーバーのアドレスを制御することを可能にします。

誤った設定の例:

rewrite ^/(.*)/some$ /$1/ last;

location ~* ^/internal-proxy/(?<proxy_proto>https?)/(?<proxy_host>.*?)/(?<proxy_path>.*)$ {
    internal;

    proxy_pass $proxy_proto://$proxy_host/$proxy_path ;
    proxy_set_header Host $proxy_host;
}

対策

このような設定を書くときには下記のようないくつかのルールがあります。

  • プロキシ処理はinternal locationsのみを使用する。
  • もし可能な場合、ユーザーデータの送信を禁止する。
  • プロキシされたサーバーアドレスの保護:
    • プロキシされたホストの数が制限されている場合、それらをハードコードして、mapで選択するか、他の方法で行うことができます。
    • ホストをプロキシに書くことができない場合、アドレスに署名する必要があります。

関連リンク

nginxの設定ミスで起こるHTTP Splitting
nginxの設定ミスで起こるパス トラバーサル
nginxの設定ミスで起こるMultiline response headers
nginxの設定ミスで起こるレスポンスヘッダの出力不備
nginxの設定ミスで起こるreferer/origin検証の問題
nginxの設定ミスで起こるHostヘッダフォージェリ
nginxの設定ミスで起こるリファラの検証不備