Apache Mod Security で基本的なセキュリティ設定を行う
ApacheのMod Securityを使用しリクエストサイズ制限やサーバ情報削除設定など基本的なセキュリティ対策を行う
目次
1.概要
2.構成図
3.前提
4.Mod Securityインストール
5.Apache設定
6.Mod Security設定ファイル編集
7.Mod Security設定適用
8.設定確認
1.概要
ApacheのMod Securityを使用し、設定ファイルの設定にてリクエストサイズ制限やサーバ情報削除設定などの基本的なセキュリティ対策を行う。
2.構成図
構成図は以下の通り。
OS | CentOS 7 |
Apache | 2.4.46 |
apr | 1.6.5 |
apr-util | 1.6.1 |
mod security | 2.9.3 |
3.前提
・OSがCentOSであること
・Apacheがインストールされていること
・aprがインストールされていること
・apr-utilがインストールされていること
・Apache、Tomcatが稼働している場合は停止していること
4.Mod Securityインストール
Githubよりソースコードを取得(今回はmodsecurity-2.9.3.tar.gz)
◎ Mod Security配布サイト(Github)
アップロードを行い、解凍する
[root@Server1 ~]# cd /usr/local/src ※アップロード先
[root@Server1 ~]# tar -xvf modsecurity-2.9.3.tar.gz
必要モジュールのインストール
[root@Server1 ~]# yum install libxml2-devel
インストール済Apacheのapxsコマンドのパスを確認する
[root@Server1 ~]# ll /usr/local/httpd-2.4.46/bin/apxs
-rwxr-xr-x 1 apache apache 23889 3月 25 22:02 /usr/local/httpd-2.4.46/bin/apxs
Mod Securityのビルド・デプロイ(各コマンド実行時にでエラーメッセージが出なければOK)
※–with-apxs:apxsコマンドのパス
※–with-apr:aprのインストールディレクトリ
※–with-apu:apr-utilのインストールディレクトリ
※「make test」コマンドは正常にmakeできているかのテストであり、時間がかかる為スキップしても良い。
[root@Server1 ~]# cd modsecurity-2.9.3
[root@Server1 ~]# ./configure --with-apxs=/usr/local/httpd-2.4.46/bin/apxs --with-apr=/usr/local/apr-1.6.5 --with-apu=/usr/local/apr-util-1.6.1
[root@Server1 ~]# make
[root@Server1 ~]# make test
[root@Server1 ~]# make install
デプロイされてることを確認
[root@Server1 ~]# ll /usr/local/modsecurity
合計 0
drwxr-xr-x 2 root root 30 4月 8 12:38 bin
drwxr-xr-x 2 root root 30 4月 8 12:38 lib
ソースコードディレクトリ内にある「modsecurity.conf-recommended」ファイルをApacheのconfフォルダにコピーし、ファイル権限を他と合わせる
[root@Server1 ~]# cp -p /usr/local/src/modsecurity-2.9.3/modsecurity.conf-recommended /usr/local/apache/conf/extra/modsecurity.conf
[root@Server1 ~]# chmod 644 /usr/local/apache/conf/extra/modsecurity.conf
ソースコードディレクトリ内にある「unicode.mapping」ファイルをApacheのconfフォルダにコピーし、ファイル権限を他と合わせる
[root@Server1 ~]# cp -p /usr/local/src/modsecurity-2.9.3/unicode.mapping /usr/local/httpd-2.4.46/conf/extra/
[root@Server1 ~]# chmod 644 /usr/local/httpd-2.4.46/conf/extra/unicode.mapping
5.Apache設定
必要モジュールがApacheインストールディレクトリ内に存在するか確認
[root@Server1 ~]# ll /usr/local/httpd-2.4.46/modules/mod_unique_id.so
[root@Server1 ~]# ll /usr/local/httpd-2.4.46/modules/mod_security2.so
Apache設定ファイル「httpd.conf」を編集する
編集対象ファイル | {Apacheインストールディレクトリ}/conf/httpd.conf |
「httpd.conf」にモジュール読み込みの為の記載を追記
※対象モジュールの記載が存在する場合は、コメント「#」を解除し、正しいパスを記載する。
LoadModule unique_id_module modules/mod_unique_id.so |
LoadModule security2_module modules/mod_security2.so |
「httpd.conf」にMod Securityの設定ファイルのパスを記載
<IfModule security2_module> Include conf/extra/modsecurity.conf </IfModule> |
~略~
LoadModule headers_module modules/mod_headers.so
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
~略~
LoadModule security2_module modules/mod_security2.so
~略~
<IfModule security2_module>
Include conf/extra/modsecurity.conf
</IfModule>
6.Mod Security設定ファイル編集
Mod Security設定ファイル「modsecurity.conf」を編集する
編集対象ファイル | {Apacheインストールディレクトリ}/conf/extra/modsecurity.conf |
<modsecurity.conf 設定プロパティ>
SecRequestBodyAccess On |
リクエスト本文へのアクセスを有効にする On:リクエスト本文をバッファリングする Off:リクエスト本文をバッファリングしない |
secrule request_headers: Content-Type;” application=”” json=”” br=””>”id:’200001′,phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON” |
JSON形式のリクエストヘッダーを、現在のCロケールを使用して全ての文字を小文字に変換する。 Id:ルールのID phase:ルールの実行タイミング 1:Phase リクエストヘッダー 2:Phase リクエストボディ 3:Phase レスポンスヘッダー 4:Phase レスポンスボディ 5:Phase ロギング t:none:指定された以前の変換関数が無効になる t:lowercase:現在のCロケールを使用して、すべての文字を小文字に変換する pass:次のルール検証に進む nolog:ログ出力しない ctl:requestBodyProcessor = JSON:リクエストをJSONとして処理する |
SecRequestBodyNoFilesLimit 1048576 |
最大ファイルサイズをbyte単位で設定(1MB) |
SecRequestBodyLimitAction Reject |
リクエストの本文の最大サイズを超過した場合、超過分のリクエスト本文を破棄 |
id:’200002′, phase:2,t:none,log,deny,status:400,msg:’Failed to parse request body.’,logdata:’%{reqbody_error_msg}’,severity:2 |
リクエスト本文の解析に使用されるプロセッサの値が「0(エラーなし)」でない場合、リクエストを拒否 |
“id:’200003′,phase:2,t:none,log,deny,status:400, \ 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}'” |
「multipart/form-data」形式のリクエストを検査する !@eq 0:エラーの場合 ※@eq:0(エラーなし)、1(エラー) phase:ルールの実行タイミング 1:Phase リクエストヘッダー 2:Phase リクエストボディ 3:Phase レスポンスヘッダー 4:Phase レスポンスボディ 5:Phase ロギング t:none:指定された以前の変換関数が無効になる log:ログ出力する deny:リクエストを拒否 status:応答ステータスコードを指定 msg:レスポンス本文 |
“id:’200004′,phase:2,t:none,log,deny,msg:’Multipart parser detected a possible unmatched boundary.'” |
multipart / request-bodyの解析フェーズ中に、一致しない可能性を検知した場合にリクエストを拒否する。 !@eq 0:エラーの場合 ※@eq:0(エラーなし)、1(エラー) Id:ルールのID phase:ルールの実行タイミング 1:Phase リクエストヘッダー 2:Phase リクエストボディ 3:Phase レスポンスヘッダー 4:Phase レスポンスボディ 5:Phase ロギング t:none:指定された以前の変換関数が無効になる log:ログ出力する deny:リクエストを拒否 msg:レスポンス本文 |
SecPcreMatchLimitRecursion 1000 |
PCRE(正規表現ライブラリ)の正規表現の最大再帰数を指定する。 ※PCREの最大マッチング数を制限することで、ReDoS(正規表現DOS)攻撃によりサーバ負荷がかからないようにする。 |
SecResponseBodyMimeType text/plain text/html text/xml |
検査対象のMIMEタイプを指定する(text/plain、text/html、text/xmlを対象とする) |
SecResponseBodyLimitAction ProcessPartial |
リクエストの本文の最大サイズを超過した場合、超過分のリクエスト本文は検査せず通過させる。 Reject:破棄する ProcessPartial:SecRequestBodyLimit で指定したサイズまで検証し、残りはパスさせる |
SecDataDir /usr/local/apache/logs/mod_security_data/ |
永続データ(IPアドレスデータ、セッションデータなど)が保存されるディレクトリ |
SecUploadKeepFiles RelevantOnly |
トランザクションの処理後に、傍受されたファイルを保持するかどうかを構成。 On-アップロードしたファイルを保持する Off-アップロードされたファイルを保持しない RelevantOnly-これは、関連すると見なされるリクエストに属するファイルのみを保持する |
SecDebugLog /usr/local/apache/logs/mod_security_debug.log |
ModSecurityデバッグログファイルへのパス |
SecAuditEngine RelevantOnly |
監査ログを出力 On:すべてのトランザクションをログに記録する Off:トランザクションをログに記録しない RelevantOnly:警告またはエラーをトリガーした、または関連すると見なされるステータスコードを持つログトランザクションのみ |
SecAuditLogRelevantStatus “^(?:5|4(?!04))” |
指定された正規表現に一致するステータスコードを持つトランザクションのみの監査ログを構成できるようにする ※404を除くすべての5xxおよび4xxレベルのステータスコードがログに記録される |
SecAuditLogType Serial |
使用する監査ログメカニズムのタイプを定義する Serial:SecAuditLogで指定された単一のファイルに保存される Concurrent:トランザクションごとに1つのファイルが監査ログに使用される |
SecAuditLogStorageDir /usr/local/apache/logs/mod_security_audit/ |
同時監査ログエントリが保存されるディレクトリを定義 |
SecCookieFormat 0 |
アプリケーションのcookieタイプを指定 0:バージョン0(Netscape)のCookieを使用。(ほとんどのアプリケーションがこちらを使用) 1:バージョン1のCookieを使用。 |
SecStatusEngine Off |
Webサーバーの起動時にステータスレポートをModSecurityプロジェクトチームに送信しない On:送信する Off:送信しない |
SecServerSignature ” “ |
レスポンスデータにサーバ情報を載せない |
SecRuleEngine On
SecRequestBodyAccess On
#SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
# "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
#SecRule REQUEST_HEADERS:Content-Type "application/json" \
# "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
SecRequestBodyLimit 2097152
SecRequestBodyNoFilesLimit 1048576
SecRequestBodyInMemoryLimit 1572864
SecRequestBodyLimitAction Reject
SecRule REQBODY_ERROR "!@eq 0" \
id:'200002', 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:'200003',phase:2,t:none,log,deny,status:400, \
#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:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
#SecPcreMatchLimit 1000
#SecPcreMatchLimitRecursion 1000
#SecRule TX:/^MSC_/ "!@streq 0" \
# "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
SecResponseBodyAccess Off
#SecResponseBodyMimeType text/plain text/html text/xml
#SecResponseBodyLimit 524288
#SecResponseBodyLimitAction ProcessPartial
SecTmpDir /usr/local/apache/logs/mod_security_tmp/
SecDataDir /usr/local/apache/logs/mod_security_data/
#SecUploadDir /opt/modsecurity/var/upload/
#SecUploadKeepFiles RelevantOnly
#SecUploadFileMode 0600
#SecDebugLog /usr/local/apache/logs/mod_security_debug.log
#SecDebugLogLevel 3
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /usr/local/apache/logs/modsec_audit.log
#SecAuditLogStorageDir /usr/local/apache/logs/mod_security_audit/
SecArgumentSeparator &
SecCookieFormat 0
#SecUnicodeMapFile unicode.mapping 20127
SecStatusEngine Off
SecServerSignature " "
7.Mod Security設定適用
Apache・Tomcatを起動
[root@Server1 ~]# /usr/local/tomcat/bin/shutdown.sh
[root@Server1 ~]# /usr/local/tomcat/bin/startup.sh
[root@Server1 ~]# /usr/local/src/modsecurity-2.9.3/bin/apachectl start
8.設定確認
Mod Securityを設定したサーバへ、別サーバから設定値を超過サイズのリクエストを送り、200以外のHTTPステータスが返却されることを確認する。
[root@Server2 ~]# cd /usr/local/apache/bin/
[root@Server2 ~]# ./ab -n 1 -c 1 -p modsecurityTest1.xlsx -T 'application/x-www-form-urlencoded' http://{Server1のIPアドレス}:80/
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.x.xx (be patient).....done
Server Software:
Server Hostname: 192.168.x.xx
Server Port: 80
Document Path: /
Document Length: 316 bytes
Concurrency Level: 1
Time taken for tests: 0.083 seconds
Complete requests: 1
Failed requests: 0
Non-2xx responses: 1
Total transferred: 490 bytes
Total body sent: 2171919
HTML transferred: 316 bytes
Requests per second: 12.09 [#/sec] (mean)
Time per request: 82.682 [ms] (mean)
Time per request: 82.682 [ms] (mean, across all concurrent requests)
Transfer rate: 5.79 [Kbytes/sec] received
25652.68 kb/s sent
25658.46 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 1 0.0 1 1
Processing: 82 82 0.0 82 82
Waiting: 0 0 0.0 0 0
Total: 83 83 0.0 83 83
ModSecurityを設定したサーバのApacheログ「access_log」「error_log」にエラーログが出力されていること、HTTPエラーコードが返されていることを確認する。
確認ログ① | {Apacheインストールディレクトリ}/logs/access_log |
192.168.x.xx - - [28/May/2021:14:46:04 +0900] "POST / HTTP/1.0" 413 316
確認ログ② | {Apacheインストールディレクトリ}/logs/error_log |
[Fri May 28 14:46:04.571377 2021] [:error] [pid 13759:tid 140379139933952] [client 192.168.x.xx:57218] [client 192.168.x.xx] ModSecurity: Request body (Content-Length) is larger than the configured limit (2097152). [hostname "192.168.x.xx"] [uri "/"] [unique_id "YLCDnKZKK42niMO9p472ugAAAcI"]