備忘録

Apacheのmod_rewriteを使って簡易WAFの実装

脆弱性を悪用した攻撃から守るるためにApacheのmod_rewriteを使って簡易WAFを実装してみました

簡易WAF

/etc/httpd/conf.d/00-security.inc

ファイルを作成して以下の内容を設定

<IfModule mod_rewrite.c>
    ### REQUEST_METHOD ###
    RewriteCond %{REQUEST_METHOD}  ^(HEAD|TRACE|DELETE|TRACK) [NC]
    RewriteRule ^(.*)$ - [R=400,L]

    ### THE_REQUEST ###
    RewriteCond %{THE_REQUEST} ^.*(\\r|\\n|%0A|%0D).* [NC]
    RewriteRule ^(.*)$ - [R=400,L]

    ### HTTP_REFERER ###
    RewriteCond %{HTTP_REFERER} ^(.*)(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC]
    RewriteRule ^(.*)$ - [R=400,L]

    ### HTTP_COOKIE ###
    RewriteCond %{HTTP_COOKIE} ^.*(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC]
    RewriteRule ^(.*)$ - [R=400,L]

    ### REQUEST_URI ###
    RewriteCond %{REQUEST_URI} ^.*(,|;|:|<|>|">|"<|\.\.\.).*     [NC,OR]
    RewriteCond %{REQUEST_URI} ^.*(\=|\@|\[|\]|\^|\`|\{|\}|\~).* [NC,OR]
    RewriteCond %{REQUEST_URI} ^.*(\'|%0A|%0D|%27|%3C|%3E|%00).* [NC]
    RewriteRule ^(.*)$ - [R=400,L]

    ### HTTP_USER_AGENT ###
    RewriteCond %{HTTP_USER_AGENT} ^$                                                              [OR]
    RewriteCond %{HTTP_USER_AGENT} ^.*(<|>|'|%0A|%0D|%27|%3C|%3E|%00).*                            [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^.*(HTTrack|clshttp|archiver|loader|email|nikto|miner|python).* [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^.*(winhttp|libwww\-perl|curl|wget|harvest|scan|grab|extract).* [NC]
    RewriteRule ^(.*)$ - [R=400,L]

    ### QUERY_STRING ###
    RewriteCond %{QUERY_STRING} base64_encode.*(.*)                                                    [NC,OR]
    RewriteCond %{QUERY_STRING} ^.*(\<|%3C).*script.*(\>|%3E)                                          [NC,OR]
    RewriteCond %{QUERY_STRING} ^.*(localhost|loopback|127\.0\.0\.1).*                                 [NC,OR]
    RewriteCond %{QUERY_STRING} ^.*(;|<|>|'|"|%0A|%0D|%00).*                                           [NC,OR]
    RewriteCond %{QUERY_STRING} ^.*(md5|benchmark|union|select|insert|cast|decldrop|update|alter).*    [NC]
    RewriteRule ^(.*)$ - [R=400,L]

    ### REMOTE_ADDR ###
#   RewriteCond %{REMOTE_ADDR} ^999\.999\.999\.999$ [OR]
#   RewriteCond %{REMOTE_ADDR} ^999\.999\.999\.999$
#   RewriteRule ^(.*)$ - [R=400,L]
</IfModule>

※簡易WAFは環境によっては誤検知する場合があるので調整ください。

/etc/httpd/conf.d/11-ip.conf

VirtualHostに先程作成した簡易WAFをInclude

<VirtualHost XXX.XXX.XXX.XXX:80>
    ServerName XXX.XXX.XXX.XXX
    DocumentRoot /var/www/ip/html

    <Directory /var/www/ip>
        AllowOverride none
        Options None
        Require all denied
    </Directory>

    <Directory /var/www/ip/html>
        Require method GET POST
        Options FollowSymLinks
        RewriteEngine On

        ### 簡易WAF ###
        Include conf.d/00-security.inc
    </Directory>

    <Directory /var/www/ip/html/phpMyAdmin>
        RewriteCond %{HTTPS} off
        RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

        ### IP制限 ###
        <RequireAll>
            <RequireAny>
                Require all denied
                Require ip 999.999.999.999
            </RequireAny>
            Require method GET POST
        </RequireAll>
    </Directory>

    CustomLog logs/ip_access_log combined_tab env=!nolog
    ErrorLog logs/ip_error_log
</VirtualHost>

※「XXX.XXX.XXX.XXX」はサーバのIPアドレスを設定します。
「999.999.999.999」は接続元(会社/自宅等)のIPアドレスを設定します。

/etc/httpd/conf.d/51-ip-ssl.conf

SSLのVirtualHostにも先程作成した簡易WAFをInclude

<VirtualHost XXX.XXX.XXX.XXX:443>
    ServerName XXX.XXX.XXX.XXX
    DocumentRoot /var/www/ip/html

    SSLEngine on
    SSLVerifyClient none
    SSLCompression off
    SSLHonorCipherOrder on

#    SSLProtocol all -SSLv3
#    SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4

    SSLProtocol ALL -SSLv2 -SSLv3
    SSLCipherSuite HIGH:!aNULL:!eNULL:!DH:!3DES

    SSLCertificateKeyFile /etc/tls/apache.key
    SSLCertificateFile /etc/tls/apache.crt

    Header always set Strict-Transport-Security "max-age=31536000"

    <Directory /var/www/ip>
        AllowOverride none
        Options None
        Require all denied
    </Directory>

    <Directory /var/www/ip/html>
        Require method GET POST
        Options FollowSymLinks
        RewriteEngine On

        ### 簡易WAF ###
        Include conf.d/00-security.inc
    </Directory>

    <Directory /var/www/ip/html/phpMyAdmin>
        ### ベーシック認証・IP制限 ###
        AuthType Basic
        AuthName "Input ID and Password."
        AuthUserFile /var/www/ip/.htpasswd
        <RequireAll>
            <RequireAny>
                Require all denied
                Require ip 999.999.999.999
            </RequireAny>
            Require method GET POST
            Require valid-user
        </RequireAll>
    </Directory>

    CustomLog logs/ip_ssl_access_log combined_tab env=!nolog
    ErrorLog logs/ip_ssl_error_log
</VirtualHost>

※「XXX.XXX.XXX.XXX」はサーバのIPアドレスを設定します。
「999.999.999.999」は接続元(会社/自宅等)のIPアドレスを設定します。

シンタックスチェック

# service httpd configtest

Syntax OK

※シンタックスエラーがないことを確認

設定ファイルの再読み込み

# systemctl reload httpd.service

簡易WAF実装の確認

「http://サーバのIPアドレス/?union+select」にアクセスして、「HTTPステータスコード=400」となればOKです。

「https://サーバのIPアドレス/?union+select」にアクセスして、「HTTPステータスコード=400」となればOKです。