晴耕雨読

working in the fields on fine days and reading books on rainy days

CentOSのApacheでModSecurityを動かす

CentOSにmod_securityをインストールして、ApacheのWAFとして動作させるための方法について説明します。

ModSecurityのインストール (yum install)

mod_securityと CRS (Core Rule Set) をインストールします。

~]# yum install mod_security mod_security_crs

ModSecurityのインストール (yum localinstall)

本番環境がインターネットへの接続ができない場合は、検証環境でrpmファイルをダウンロードして、それを本番環境にインストールします。 まず、検証環境で以下のコマンドを叩いて、rpmファイルたちを .tar.gz にまとめます。

~]# mkdir mod_security
~]# yum install --downloadonly --downloaddir=./mod_security mod_security mod_security_crs
~]# tar zcvf mod_security.tar.gz ./mod_security

次に、tar.gzファイルをscpで検証環境から本番環境にコピーします。

$ scp root@検証サーバIP:/root/mod_security.tar.gz ./

$ scp mod_security.tar.gz root@本番サーバIP:~

コピーしたら、本番環境でrpmファイルをローカルインストールします。

~]# tar zxvf mod_security.tar.gz
~]# yum localinstall ./mod_security/*.rpm

ApacheでModSecurityを有効化する

mod_securityをインストールすると /etc/httpd (Apache用) や /usr/lib (Nginx用) に必要なファイルが配置されます。

ApacheでModSecurityを有効化する設定ファイルは /etc/httpd/conf.d/mod_security.conf にあります。 この設定ファイルの SecRuleEngine が On だと有効化され、Off だと無効化されます。

~]# cat /etc/httpd/conf.d/mod_security.conf
<IfModule mod_security2.c>
    # ModSecurity Core Rules Set configuration
        IncludeOptional modsecurity.d/*.conf
        IncludeOptional modsecurity.d/activated_rules/*.conf

    # Default recommended configuration
    SecRuleEngine On
    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
    ...
</IfModule>

また、ModSecurityのモジュールをロードしている設定ファイルは /etc/httpd/conf.modules.d/10-mod_security.conf にあります。

~]# cat /etc/httpd/conf.modules.d/10-mod_security.conf
LoadModule security2_module modules/mod_security2.so

<IfModule !mod_unique_id.c>
    LoadModule unique_id_module modules/mod_unique_id.so
</IfModule>

設定変更後に、モジュールが読み込まれることを確認して、httpdを再起動します。

~]# httpd -M | grep security
 security2_module (shared)

~]# systemctl restart httpd

WAF動作検証

検証のためにPHPをインストールして、パラメータをそのまま表示するphpを用意します。

~]# yum install php
~]# systemctl restart httpd
~]# cat /var/www/html/index.php
<?php echo($_REQUEST['cmd']); ?>

POSTリクエストで「'」を含めたSQLiを試みるリクエストは403で拒否されます。

~]# curl -X POST "localhost/index.php" -d "cmd=123"
123

~]# curl -X POST "localhost/index.php" -d "cmd=123'"
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>

POSTリクエストで「sleep(1)」を含めた時間に基づくブラインドアタックを試みるリクエストも403で拒否されます。

~]# curl -X POST "localhost/index.php" -d "cmd=sleep"
sleep

~]# curl -X POST "localhost/index.php" -d "cmd=sleep(1)"
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>

POSTリクエストで「<script>」を含めたXSSを試みるリクエストも403で拒否されます。

~]# curl "localhost:80/index.php?cmd=script"
script

~]# curl -X POST "localhost/index.php" -d "cmd=<script>"
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>

POSTリクエストで「curl」や「wget」などのファイル取得コマンドを含む場合も403で拒否されます。

~]# curl -X POST "localhost/index.php" -d "cmd=google.com"
google.com

~]# curl -X POST "localhost/index.php" -d "cmd=curl%20google.com"
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>

mod_securityでアクセス拒否した場合は /var/log/httpd/modsec_audit.log に拒否ログが残ります。

以上です。