ModSecurity入門
目次
ModSecurityとは
- オープンソースのWAF(Web Application Firewall)です。
- XSS や SQLインジェクションなどの Web に対する攻撃を検知・防御します。
- Trastwave社が開発し、Apache License 2.0 で公開しています。
- ホスト型の WAF と呼ばれるもので、Webサーバにインストールします。
- Apache, Nginx, IIS などに組み込んで使用することができます。
- 攻撃パターンを定義する CRS(Core Rule Set)と組み合わせて使用します。
- CRS はOWASP(Open Web Application Security Project)が公開しています。
- CRS のライセンスも Apache License 2.0 です。
- 現時点(2020年4月)の最新版は 3.0.4 ですが、ここでは、CentOS にインストール可能な 2.x について説明します。
インストール
CentOS 7 に Apache 対応版の ModSecurity 2.9 をインストールする手順を下記に示します。
Shell
# yum install -y httpd
# yum install -y epel-release
# yum install -y mod_security mod_security_crs
# systemctl enable httpd
# systemctl start httpd
試してみる
下記の様な簡単なフォームから 「';」 を入力して送信してください。SQLインジェクション の疑いがあるとして、403 Forbidden エラーとなればテストは成功です。
HTML
<form method="POST" action="test_page.html">
<input type="text" name="data">
<button>OK</button>
</form>
監査ログ
監査ログは下記に記録されます。
- /var/log/httpd/modsec_audit.log
/var/log/httpd/modsec_audit.log
--bd796373-A--
[12/Apr/2020:02:22:13 +0000] XpJ7VZPq2O@DCdEaiF0OawAAAAM 169.254.127.84 53499 172.17.0.2 80
--bd796373-B--
POST /index.html HTTP/1.1
Host: www.example.com
Connection: keep-alive
Content-Length: 11
Cache-Control: max-age=0
Origin: http://www.example.com
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.example.com/
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
--bd796373-C--
data=%27%3B
--bd796373-F--
HTTP/1.1 403 Forbidden
Content-Length: 212
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1
--bd796373-E--
--bd796373-H--
Message: Access denied with code 403 (phase 2). Pattern match "(^[\"'`\xc2\xb4\xe2\x80\x99\xe2\x80\x98;]+|[\"'`\xc2\xb4\xe2\x80\x99\xe2\x80\x98;]+$)" at ARGS:data. [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "64"] [id "981318"] [rev "2"] [msg "SQL Injection Attack: Common Injection Testing Detected"] [data "Matched Data: '; found within ARGS:data: ';"] [severity "CRITICAL"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "8"] [tag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"]
Apache-Error: [file "apache2_util.c"] [line 271] [level 3] [client 169.254.127.84] ModSecurity: Access denied with code 403 (phase 2). Pattern match "(^[\\\\"'`\\\\xc2\\\\xb4\\\\xe2\\\\x80\\\\x99\\\\xe2\\\\x80\\\\x98;]+|[\\\\"'`\\\\xc2\\\\xb4\\\\xe2\\\\x80\\\\x99\\\\xe2\\\\x80\\\\x98;]+$)" at ARGS:data. [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "64"] [id "981318"] [rev "2"] [msg "SQL Injection Attack: Common Injection Testing Detected"] [data "Matched Data: '; found within ARGS:data: ';"] [severity "CRITICAL"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "8"] [tag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] [hostname "www.example.com"] [uri "/index.html"] [unique_id "XpJ7VZPq2O@DCdEaiF0OawAAAAM"]
Action: Intercepted (phase 2)
Stopwatch: 1586658133894961 2946 (- - -)
Stopwatch2: 1586658133894961 2946; combined=1662, p1=850, p2=732, p3=0, p4=0, p5=79, sr=76, sw=1, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.9.2 (http://www.modsecurity.org/); OWASP_CRS/2.2.9.
Server: Apache/2.4.6 (CentOS)
Engine-Mode: "ENABLED"
--bd796373-Z--
監査ログは、ひとつのトランザクションに対して A~Z のセクションが記録されます。SecAuditLogParts でどのセクションをロギングするかを制御できます。
- Aセクション
- 監査ログのヘッダ情報。発生時刻や接続元IPアドレス情報などを含みます。
- Bセクション
- リクエストヘッダ。
- Cセクション
- リクエストボディ。
- Dセクション
- 中間的なレスポンスヘッダ。ModSecurity によって変更される前のレスポンスヘッダだと思いますが、未実装です。
- Eセクション
- 中間的なレスポンスボディ。ModSecurity によって変更される前のレスポンスボディだと思いますが、未実装です。
- Fセクション
- 最終的なレスポンスヘッダ。
- Gセクション
- 最終的なレスポンスボディ。未実装。
- Hセクション
- 監査の要約情報。id にはルールID、msg にはルール名、severity には重要度が記録されます。
- Iセクション
- リクエストボディ。Cセクションとほぼ同様ですが、アップロードファイルの中身をロギングしない点が異なります。ただ、現状の実装では、C を指定しても、I を指定しても、ファイルの中身をロギングしない Cセクションが記録されるようです。
- Jセクション
- multipart/form-data で送信されるアップロードファイルに関する情報。
- Kセクション
- 監査でマッチしたルール情報。
- Zセクション
- ひとつのトランザクションに関する監査ログの終了を示す。
コンフィグファイル
ModSecurity に関する設定ファイルは下記にあります。
- /etc/httpd/conf.d/mod_security.conf - ModSecurityの設定ファイル
- /etc/httpd/modsecurity.d/modsecurity_crs_10_config.conf - CRSの設定ファイル
- /etc/httpd/modsecurity.d/activated_rules/*.conf - CRS定義(アクティブなルール)
- /usr/lib/modsecurity.d/base_rules/*.conf - CRS定義(基本ルール)
主な設定項目は下記の通り。注意すべき項目に * をつけています。
- SecRuleEngine*
- ルールエンジンの動作を指定します。On は防御有効。Off は無効。DetectionOnly は検知(ロギング)のみを行います。デフォルトは On になっていますが、運用開始時は DetectionOnly で運用し、ログを見ながらルールの除外設定を行い、安定してから On にするのがお勧めです。
- SecRequestBodyAccess
- POST などのリクエストボディを解析するには On を指定します。
- SecRule*
- 検証ルールを指定します。詳細は別途。
- SecRequestBodyLimit*
- 検証するリクエストボディの最大バイト数を指定します。このサイズを超えるデータは POST やアップロードできなくなります。
- SecRequestBodyNoFilesLimit
- 検証するリクエストボディの最大バイト数を指定します。ただし、ファイルアップロードには適用されません。
- SecRequestBodyInMemoryLimit
- オンメモリで検証するリクエストボディの最大バイト数を指定します。このサイズを超えるデータをアップロードする場合、/var/lib/mod_security/ に一時ファイルが作成されますのでパーミッションに注意してください。
- SecRequestBodyLimitAction*
- リクエストボディの最大バイト数を超えた場合の動作を指定します。Reject は破棄を、ProcessPartial は SecRequestBodyLimit で指定したサイズまでを検証し、残りはパスさせます。
- SecPcreMatchLimit
- PCRE正規表現の最大マッチング数を指定します。
- SecPcreMatchLimitRecursion
- PCRE正規表現の最大再帰数を指定します。
- SecResponseBodyAccess
- レスポンスボディの検証を行うかどうかを指定します。
- SecDebugLog
- デバッグログファイルを指定します。
- SecDebugLogLevel
- デバッグログの出力レベルを 0~9 の範囲で指定します。0 はロギングしません。
- SecAuditEngine
- 監査ログエンジンを設定します。On はすべてをロギングする、Off はすべてロギングしない。RelevantOnly は warning、error、または SecAuditLogRelevantStatus で定義されたステータスコードにマッチする場合のみロギングします。
- SecAuditLogRelevantStatus
- 監査ログに記録するステータスコードを指定します。"^(?:5|4(?!04))" は 5 または 4 で始まるコード(ただし 404 は除外する)を意味します。
- SecAuditLogParts*
- 監査ログに記録するセクションを指定します。例えば ABIH は A(ヘッダ)、B(リクエストヘッダ)、I(リクエストボディ)、H(監査の要約情報)を記録することを意味します。
- SecAuditLogType
- 監査ログの保存方法を指定します。Serial はひとつのファイルにシリアルに書き込みます。Concurrent はトランザクション毎に別々のファイルに書き込みます。
- SecAuditLogStorageDir
- SecAuditLogType に Concurrent を指定した際にログを保存するディレクトリを指定します。ログファイルは、YYYYMMDD/YYYYMMDD-HHMM/YYYYMMDD-HHMMSS-識別子 のファイル名で保存されます。ディレクトリのパーミッションに注意してください。
- SecAuditLog
- 監査ログのファイル名を指定します。
- SecArgumentSeparator
- application/x-www-form-urlencoded で送信されるパラメータの区切り文字を指定します。
- SecCookieFormat
- Cookie形式のバージョンを指定します。通常は 0 で構いません。
- SecTmpDir
- バッファリングなどの一時ファイルを格納するディレクトリを指定します。ディレクトリのパーミッションに注意してください。
- SecDataDir
- IPアドレス情報やセッション情報などのデータを格納するディレクトリを指定します。
- SecRuleRemoveById*
- 無視するルールのルールIDを指定します。監査ログ Hセクションに記録されるルールID を指定します。例えば、特定のページに対して特定のルールを除外したい時は、下記の様に指定します。
/etc/httpd/conf.d/mod_security.conf
<LocationMatch "/login">
SetRuleRemoveById 960024 981318
</LocationMatch>
リンク
Copyright (C) 2020 杜甫々
初版:2020年4月12日 最終更新:2020年4月12日
https://www.tohoho-web.com/ex/modsecurity.html