apacheのリバースプロキシ+mod_securityでリバースプロキシ型WAFを簡単に作ってみました。
■ネットワーク図
■説明
今回、リバースプロキシ型WAFを作ってみたかったのでapacheに組み込めるmod_securityとapacheで作ってみました。
例えば、これで攻撃者から攻撃を受けたとしてもリバースプロキシのWAFで防御できるためWAFで防御できたものであればバックにあるWebサーバには影響が出ないようになります。
また、初期導入時の事を考えて最初はブロックせず検知のみにします。
# 最初からブロックしてしまうと正規のアクセスであってもWAFのルールにひかかってブロックされてしまうからです。
# そのため、最初は検知のみにして誤検知があった場合はそのルールを外しながらしばらく様子を見ます。
そこで、リアルタイムにログを監視する「swatch」を導入しmod_securityで検知したログはメールで飛ばす事にします。
ちなみに、今回SSLは利用(設定)しません。
■使用OS
CentOS 5.6 64bit
注)OSのインストール方法は、以下アドレスの通りにしています。
http://www.kurobuti.com/linuxserver/index.php?option=com_content&view=artic
le&id=68&Itemid=74
■httpdバージョン
httpd-2.2.17
■mod_securityバージョン
modsecurity-apache_2.5.13
■swatchバージョン
swatch-3.2.3
※最新版は下記URLを参照してください。
http://sourceforge.net/projects/swatch/
■URL
http://www.example.com/
■リバースプロキシサーバ
Host: example
WAN IP: 192.168.0.60
LAN IP: 192.168.1.60
■Webサーバ
Host: example2
LAN IP:192.168.1.71
※Webサーバは構築済みとします。
(1)apacheをインストール
http://www.kurobuti.com/blog/?p=3365
※specファイルを使用してrpmでインストールします。上記URLを参照してください。
(2)apacheの設定
[root@example ~]# cd /etc/httpd/conf [root@example conf]# mv httpd.conf httpd.conf.bak [root@example conf]# vi httpd.conf # ServerRoot ServerRoot "/etc/httpd" # Listen Port Listen 80 # User and Group User apache Group apache # Load Modules #LoadModule alias_module /usr/lib64/httpd/modules/mod_alias.so LoadModule proxy_module /usr/lib64/httpd/modules/mod_proxy.so LoadModule proxy_http_module /usr/lib64/httpd/modules/mod_proxy_http.so LoadModule log_config_module /usr/lib64/httpd/modules/mod_log_config.so LoadModule authz_host_module /usr/lib64/httpd/modules/mod_authz_host.so # mod_security Include conf/mod_security.d/mod_security.conf <IfModule mod_proxy.c> ProxyRequests Off </IfModule> <Proxy *> Order allow,deny Allow from all </Proxy> # Log Setting ErrorLog "logs/error_log" LogLevel warn LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined CustomLog "logs/access_log" combined <VirtualHost *:80> ServerName www.example.com ProxyPass / http://www.example.com/ ProxyPassReverse / http://www.example.com/ </VirtualHost> [root@example ~]# vi /etc/hosts 192.168.1.71 www.example.com
(3)mod_securityインストール
http://www.kurobuti.com/blog/?p=3554
※インストール方法は上記URLの(4)までを参照してください。
※ただ、ここで必要なパッケージは以下だけのものです。
[root@example ~]# yum -y install curl curl-devel libxml2 libxml2-devel lua lua-devel
(4)mod_securityの最新版ルールをダウンロード
ルールをダウンロードするのに必要なperlモジュールをCPANからインストールします。
※CPANでproxyを使いたい場合は下記URLを参照してください。
http://www.kurobuti.com/linuxserver/index.php?option=com_content&view
=article&id=41%3Acpanftpproxy&catid=2%3A2010-05-13-11-40-22&Itemid=2
[root@example ~]# cd modsecurity-apache_2.5.13/tools/ [root@example tools]# cpan -i LWP::UserAgent [root@example tools]# cpan -i LWP::Protocol::https [root@example tools]# ./rules-updater.pl -rhttp://www.modsecurity.org/autoupdate/repository/ -prules -Smodsecurity-crs
(5)mod_securityの設定
[root@example tools]# cd rules/modsecurity-crs/ [root@example modsecurity-crs]# unzip modsecurity-crs_2.1.2.zip [root@example modsecurity-crs]# mkdir /etc/httpd/conf/mod_security.d [root@example modsecurity-crs]# cp -r base_rules/ /etc/httpd/conf/mod_security.d/ [root@example modsecurity-crs]# cp -r optional_rules/ /etc/httpd/conf/mod_security.d/ [root@example modsecurity-crs]# cp modsecurity_crs_10_config.conf.example /etc/httpd/conf/mod_security.d/modsecurity_crs_10_config.conf [root@example modsecurity-crs]# vi /etc/httpd/conf/mod_security.d/mod_security.conf # Load File. LoadFile /usr/lib64/libxml2.so LoadFile /usr/lib64/liblua-5.1.so # LoadModule LoadModule unique_id_module /usr/lib64/httpd/modules/mod_unique_id.so LoadModule security2_module /usr/lib64/httpd/modules/mod_security2.so # Log File. SecAuditEngine On SecAuditLog On SecAuditLog logs/mod_security_audit.log <IfModule mod_security2.c> Include conf/mod_security.d/base_rules/*.conf Include conf/mod_security.d/modsecurity_crs_10_config.conf </IfModule> [root@example modsecurity-crs]# vi /etc/httpd/conf/mod_security.d/modsecurity_crs_10_config.conf #SecRuleEngine DetectionOnly # ↓ コメントアウト削除 SecRuleEngine DetectionOnly # 検知のみ。ブロックの場合は「ON」にする。 SecRequestBodyAccess On # POSTを解析する。 SecResponseBodyAccess Off # POSTに対する応答を解析しない。 SecDefaultAction "phase:2,deny,log" # ↓ 変更 SecDefaultAction "phase:2,deny,log,auditlog,status:406"
(6)apacheを起動
[root@example conf]# service httpd start httpd を起動中: [ OK ] [root@example conf]# chkconfig httpd on適当にリバースプロキシにアクセスして「mod_security_audit.log」にログが出力されているか確認する。
※Webサーバのaccess_logに出力されるソースIPはリバースプロキシのものとなってしまうのでmod_securityインストールページの一番最後にかかれている項目を確認してください。
(7)swatchのダウンロード
[root@example ~]# wget http://sourceforge.net/projects/swatch/files/swatch/3.2.3/swatch-3.2.3.tar.gz/download
(8)swatchのインストール
[root@example ~]# mv swatch-3.2.3.tar.gz /usr/local/src/ [root@example ~]# cd /usr/local/src/ [root@example src]# tar zxvf swatch-3.2.3.tar.gz [root@example src]# cd swatch-3.2.3 [root@example swatch-3.2.3]# cpan -i Date::Calc [root@example swatch-3.2.3]# cpan -i Date::Parse [root@example swatch-3.2.3]# cpan -i Date::Manip [root@example swatch-3.2.3]# cpan -i File::Tail [root@example swatch-3.2.3]# cpan -i Time::HiRes [root@example swatch-3.2.3]# perl Makefile.PL Looks good Writing Makefile for swatch [root@example swatch-3.2.3]# make [root@example swatch-3.2.3]# make install※ここでもCPANを使用してperlモジュールをインストールします。
(9)swatchの設定
[root@example ~]# mkdir -p /etc/swatch/log_watch [root@example ~]# vi /etc/swatch/swatch.conf # About a setting method of swatch. # # The destination of Log watch config. # -- /etc/swatch/log_watch # # Log watch config file name. # Example # -- /etc/swatch/log_watch/hogehoge.conf # # Creating a Form Configuration File. # Example File # -- # vi /etc/swatch/log_watch/hogehoge.conf # # The contents of the configuration file # # appoint log to watch. # # |/var/log/messages # CommentOut and Pipe /Log path/log file. # # watchfor /error/i # Monitoring character string. # echo # acction. # mail root,subject=example # acction. # SWATH Log File. SWATCH_LOG='/var/log/swatch.log' # Script Directory. SCRIPT_DIR='/tmp' # PID Directory. PID='/var/run' # Lock File. LOCK='/var/lock/subsys/swatch' [root@example ~]# vi /etc/swatch/log_watch/mod_security.conf # appoint log to watch. # |/var/log/httpd/mod_security_audit.log watchfor /Pattern match/i echo mail root,subject=Detection_notification [root@example ~]# vi /etc/logrotate.d/swatch /var/log/swatch.log { compress delaycompress missingok }
(10)swatchの起動スクリプト作成
[root@example ~]# vi /etc/rc.d/init.d/swatch #!/bin/sh # # swatch # # description: swatch start/stop script. # chkconfig: 2345 90 35 # # Source function library. . /etc/rc.d/init.d/functions CONF=/etc/swatch/swatch.conf WATCH_CONF=/etc/swatch/log_watch prog=swatch # Config File Check. if [ -f $CONF ] ; then . $CONF else exit 1 fi start () { RETVAL=0 [ -x /usr/local/bin/swatch ] || exit 1 for LOG_CONF in $( find $WATCH_CONF | grep conf ) ; do WATCH_LOG=`grep \| $LOG_CONF | cut -d \| -f 2` /usr/local/bin/swatch --config $LOG_CONF --tail-file $WATCH_LOG \ --script-dir=$SCRIPT_DIR --awk-field-syntax --use-cpan-file-tail \ --daemon --pid-file $PID/swatch_`find $WATCH_CONF | grep $LOG_CONF | \ cut -d / -f 5 | awk -F . '{print $1}'`.pid >> $SWATCH_LOG 2>&1 if [ $? -ne 0 ] ; then let RETVAL=RETVAL+1 fi done if [ $RETVAL -eq 0 ] ; then echo -n $"Starting $prog: " && success echo "" touch $LOCK else echo -n $"Starting $prog: " && failure echo "" exit 1 fi } stop () { RETVAL=0 for PID_FILE in $( find $PID | grep swatch ) ; do [ -f $PID_FILE ] && kill `cat $PID_FILE` > /dev/null 2>&1 if [ $? -eq 0 ] ; then rm $PID_FILE > /dev/null 2>&1 else let RETVAL=RETVAL+1 fi done if [ $RETVAL -eq 0 ] ; then echo -n $"Stopping $prog: " && success echo "" rm $LOCK else echo -n $"Stopping $prog: " && failure echo "" exit 1 fi } stats() { for PID_FILE in $( find $PID | grep swatch ) ; do [ -f $PID_FILE ] && echo `echo $PID_FILE | awk -F / '{print $4}'` `cat $PID_FILE` done } case $1 in start ) start ;; stop ) stop ;; restart ) stop ; sleep 1 ; start ;; stats ) stats ;; * ) echo $"Usage: $0 {start|stop|stats}" ;; esac
(11)swatchを起動
[root@example ~]# chmod +x /etc/rc.d/init.d/swatch [root@example ~]# service swatch start swatch を起動中: [ OK ] [root@example ~]# chkconfig swatch on [root@example ~]# ps aux | grep swatch root 24552 0.0 1.0 102220 10832 ? Ss 02:52 0:00 /usr/bin/swatch --config /etc/swatch/log_watch/mod_security.conf --tail-file /var/log/httpd/mod_security_audit.log --script-dir=/tmp -
(12)適当な攻撃をしてみて、検知されたメールが送信されるか確認
XSSでもしてみる。
http://www.example.com/?<script>alert</script>
これで、検知されてメールがroot宛てに届くはず。
後は、正規アクセスで引っかかったやつをホワイトリストに設定すれば大丈夫です。
ホワイトリストは参考文献「3」に例が書かれています。
参考文献
1. http://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Main_Page
2. https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set
_Project#tab=Download
3. http://laquan.hostzi.com/techbox/httpd.html
4. http://webos-goodies.jp/archives/51261261.html
5. http://unixlife.jp/unixlife/linux/t-swatch.jsp