Mod Security環境構築

製品紹介

オープンソースのWAFとして著名な、Mod Securityをご紹介します。
Mod Securityは、Apacheのモジュールとして動作する無償のソフトウェア型のWeb Application Firewallです。
Apacheだけでなく、Nginx、IISなどの拡張モジュールとして機能するソフトウェア型で、UNIX系、Windowsにも対応しています。
米国・シカゴに本社を置くTrustwave社が管理しており、GPLライセンスで提供されています。

数回にわけて、WAFの動作検証を行っていきます。

 

公式ホームページ

https://modsecurity.org/

 

検証内容

検証用サーバとしてLAMPサーバとMod SecurityをインストールしたWAFを構築し、クライアントPCとLAMPサーバの間にWAFを置く構成を作ります。
脆弱性があるページをLAMPサーバに配置し、アクセスします。
脆弱性があることを確認し、WAFを有効化させ、動作を検証します。

 

検証環境

VMWare Workstation 12 Plyaer
仮想サーバ2台
CentOS Linux release 7.2.1511 (Core) minimal install PKG

 

構成

Client PC
IP: 192.168.136.1

WAFサーバ
IP:192.168.136.135
パッケージ構成
Apache 2.4
mod_ssl
mod_security

 

LAMPサーバ
IP:192.168.136.136
パッケージ構成
Apache 2.4
mod_ssl
PHP 5.4.16
Maria DB 10.1.19

構成図

 

事前作業

名前解決できるよう、クライアントPCのhostsファイルにホストネームとIPアドレスを紐づけてください。

WAF 192.168.136.135
LAMP 192.168.136.136

各サーバに対して実行してください。

・SELinux一時無効化

# getenforce
Enforcing
# setenforce 0
# getenforce
Permissive

恒久的に無効化する場合は以下を修正して保存します。
vi /etc/selinux/config
~
SELINUX=disable

・firewalldインストール

# yum -y install firewalld

# systemctl enable firewalld

# systemctl start firewalld

・ntp or chronyインストール
ntpはこちらの手順を参照してください。
chronyはこちらの手順を参照してください。

 

 

 

導入手順

(インストール日時記載)2016/12/08現在の最新バージョンは2.9です。

今回はすべてyumによるバイナリインストールで導入を行います。

Mod Securityの公式ホームページに掲載されているインストール手順を参照して実施しました。

 

目次

1.LAMPサーバ構築

2.WAFサーバ構築

3.Apacheの処理とMod Securityの動作

4.Mod Securityの設定・CRSの定義確認

 

1.LAMPサーバ構築

まず、Apacheをインストールします。
こちらの手順を参照してください。

次にPHPをインストールします。
こちらの手順を参照してください。

次にMariaDBをインストールします。
こちらの手順を参照してください

最後に、いわゆるオレオレ証明書を発行して、通信をSSLにします。
こちらの手順を参照してください。

LAMPサーバの構築は以上になります。

 

2.WAFサーバ構築

Apacheをインストールします。
こちらの手順を参照してください。

それでは、Mod Securityをインストールしていきます。
まず、モジュールをインストールします。
# yum -y install mod_security

OWASPが提供するCRS(Core Rule Set)をインストールします。
# yum -y install mod_security_crs

※OWASP CRSとは
OWASP ModSecurity Core Rule Set(CRS)は、ModSecurityまたは互換性のあるWAFで使用するための一般的な攻撃検出ルールのセットです。
幅広い攻撃からWebアプリケーションを保護することを目的としています。
下記の攻撃方法に対応しています。
SQL Injection (SQLi)
Cross Site Scripting (XSS)
Local File Inclusion (LFI)
Remote File Inclusion (RFI)
Remote Code Execution (RCE)
PHP Code Injection
HTTP Protocol Violations HTTPoxy
Shellshock
Session Fixation
Scanner Detection
Metadata/Error Leakages
Project Honey Pot Blacklist
GeoIP Country Blocking

最新版を導入する場合は、ソースからインストールする必要があります。

インストールしたパッケージを確認します。
yumでインストールされるバージョンです。
# rpm -qa | grep mod_security

mod_security_crs-2.2.6-6.el7.noarch
mod_security-2.7.3-5.el7.x86_64

 

Apacheを再起動すれば、有効化されます。
# systemctl restart httpd

※速度性能を確認するにはApacheBench(Apache HTTP Serverに同梱されているベンチマークテストツール)を実行します。

下記は同時接続数10・リクエスト数100になるまでhttp://waf/にアクセスする例です。
# ab -n 100 -c 10 http://waf/
必要に応じて実施してください。

下記実行例
# ab -n 100 -c 10 http://waf/

This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.136.135 (be patient).....done

Server Software: Apache/2.4.6
Server Hostname: 192.168.136.135
Server Port: 80

Document Path: /
Document Length: 123 bytes

Concurrency Level: 10
Time taken for tests: <span style="color: #ff0000;">0.076 seconds</span>
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 41500 bytes
HTML transferred: 12300 bytes
Requests per second: <span style="color: #333333;">1315.69 [#/sec] (mean)</span>
Time per request: 7.601 [ms] (mean)
Time per request: 0.760 [ms<span style="color: #333333;">]</span> (mean, across all concurrent requests)
Transfer rate: 533.21 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 0
Processing: 1 6 11.5 2 53
Waiting: 1 6 11.5 2 52
Total: 2 6 11.5 2 53

Percentage of the requests served within a certain time (ms)
50% 2
66% 3
75% 3
80% 3
90% 35
95% 38
98% 47
99% 53
100% 53 (longest request)

通信をSSLにします。
作業手順はこちらをご確認ください。

ここで、WAFサーバのmod_proxy モジュールを有効にして、特定のコンテンツへのリクエストを別の Web サーバーに転送するリバースプロキシ機能の設定をします。
こうすることで、必ずWAFを経由してLAMPサーバに通信が向くよう設定します。

またリバースプロキシの運用では、より多数のクライアントを同時に処理することができ、クライアントあたりにスレッド1本で済ませることができるworkerが推薦されていますので、workerで動かすよう設定します。

# vi /etc/httpd/conf.modules.d/00-mpm.conf
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so(コメントインする
LoadModule mpm_worker_module modules/mod_mpm_worker.so(コメントアウトする
Apacheを再起動して有効化します。
# systemctl restart httpd

mod_proxyモジュールが有効であることを確認します。
# grep "mod_proxy" /etc/httpd/conf.modules.d/00-proxy.conf

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_express_module modules/mod_proxy_express.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

 

# httpd -M | grep proxy

proxy_module (shared)
proxy_ajp_module (shared)
proxy_balancer_module (shared)
proxy_connect_module (shared)
proxy_express_module (shared)
proxy_fcgi_module (shared)
proxy_fdpass_module (shared)
proxy_ftp_module (shared)
proxy_http_module (shared)
proxy_scgi_module (shared)
proxy_wstunnel_module (shared)

 

Apache設定ファイルに下記を追加します。
# vi /etc/httpd/conf/httpd.conf

ProxyRequests off
ProxyPreserveHost On
Order deny,allow
Allow from All
ProxyPass / https://192.168.136.136/dir
ProxyPassReverse / https://192.168.136.136/dir

SSL通信でのProxyを有効にするために、下記をSSL設定ファイルに追記します。
# cp -p /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.bk
# vi /etc/httpd/conf.d/ssl.conf
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off

WAFにアクセスして、LAMPサーバのページが表示されることを確認します。
https://WAF/index.php

 

3.Apacheの処理とMod Securityの動作

Mod Securityは、Apacheのリクエスト処理サイクルのいずれかの中で次の5つのフェーズでルールを配置できます。

phase1: Request headers (REQUEST_HEADERS)
phase2: Request body (REQUEST_BODY)
phase3: Response headers (RESPONSE_HEADERS)
phase4: Response body (RESPONSE_BODY)
phase5: Logging (LOGGING)
下記の図は、Apacheの標準的なリクエスト処理サイクルと、Mod Securityのプロセスフェーズの配置図です。

 

phase1: Request headers (REQUEST_HEADERS)
Apacheが「Request読み込み」処理を完了した直後にこのルールが適用されます。
Apache内部でModSecurityルールを使用する場合は、フェーズ2でModSecurityルールを使用する必要があります。

phase2: Request body (REQUEST_BODY)
このフェーズで、通常の入力情報を分析します。 ほとんどの場合、このルールが適用されます。
このフェーズでは、Request bodyをバッファしてModSecurityで処理します。
設定ファイルにてSecRequestBodyAccess On/Off選択できます。(デフォルトでは有効)
※データ転送されたリクエスト本体(POSTパラメータなど)を検査する場合に必要ですので、有効にしておきます。

phase3: Response headers (RESPONSE_HEADERS)
このフェーズは、レスポンスヘッダーがクライアントに返送される時にこのルールが適用されます。
その前にレスポンスを観察したい場合や、レスポンスヘッダーを使用してレスポンス本体をバッファーするかどうかを判断する場合は、このフェーズで適用します。

phase4: Response body (RESPONSE_BODY)
このフェーズで、通常の出力情報を分析します。 この時点で、レスポンスボディに対してルールが適用されます。
このフェーズでは、Response bodyをバッファしてModSecurityで処理します。
設定ファイルにてSecResponseBodyAccess On/Off選択できます。(デフォルトではOff)

phase5: Logging (LOGGING)
このフェーズは、ロギングが行われる直前にこのルールが適用され、Apacheでの処理で記録されたエラーメッセージを検査するために使用できます。
当然、このフェーズでは接続をブロックすることはできませんので、このフェーズでルールを設定することはほぼありません。。

 

4.Mod Securityの設定・CRSの定義確認

ここで、設定ファイルを確認します。
設定は /etc/httpd/conf.d/mod_security.conf に記載されています。
インストールした CRS(ルール)を全て読み込む設定がされているので、利用するルールを選択します。
ルールは /etc/httpd/modsecurity.d/ ディレクトリ内にあるので読み込みたいルールを記述することで、セットアップできます。

※いったんここでは、WAFの機能を無効化しておきます。SecRuleEngine OnをOffにしてください。

/etc/httpd/conf.d/mod_security.conf
======================================

# ModSecurity Core Rules Set configuration(ここでは、一例としてsqlインジェクションとXSSのルールセットを有効化し、それ以外は無効化します。)
IncludeOptional modsecurity.d/*.conf
#Include modsecurity.d/activated_rules/*.conf(コメントアウト=無効化)
Include modsecurity.d/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf(sqlインジェクションルールセット有効化)
Include modsecurity.d/activated_rules/modsecurity_crs_41_xss_attacks.conf(XSSルールセット有効化)

# Default recommended configuration
SecRuleEngine Off(←この項目で「On=有効/Off=無効/DetectionOnly=検知のみ」を設定)
SecRequestBodyAccess On
SecRule REQUEST_HEADERS:Content-Type "text/xml" \
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyInMemoryLimit 131072
SecRequestBodyLimitAction Reject
SecRule REQBODY_ERROR "!@eq 0" \
"id:'200001', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
"id:'200002',phase:2,t:none,log,deny,status:44,msg:'Multipart request body \
failed strict validation: \
PE %{REQBODY_PROCESSOR_ERROR}, \
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
DB %{MULTIPART_DATA_BEFORE}, \
DA %{MULTIPART_DATA_AFTER}, \
HF %{MULTIPART_HEADER_FOLDING}, \
LF %{MULTIPART_LF_LINE}, \
SM %{MULTIPART_MISSING_SEMICOLON}, \
IQ %{MULTIPART_INVALID_QUOTING}, \
IP %{MULTIPART_INVALID_PART}, \
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"

SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
"id:'200003',phase:2,t:none,log,deny,status:44,msg:'Multipart parser detected a possible unmatched boundary.'"

SecPcreMatchLimit 1000
SecPcreMatchLimitRecursion 1000

SecRule TX:/^MSC_/ "!@streq 0" \
"id:'200004',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"

SecResponseBodyAccess Off
SecDebugLog /var/log/httpd/modsec_debug.log
SecDebugLogLevel 0
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/httpd/modsec_audit.log(←ログファイル)
SecArgumentSeparator &
SecCookieFormat 0
SecTmpDir /var/lib/mod_security
SecDataDir /var/lib/mod_security

======================================
ルールの書式設定を簡単に紐解いていきます

・SecDefaultAction
ルールにマッチした際のデフォルトのアクションを定義します。
書式:SecDefaultAction "action1,action2,action3“
作成例:SecDefaultAction "phase:2,log,auditlog,deny,status:403,tag
→リクエストボディフェーズで処理を停止しログを記録して 403 を返す

・SecRule
選択した演算子を使用して選択した変数を分析するルールを作成・定義します。
書式:SecRule VARIABLES OPERATOR [ACTIONS]
VARIABLES=チェックを実行する変数
OPERATOR=フィルタリングルール
[ACTIONS]=ルールにマッチした場合のアクションを指示
作成例:SecRule ARGS "@rx attack" "phase:1,log,deny,id:1"
→正規表現のパターンマッチングで「attack」が含まれる引数のリクエストをログに記載し、拒否する。ルールIDは1とする。

・ID
ルールのIDをアサインします。しかし、番号によってはすでにアサインされているものもあります。
1–99,999:ローカルで定義可能な番号
100,000–199,999:Oracleで予約されているID
など、様々あります。

・phase
ルール適用する処理を定義します。
SecDefaultAction "phase:1,deny,log"
→ログに記録し、拒否する※こちらはCRSの設定ファイル(/etc/httpd/modsecurity.d/modsecurity_crs_10_config.conf)に記載されています。
バージョン2.7以降、下記フェーズ番号をもったエイリアスが存在します。

ルールセット(CRS)はこちらに格納されています。
※/etc/httpd/modsecurity.d/activated_rules ディレクトリには下記へのリンクが配置されています。
/usr/lib/modsecurity.d/base_rules
modsecurity_35_bad_robots.data
modsecurity_35_scanners.data
modsecurity_40_generic_attacks.data
modsecurity_41_sql_injection_attacks.data
modsecurity_50_outbound.data
modsecurity_50_outbound_malware.data
modsecurity_crs_20_protocol_violations.conf
modsecurity_crs_21_protocol_anomalies.conf
modsecurity_crs_23_request_limits.conf
modsecurity_crs_30_http_policy.conf
modsecurity_crs_35_bad_robots.conf
modsecurity_crs_40_generic_attacks.conf
modsecurity_crs_41_sql_injection_attacks.conf
modsecurity_crs_41_xss_attacks.conf
modsecurity_crs_42_tight_security.conf
modsecurity_crs_45_trojans.conf
modsecurity_crs_47_common_exceptions.conf
modsecurity_crs_48_local_exceptions.conf.example
modsecurity_crs_49_inbound_blocking.conf
modsecurity_crs_50_outbound.conf
modsecurity_crs_59_outbound_blocking.conf
modsecurity_crs_60_correlation.conf

OWASP(The Open Web Application Security Project)はWebアプリケーション開発者の助けとなるよう、アプリケーションのセキュリティを高めるためのツールやフレームワークやガイドラインを提供する活動をしています。

GithubにあるMod Security公式ドキュメントにも詳細が記載されていますので、合わせてご確認ください。
https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual
Mod Security検証ページへ