著者は、Write for DOnationsプログラムの一部として寄付を受け取るためにThe OWASP Foundationを選択しました。
前書き
Nginxは、その安定性、シンプルな構成、および質素なリソース要件で知られる、人気のあるオープンソースのHTTPサーバーおよびリバースプロキシです。 NAXSIなどのモジュールを使用すると、Nginxサーバーのセキュリティを大幅に向上できます。 NAXSI(Nginx Anti XSS & SQL Injection)は、Webアプリケーションファイアウォール機能を提供する無料のサードパーティNginxモジュールです。 NAXSIは、Webアプリケーションに着信するトラフィックを分析、フィルタリング、および保護し、デフォルトのドロップファイアウォールのように動作します。つまり、特にアクセスを許可するように指示されない限り、着信するすべてのトラフィックをブロックします。
ユーザーがアクセスを操作できるシンプルさは、NAXSIをModSecurityのような同様の機能を持つ他のWebアプリケーションファイアウォール(WAF)と区別する重要な機能です。 ModSecurityには豊富な機能セットが付属していますが、NAXSIよりも保守が困難です。 これにより、NAXSIは、WordPressなどの一般的なWebアプリケーションで適切に機能する、すぐに使用可能なルールを提供する、シンプルで適応可能な選択肢になります。
このチュートリアルでは、NAXSIを使用してUbuntu 16.04サーバー上のNginxを保護します。 NAXSIモジュールにはデフォルトでNginxパッケージが付属していないため、NAXSIを使用してソースからNginxをコンパイルする必要があります。 このチュートリアルの終わりまでに、NAXSIがブロックできる攻撃の種類と、NAXSIルールの構成方法がわかります。
前提条件
このチュートリアルを完了するには、次のものが必要です。
-
sudo非rootユーザーとファイアウォールを含むthe Ubuntu 16.04 initial server setup guideをフォローしてセットアップされた1つのUbuntu16.04サーバー。
[[step-1 -—- installing-nginx-and-naxsi]] ==ステップ1—NginxとNAXSIのインストール
Nginxモジュールのほとんどはリポジトリを介して利用できず、NAXSIも例外ではありません。 このため、NAXSIを使用してソースからNginxを手動でダウンロードしてコンパイルする必要があります。
まず、次のコマンドを使用してNginxをダウンロードします。
[.note]#Note:このチュートリアルでは、バージョン1.14のNginxを使用します。 より新しいバージョンを使用するには、the download pageにアクセスして、前のコマンドで強調表示されたテキストを更新されたバージョン番号に置き換えることができます。 最新の安定バージョンを使用することをお勧めします。
#
wget http://nginx.org/download/nginx-1.14.0.tar.gz
次に、Githubの安定した0.56リリースからNAXSIをダウンロードします。
[.note]#Note:このチュートリアルでは、NAXSIのバージョン0.56を使用します。 最新のリリースはNAXSI Github pageにあります。 最新の安定バージョンを使用することをお勧めします。
#
wget https://github.com/nbs-system/naxsi/archive/0.56.tar.gz -O naxsi
お気づきかもしれませんが、Nginxリポジトリはtar
アーカイブです。 コンパイルしてインストールできるようにするには、最初にそれを抽出する必要があります。これは、tar
コマンドを使用して実行できます。
tar -xvf nginx-1.14.0.tar.gz
上記のコマンドで、-x
は抽出ユーティリティを指定し、-v
はユーティリティを冗長モードで実行し、-f
は抽出するアーカイブファイルの名前を示します。
Nginxファイルを抽出したので、次のコマンドを使用してNAXSIファイルの抽出に進むことができます。
tar -xvf naxsi
これで、ホームディレクトリにnaxsi-0.56
フォルダとnginx-1.14.0
フォルダができました。 ダウンロードして抽出したファイルを使用して、NAXSIでNginxサーバーをコンパイルできます。 nginx-1.14.0
ディレクトリに移動します
cd nginx-1.14.0
ソースからNginxをコンパイルするには、Cコンパイラgcc
、Perl互換正規式ライブラリlibpcre3-dev
、およびSSLおよびTLD暗号化プロトコルを実装するlibssl-dev
が必要です。 これらの依存関係は、apt-get
コマンドで追加できます。
まず、次のコマンドを実行して、更新されたパッケージのリストがあることを確認します。
sudo apt-get update
次に、依存関係をインストールします。
sudo apt-get install build-essential libpcre3-dev libssl-dev
依存関係がすべて揃ったので、ソースからNginxをコンパイルできます。 Nginxをシステムのソースからコンパイルする準備をするには、次のスクリプトを実行します。これにより、必要なすべての依存関係を見つける場所を示すMakefile
が作成されます。
./configure \
--conf-path=/etc/nginx/nginx.conf \
--add-module=../naxsi-0.56/naxsi_src/ \
--error-log-path=/var/log/nginx/error.log \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-log-path=/var/log/nginx/access.log \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--lock-path=/var/lock/nginx.lock \
--pid-path=/var/run/nginx.pid \
--user=www-data \
--group=www-data \
--with-http_ssl_module \
--without-mail_pop3_module \
--without-mail_smtp_module \
--without-mail_imap_module \
--without-http_uwsgi_module \
--without-http_scgi_module \
--prefix=/usr
上記のコマンドの各行は、Nginx Webサーバーのパラメーターを定義します。 これらの中で最も重要なのは、NAXSIモジュールをNginxに接続する--add-module=../naxsi-0.56/naxsi_src/
パラメーターと、専用のユーザーおよびグループ特権でNginxを実行する--user=www-data
および--group=www-data
パラメーターです。 Ubuntu 16.04サーバーに付属するwww-data
というユーザー/グループ。 --with-http_ssl_module
パラメータはNginxサーバーがSSL暗号化を使用できるようにし、--without-mail_pop3_module
、--without-mail_smtp_module
、および--without-mail_imap_module
パラメータは、そうでなければ自動的に含まれる不要なメールプロトコルをオフにします。 これらのパラメーターの詳細については、official Nginx docsを参照してください。
./configure
コマンドを使用した後、make
コマンドを実行して、ソースコードからプログラムをビルドするために作成したMakefile
で定義された一連のタスクを実行します。
make
Nginxがビルドされて実行の準備ができたら、スーパーユーザーとしてmake install
コマンドを使用して、ビルドされたプログラムとそのライブラリをサーバー上の正しい場所にコピーします。
sudo make install
これが成功すると、NAXSIモジュールを備えたNginxのコンパイル済みバージョンが得られます。 NAXSIに不要なトラフィックのブロックを開始させるには、一連の構成ファイルを作成して、NAXSIが処理する一連のルールを確立する必要があります。
[[step-2 -—- configuring-naxsi]] ==ステップ2—NAXSIの構成
ファイアウォールの機能の最も重要な部分は、サーバーからの要求をブロックする方法を決定するルールです。 NAXSIにデフォルトで付属している基本的なルールのセットは、core rulesと呼ばれます。 これらのルールは、リクエストの一部のパターンを検索し、攻撃の可能性があるものを除外することを目的としています。 NAXSIコアルールは、署名の一致のためにサーバーにグローバルに適用されます。
これらのコアルールを使用するようにNginxを構成するには、naxsi_core.rules
ファイルをNginx構成ディレクトリにコピーします。
sudo cp ~/naxsi-0.56/naxsi_config/naxsi_core.rules /etc/nginx/
コアルールが確立されたので、ロケーションごとにコアルールを有効化および実装し、URLリクエストがコアルールを満たさない場合にサーバーが実行するアクションを割り当てる基本的なNaxsiルールを追加します。 /etc/nginx/
ディレクトリ内にnaxsi.rules
というファイルを作成します。 そのためには、次のコマンドを使用してnanoというテキストエディターでファイルを開くか、任意のテキストエディターを使用します。
sudo nano /etc/nginx/naxsi.rules
基本的なファイアウォールルールを定義する次のコードブロックを追加します。
/etc/nginx/naxsi.rules
SecRulesEnabled;
DeniedUrl "/error.html";
## Check for all the rules
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
上記のコードは、DeniedUrl
を定義します。これは、リクエストがブロックされたときにNAXSIがリダイレクトするURL
です。 このファイルは、SQLインジェクション、クロスサイトスクリプティング(XSS)、リモートファイルインクルージョン(RFI)など、NAXSIがブロックする必要のあるさまざまな種類の攻撃のチェックリストも有効にします。 上記のコードをファイルに追加したら、テキストエディターを保存して終了します。
ブロックされたリクエストを/error.html
にリダイレクトしたので、/usr/html
ディレクトリ内にerror.html
ファイルを作成して、この宛先にランディングページを提供できるようになりました。 テキストエディターでファイルを開きます。
sudo nano /usr/html/error.html
次に、次のHTMLコードをファイルに追加して、リクエストがブロックされたことをユーザーに知らせるWebページを作成します。
/usr/html/error.html
Blocked By NAXSI
Malicious Request
This Request Has Been Blocked By NAXSI.
ファイルを保存し、エディターを終了します。
次に、テキストエディタでNginx構成ファイル/etc/nginx/nginx.conf
を開きます。
sudo nano /etc/nginx/nginx.conf
NAXSI構成ファイルをNginxの構成に追加して、WebサーバーがNAXSIの使用方法を認識できるようにするには、強調表示されたコード行をnginx.conf
ファイルのhttp
セクションに挿入します。
/etc/nginx/nginx.conf
. . .
http {
include mime.types;
include /etc/nginx/naxsi_core.rules;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
default_type application/octet-stream;
. . .
次に、同じファイルのserver
セクションに、次の強調表示された行を追加します。
/etc/nginx/nginx.conf
. . .
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
include /etc/nginx/naxsi.rules;
root html;
index index.html index.htm;
}
. . .
NAXSIのコアルールと基本ルールを使用してNginxを構成したので、ファイアウォールは、Webサーバーの起動時に一致する悪意のある要求をブロックします。 次に、起動スクリプトを記述して、サーバーの再起動時にNginxが起動することを確認できます。
[[step-3 -—- creating-the-startup-script-for-nginx]] ==ステップ3—Nginxのスタートアップスクリプトを作成する
Nginxを手動でインストールしたため、次のステップは、システムのリロード時にWebサーバーを自動起動するための起動スクリプトを作成することです。
このチュートリアルでは、Systemdソフトウェアスイートを使用してスクリプトを作成します。 これを行うには、ユニットファイルを作成して(詳細についてはUnderstanding Systemd Units and Unit Filesを参照)、SystemdがNginxサービスを開始および管理する方法を構成します。
nginx.service
というファイルを作成し、テキストエディタで開きます。
sudo nano /lib/systemd/system/nginx.service
ファイルに次の行を追加します。
/lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
[Unit]
セクションは、構成しているプログラムを定義し、[Service]
は、起動時にNginxがどのように動作するかを説明し、[Install]
は、ユニットのインストールに関する情報を提供します。 これらの行をnginx.service
ファイルに追加すると、systemd
はNginxを起動する方法を認識します。
次に、Nginxには、サーバーに十分なメモリがない場合に処理する前に、受信したリクエストデータを一時的に保存するフォルダーが必要です。 ソースからNginxをインストールしたため、このデータを保存するためにNginxが使用できるディレクトリを作成する必要があります。 /var/lib/nginx
内にbody
というディレクトリを作成します。
sudo mkdir -p /var/lib/nginx/body
スタートアップスクリプトをセットアップすると、Nginxサーバーを起動できるようになります。
次のコマンドを使用して、サーバーを起動します。
sudo systemctl start nginx
サーバーがアクティブであることを確認するには、次のコマンドを実行します。
sudo systemctl status nginx
サーバーに正常に起動したことを示す次の出力が端末に表示されます。
Output● nginx.service - The NGINX HTTP and reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; disabled; vendor preset: enabled)
Active: active (running) since Mon 2018-11-05 13:59:40 UTC; 1s ago
Process: 16199 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Process: 16194 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Main PID: 16201 (nginx)
Tasks: 2
Memory: 1.3M
CPU: 17ms
CGroup: /system.slice/nginx.service
├─16201 nginx: master process /usr/sbin/ngin
└─16202 nginx: worker proces
. . .
これで、NAXSIで保護された実行中のNginxサーバーができました。 次のステップでは、シミュレートされたXSSおよびSQLインジェクション攻撃を実行して、NAXSIがサーバーを効果的に保護していることを確認します。
[[step-4 -—- testing-naxsi]] ==ステップ4—NAXSIのテスト
NAXSIモジュールが有効な状態でNginxが稼働していることをテストするには、悪意のあるHTTP要求でサーバーにアクセスして応答を分析します。
まず、サーバーのパブリックIPをコピーし、curl
コマンドを使用してNginxサーバーに悪意のある要求を行います。
curl 'http://your_server_ip/?q=">'
このURLは、q
パラメータにXSSスクリプト"><script>alert(0)</script>
を含み、サーバーによって拒否される必要があります。 以前に設定したNAXSIルールに従って、error.html
ファイルにリダイレクトされ、次の応答を受け取ります。
Output
Blocked By NAXSI
Malicious Request
This Request Has Been Blocked By NAXSI.
NAXSIファイアウォールが要求をブロックしました。
次に、次のコマンドを使用してNginxサーバーログを追跡することにより、Nginxログを使用して同じことを確認します。
tail -f /var/log/nginx/error.log
ログでは、リモートIPアドレスからのXSS要求がNAXSIによってブロックされていることがわかります。
Output2018/11/07 17:05:05 [error] 21356#0: *1 NAXSI_FMT: ip=your_server_ip&server=your_server_ip&uri=/&learning=0&vers=0.56&total_processed=1&total_blocked=1&block=1&cscore0=$SQL&score0=8&cscore1=$XSS&score1=8&zone0=ARGS&id0=1001&var_name0=q, client: your_server_ip, server: localhost, request: "GET /?q="> HTTP/1.1", host: "your_server_ip"
CTRL-C
を押してtail
を終了し、エラーログファイルの出力を停止します。
次に、今度は悪意のあるSQLインジェクションクエリを使用して、別のURLリクエストを試みます。
curl 'http://your_server_ip/?q=1" or "1"="1"'
上記のURLのor "1"="1"
部分は、データベース内のユーザーのデータを公開する可能性があり、NAXSIによってブロックされます。 ターミナルで同じ応答を生成する必要があります。
Output
Blocked By NAXSI
Malicious Request
This Request Has Been Blocked By NAXSI.
ここで、tail
を使用して、サーバーログを再度追跡します。
tail -f /var/log/nginx/error.log
ログファイルには、SQLインジェクション試行のブロックされたエントリが表示されます。
Output2018/11/07 17:08:01 [error] 21356#0: *2 NAXSI_FMT: ip=your_server_ip&server=your_server_ip&uri=/&learning=0&vers=0.56&total_processed=2&total_blocked=2&block=1&cscore0=$SQL&score0=40&cscore1=$XSS&score1=40&zone0=ARGS&id0=1001&var_name0=q, client: your_server_ip, server: localhost, request: "GET /?q=1" or "1"="1" HTTP/1.1", host: "your_server_ip"
CTRL-C
を押してログを終了します。
NAXSIは、XSSおよびSQLインジェクション攻撃を正常にブロックしました。これは、NAXSIが正しく構成され、Nginx Webサーバーが安全であることを証明します。
結論
これで、NAXSIを使用してWebサーバーを悪意のある攻撃から保護する方法の基本的な理解ができました。 Nginxの設定の詳細については、How To Set Up Nginx Server Blocks (Virtual Hosts) on Ubuntu 16.04を参照してください。 Webサーバーのセキュリティについて引き続き調査する場合は、How To Secure Nginx with Let’s Encrypt on Ubuntu 16.04とHow To Create a Self-Signed SSL Certificate for Nginx in Ubuntu 16.04を確認してください。