連載
» 2014年09月18日 17時47分 公開

NginxをWebサーバー“以外”でも徹底活用するこれから始める人のためのNginx(3)(4/4 ページ)

[鶴長鎮一,@IT]
前のページへ 1|2|3|4       

NginxでWAF(Webアプリケーションファイアウォール)を実現

 Webページの改ざんや情報漏えいなど、Webにまつわるセキュリティインシデントが数多く報告されています。攻撃手法もバッファオーバーフロー、クロスサイトスクリプティング、SQLインジェクション、ディレクトリトラバーサルなど多岐に渡ります。こうした攻撃からWebサーバーを保護するのがWAF(Webアプリケーションファイアウォール)の役割です。

 Apache HTTPDは拡張モジュールのmod_securityをインストールすることでWAFとして機能させることができます。Nginxも同じようにmod_securityのインストールが可能です。mod_securityを使えば次のようなことが可能になります。

  • HTTPリクエストがサーバーで処理される前に、監査を実施できる
  • フォームデータ、リクエストヘッダーの中身など、監査対象を細かく設定できる
  • 監査ルールに引っ掛かった際の動作を細かく設定できる
  • 監査内容に、正規表現を使用できる
  • HTTPレスポンスに対して、監査を実施できる
  • 監査ログを記録できる

 ただし、mod_securityはサードパーティ製モジュールなので、Nginxのソースファイルを用意し再ビルドする必要があります。

mod_securityを含んだRPMファイルの作成

 今回、公式サイトのRPMファイルを使ってNginxをインストールしているため、mod_securityを含んだRPMファイルを自作し、アップデートすることにします。RPMファイルを自作するには、元になるSRPMファイルをインストールした後、SPECファイルを修正し、rpmbuildコマンドでRPMファイルを作成します。

1)RPMの作成やmod_securityのビルドに必要な開発ツールやライブラリをインストールする

# yum groupinstall 開発ツール
# yum install httpd-devel apr apr-devel apr-util apr-util-devel pcre pcre-devel libxml2 libxml2-devel curl curl-devel openssl-devel git

2)mod_securityのソースファイルをGitHubからダウロードしビルドする

作業ディレクトリに「/tmp」を使用しています。

# cd /tmp
# git clone https://github.com/SpiderLabs/ModSecurity.git mod_security
# cd mod_security/
# ./autogen.sh 
# ./configure --enable-standalone-module
# make

3)SRPM(ソースRPM)をNginx社の公式サイトからダウンロードしインストールする

# cd /tmp
# rpm -ivh http://nginx.org/packages/mainline/centos/7/SRPMS/nginx-1.7.4-1.el7.ngx.src.rpm
(*バージョンは2014年9月現在のもの)

4)RPMを自作するには、SRPMに含まれるspecファイルを修正し、ビルドオプションをパラメーター変更する

 先ほど作成したmod_securityを取り込むよう「/tmp/rpmbuild/SPECS/nginx.spec」を修正し、configureの「--add-module」オプションでmodsecurityのパスを指定するようにします。以上の手順でmod_securityモジュールが追加されます。

./configure \	<--87行目あたり
...省略...
        --add-module=/tmp/mod_security/nginx/modsecurity \		<--追加
        $*
./configure \	<--126行目あたり
...省略...
        --add-module=/tmp/mod_security/nginx/modsecurity \		<--追加
        $*
(*行数はnginx-1.7.4-1.el7.ngx.src.rpmのもの)
「/tmp/rpmbuild/SPECS/nginx.spec」を編集

5)修正したspecファイルに対しrpmbuildコマンドを実行し、自家製RPMファイルをビルドする

 ビルドに成功した後、rpmコマンドでパッケージをアップデートします。

# rpmbuild -ba nginx.spec
# cd /tmp/rpmbuild/RPMS/x86_64/
# rpm -Uvh nginx-1.7.4-1.el7.centos.ngx.x86_64.rpm
(*バージョンは2014年9月現在のもの)

mod_securityの設定

 mod_securityの設定は「/etc/nginx/modsecurity.conf」ファイルで行います。動作を確認するため図6のような内容で新規に作成します。

#基本設定

SecRuleEngine On

SecRequestBodyAccess On

SecResponseBodyAccess Off

#デフォルトアクションの指定

SecDefaultAction phase:2,log,auditlog,deny

#デバッグログ

SecDebugLog /var/log/nginx/modsec_debug.log

SecDebugLogLevel 3

#監査ログ

SecAuditEngine RelevantOnly

SecAuditLog /var/log/nginx/modsec_audit.log

#監査ルールの設定

#IPアドレスをチェック

SecRule REMOTE_ADDR "^10\.0\.0\.[0-9]{1,3}$" "log,deny,id:1"

SecRule REMOTE_ADDR "^192\.168\.[0-9]{1,3}\.[0-9]{1,3}$" "log,deny,id:2"

#GETメソッドパラメータをチェック

SecRule ARGS_GET "atack" "log,deny,id:3"

#POSTメソッドパラメータをチェック

SecRule ARGS_POST "evil" "log,deny,id:4"

#GET/POSTともにチェック

SecRule ARGS "(\"|>|<|'|script|onerror)" "log,deny,id:5"

SecRule ARGS "foo" "log,pass,id:6"

図6 「/etc/nginx/modsecurity.conf」ファイルでmod_securityを設定

 図6において、最初にmod_securityを有効にするため「SecRuleEngine」ディレクティブで「On」を指定しています。次に「SecRequestBodyAccess On」でクライアントからサーバーに送信されるデータ(リクエストデータ)に対し監査を実施するようにします。サーバーからクライアントへ送信されるデータ(レスポンスデータ)に対して監査を実施するには、「SecResponseBodyAccess On」とします、今回は不要なため「Off」にしています。

 監査処理で疑わしいものが見つかった場合の対処方法は、監査ルールを定める際に同時に指定しますが、デフォルトの対処方法を「SecDefaultAction」で指定しておくことができます。「SecDefaultAction phase:2,log,auditlog,deny」と指定した場合、Nginxのエラーログと監査ログへの記録の後、アクセスを拒否します。「phase:2」は動作タイミングを表しており、この場合はクライアントからのリクエストを受け付けた後監査ルール毎(サーバーからレスポンスを返す前)になります。

 デバッグログは、動作を確認する際に利用します。「SecDebugLog」で出力先ログファイルを指定し、「SecDebugLogLevel」でデバッグレベルを指定します。レベルは「0〜9」まで指定可能で、「0」を指定すると何も出力しません。数字が上がるほど出力される情報が多くなり、「9」で全ての情報を出力します。

 監査を実施した記録を残すために、「SecAuditEngine」ディレクティブで「RelevantOnly」を指定します。「SecAuditEngine On」とした場合全ての監査記録が出力されます。監査に引っ掛かったものだけ出力するために「RelevantOnly」を指定します。

 監査ルールの設定は「SecRule」ディレクティブで行います。「SecRule 監査対象 一致内容 アクション」のように指定します。

動作確認(監査ルールの設定方法)

 設定終了後、Nginxを再起動します。その後、監査ログ用のファイル「modsec_audit.log」とデバッグログ用のファイル「modsec_debug.log」が作成されていることを確認します。

# ls /var/log/nginx/
modsec_audit.log  modsec_debug.log

 監査ルールの設定方法を、監査ログを見ながら解説します。図6の「SecRule REMOTE_ADDR ...」では、クライアントのIPアドレスでアクセスを制限しています。

 アクセス制限の範囲は、IPアドレスやホスト名を正規表現を使って指定します。アクションに「"log,deny"」を指定しているため、ログファイルへの記録と、アクセス拒否が実行されます。末尾の「id:1」はルール番号です。設定した監査ルールごとに一意なIDを指定します。指定したIPアドレスのクライアントから実際にアクセスを試し、アクセスできないことを確認します。

 次に「modsec_audit.log」に監査ログが出力されていることを確認します。監査ログには監査対象にマッチしたパターンや、どのタイミングで監査が実施されたかなどが出力されます。

--e3de6d6c-H--

Message: Access denied with code 403 (phase 2). Pattern match "^10\.0\.0\.[0-9]{1,3}$" at REMOTE_ADDR. [file "/etc/nginx/modsecurity.conf"] [line "20"] [id "11"]

Message: Audit log: Failed to lock global mutex: Permission denied

Action: Intercepted (phase 2)

Apache-Handler: IIS

Stopwatch: 1409603540000454 455248 (- - -)

Stopwatch2: 1409603540000454 455248; combined=74, p1=5, p2=60, p3=0, p4=0, p5=9, sr=0, sw=0, l=0, gc=0

Producer: ModSecurity for nginx (STABLE)/2.8.0 (http://www.modsecurity.org/).

Server: ModSecurity Standalone

Engine-Mode: "ENABLED"

--e3de6d6c-Z--


 監査ルールを「SecRule ARGS_GET "atack" "log,deny,..."」と設定すると、GETメソッドを使ったフォームデータの中に、「atack」という文字列を見つけた場合に、ログへの記録とアクセス拒否を実施するようになります。「http://サーバーのアドレス/index.html?key=atack」のように、GETメソッドパラメータをURLに付け加えアクセスします。するとアクセスが拒否され、監査ログに記録されるのを確認できます。

 POSTメソッドを使ったフォームデータに対して監査ルールを設定するには、「SecRule ARGS_POST "evil" "log,deny,..."」のようにします。先ほどGETメソッドでの監査ルールには「ARGS_GET」を使用しましたが、POSTメソッドでは「ARGS_POST」を使用します。この設定ではPOSTメソッドを使ったフォームデータ中に、文字列「evil」が含まれていた場合に、ログへの記録とアクセス拒否を実施します。

 設定を確認するには、フォームデータをPOSTメソッドでサーバーに送信できるよう、図7ようなWebフォームを「/usr/share/nginx/html/test.html」として作成します。作成したWebフォームにアクセスするには、URLに「http://サーバーのアドレス/test.html」を指定します。表示されたWebフォームのテキストフィールドに「evil」とタイプし、送信ボタンをクリックすれば、アクセスが拒否され監査ログに記録されるのを確認できます。

<html>

<body>

<form action=/cgi-bin/not_found.cgi method=post> <--CGIファイルは実在しなくてもテスト可能

<input type=text name=test>

<input type=submit>

</form>

</body>

</html>

図7 POSTメソッドで悪意のあるデータを送信するのに使用するWebフォーム(/usr/share/nginx/html/test.html)

 POST/GETメソッドのどちらにも対応する監査ルールを設定するには、「SecRule ARGS ...」とします。監査ルールに引っ掛かった際に、ログの記録だけ行い接続を許可するには、アクションの指定で「"log,pass"」とします。

 以上のように、mod_securityは細かな内容を設定できるため、記述が複雑です。SQLインジェクション対策ではSQLクエリとして有害な文字列を監視する必要があります。その他にもさまざまな攻撃を想定し、条件を設定する必要があります。そうした有害な文字列を全て列挙するのは大変な作業です。

 そこで、あらかじめ用意されたルールセットの「ModSecurity Core Rule Set」(CRS)を利用します。CRSは「http://www.modsecurity.org/」からダウンロードできます。

連載の終わりに寄せて

 3回にわたりNginxについて解説しました。Webサーバーで大きなシェアを誇るApache HTTPDも、epollシステムコールに対応するなど、パフォーマンスの面でNginxと肉薄する場面が多くなっていますが、Apache、Nginxともに一長一短あります。

 Nginxの長所は、サーバーリソースにおける消費の少なさ、設定ファイルなどメンテナンスにかかる労力の軽さといった軽量さです。一方Apacheの長所は機能とパフォーマンスのバランスの良さです。それぞれの長所を生かしながら、適材適所でWebサーバーを選択するようにしてください。

 Nginxも商用サポートを開始するなど、今後ますますの普及が期待されています。

参考:

鶴長 鎮一著「サーバ構築の実際がわかる Apache[実践]運用/管理 (Software Design plus)」技術評論社


鶴長 鎮一(つるなが しんいち)

愛知県出身、東京都在住。1970年生まれ。大学在学中から地元ISPの立ち上げに係わり、紆余曲折を経て通信キャリアに勤務。企画からコーディングやインフラ構築まで幅広い業務に従事。@ITには2001年から数多くの記事を寄稿。その他、Software Design(技術評論社)や日経Linuxでの連載をはじめ、著書に『サーバ構築の実際がわかる Apache[実践]運用/管理』(技術評論社)、『rsyslog 実践ログ管理入門』(技術評論社)、『MySQL徹底入門 第3版』(翔泳社/共著)、『PHPによるWebアプリケーションスーパーサンプル〜リッチクライアント編〜』(ソフトバンククリエイティブ/共著)ほか多数。


前のページへ 1|2|3|4       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。