WAF★ModSecurityルールファイル設定

ModSecurityのルールを設定するには下記リンクのマニュアルにある通りなんですが、腐るほどパラメータがあってどれを設定していいかよくわかりません。
そこで、このページではよく使いそうなものをピックアップして見ていきます。
ModSecurityルールの主な項目
Configuration Directives
SecRule
新しいルールの定義を行います。
SecRule 変数 オペレータ [アクション]
アクションが無かった場合にはデフォルトのアクションに従います。アクションが記載された場合はこちらが優先されます。
【例】SecRule ARGS "@rx attack" "phase:1,log,deny,id:1"
SecRuleを定義した際にアクションをidしか設定していなかった為次のようなエラーが出ました。
SecRule takes two or three arguments, rule target, operator and optional action list
解決策は、アクションにphase、log、deny等を追加したことです。
SecRuleEngine
ModSecurityのルールエンジン(セキュリティ検査とブロック)の設定を行います。
SecRuleEngine On|Off|DetectionOnly
On | 起動 |
Off | 停止(デフォルト) |
DetectionOnly | 検出のみでブロックはしない |
SecRuleEngine On
SecAuditEngine
ログ取得を行うかどうかの設定をします。
SecAuditEngine On|Off|RelevantOnly
On | 全てのトランザクション |
Off | ログは取らない |
RelevantOnly | エラーや警告、またはSecAuditLogRelevantStatusで定義されたステータスコードに関するもの |
SecAuditEngine On
SecAuditLogRelevantStatus
ログを取得するステータスコードを登録します。
SecAuditLogRelevantStatus 正規表現
SecDefaultAction
検出した時のアクションを定義します。このルールは同じコンテキスト内で引き継がれます。
このディレクティブではアクショングループのdisruptiveとphaseの設定が必要になります。meta-dataアクションは記載出来ません。
SecDefaultAction “アクション1, アクション2, アクション3"
【例】SecDefaultAction "phase:2,log,auditlog,deny,status:403,tag:'SLA 24/7'"
SecRuleRemoveById
不要なルールをIDの指定によりルールの無効化を行います。
注:このディレクティブは削除しようとしているルールが定義された後に記載するようにすること。
SecRuleRemoveById ルールID
※ルールIDはレンジ(範囲)でも指定可能(下記参照)
【例】SecRuleRemoveByID 1 2 "9000-9010"
SecRequestBodyLimit
ModSecurityが受け取るができるリクエストボディサイズの最大値を設定します。
SecRequestBodyLimit 許容リクエストボディサイズ
※許容リクエストボディサイズはバイトで指定
【例】SecRequestBodyLimit 134217728
SecRequestBodyNoFilesLimit
ファイル転送以外のModSecurityが受け取ることができるリクエストボディサイズの最大値を設定します。
※DoS攻撃対策として用いられる。
※SecRequestBodyLimitでより高い設定値にすること。
※一般的には128KBより小さい値を設定。
SecRequestBodyNoFilesLimit 許容リクエストボディサイズ
※許容リクエストボディサイズはバイトで指定
【例】SecRequestBodyNoFilesLimit 131072
Variables
Variables(変数)は送られてきたリクエストの内容をVariables事に保持します。Variablesを使ってModSecurityのルールを作成します。
Variablesの書き方
Variablesはそれぞれの役割毎の変数を意味し、役割毎に設定された値を使ってセキュリティ検査を行います。
例えば変数名"REQUEST_URI_RAW"ならURIに含まれる文字列を意味し、変数名"RESPONSE_BODY"ならレスポンスの本文に含まれる文字列を意味します。
SecRule 変数 “パラメータ" OPERATORS ACTIONS
変数 | ルールに使うVariablesを指定 |
パラメータ | Variablesで確認したい文字列を指定 |
SecRule RESPONSE_BODY "ODBC Error Code" "phase:4,id:54,t:none"
SecRule REQUEST_URI_RAW "http:/" "phase:1,id:53,t:none,t:urlDecode,t:lowercase,t:normalizePath"
それぞれのVariablesを見ていきましょう。
REQUEST_URI
REQUEST_URIはリクエストURIに含まれる文字列を意味します。尚ドメインを含まないURIになります(例えば"http://www.example.com/index.php?p=X"の場合だと、"/index.php?p=X"の部分になります。)
REQUEST_URI “パラメータ"
【例】# REQUEST_URIに"attack"という文字が含まれていないか検査
SecRule REQUEST_URI "attack" "phase:1,id:52,t:none,t:urlDecode,t:lowercase,t:normalizePath"
REMOTE_ADDR
REMOTE_ADDRはリモートクライアントのIPアドレスを意味します。
REMOTE_ADDR “@ipMatch ipアドレス"
【例】# IPアドレス192.168.100.1からのアクセスは拒否
SecRule REMOTE_ADDR "@ipMatch 192.168.100.1" "phase:1,id:101,log,deny"
Actions
ActionsはModSecurityのルールに合致した際の動作を指定します。
Actionsの書き方
SecRuleの中でActionsを記載します。複数記載する場合はカンマ区切りで記載します。
SecRule VARIABLES OPERATORS “アクション1,アクション2:パラメータ2"
アクションは複数指定可。パラメータが必要な項目は":"で区切って設定する。
ダブルクォーテーションはあっても無くても良い。あった方が可読性が上がると思う。
※上記のように"アクション1,アクション2,アクション3・・・"と並んでいる表記をアクションリストと言います。
【例】SecDefaultAction phase:2,deny,id:101,status:403,log,auditlog
SecRule RESPONSE_CONTENT_TYPE "^text/html" "nolog,id:99,pass,append:'<hr>Footer'"
アクショングループ
アクションには次のようなグループがあり、カテゴリー分けされています。
- Disruptive(セキュリティ問題に関わる項目)
- Non-Disruptive
- Meta-data
- Flow
- Data
Disruptiveが最も重要っぽいので設定する時には注意して行いましょう。
phase
アクショングループ:Disruptive
ルールを適用する段階を示しています。
phase:1 | リクエストヘッダー読込時の処理 |
phase:2 | リクエストボディ読込時の処理(通常はこれを使用) |
phase:3 | レスポンスヘッダー返送時の処理 |
phase:4 | レスポンスボディ返送時、出力情報分析の処理 |
phase:5 | ロギング直前の処理 |
id (必須)
アクショングループ:Meta-data
各ルールに対して一意の番号を付与します(必須です)。しかし殆どの番号が予約番号で使えないため、idを使うときは注意しましょう。
使える番号
- 1–99,999(※ローカル使用限定)
- 400,000–419,999
- 440.000-599,999
- 1,010,000-1,999,999
- 4,301,000-19,999,999
- 22,000,000 and above
※1–99,999はローカルでの確認やテストに限り使えます。正式な使用は他のidを使いましょう。
log
アクショングループ:Non-disruptive
ルールに合致した場合ログの取得を指示する。
deny
アクショングループ:Disruptive
トランザクションを中断して、ルールの処理も停止します。アクセス拒否します。
ctl
アクショングループ:Non-disruptive
一時的な設定の変更を行います。
変更可能な設定項目は次の通りです。
項目 | 内容 |
---|---|
auditEngine | ModSecurityのon/off |
auditLogParts | ログ取得(取得内容の指定可) |
debugLogLevel | errors,warnings,notices等のログレベルの設定 |
forceRequestBodyVariable | リクエストボディが検査項目に無い場合のみREQUEST_BODY変数に値の設定可 |
requestBodyAccess | リクエストボディのバッファや処理を行う |
requestBodyLimit | リクエストボディをバッファで保持するmaxサイズを設定 |
requestBodyProcessor | デフォルトではURLエンコード(application/x-www-form-urlencoded)と 複合型(multipart/form-data)のフォーマットを処理。JSONやXMLも可。 |
responseBodyAccess | レスポンスボディをバッファさせる |
responseBodyLimit | レスポンスボディをバッファで保持するmaxサイズを設定 |
ruleEngine | ルールエンジン(検査とブロック)の起動の設定 |
ruleRemoveById | IDにより適用しないルールを設定 |
ruleRemoveByMsg | 正規表現で合致したメッセージのルールは適用しないよう設定 |
ruleRemoveByTag | タグの指定により適用しないルールを設定 |
ruleRemoveTargetById | IDによりターゲットリストの削除を設定 |
ruleRemoveTargetByMsg | 正規表現で合致したメッセージによりターゲットリストの削除を設定 |
ruleRemoveTargetByTag | タグによりターゲットリストの削除を設定 |
hashEngine | ハッシュエンジンの起動設定 |
hashEnforcement | 不明(強制的なハッシュ?) |
tag
アクショングループ:Meta-data
ルールのカテゴリー分類を行う。
t
アクショングループ:Non-disruptive
Variablesの値を指定した形式に変換します。例えば"大文字を小文字にする"など。
t:パラメータ(Transformation Functions)
指定した形式に変換させるにはパラメータで指定します。指定するパラメータにはTransformation Functionsを利用する。
※tを使うときは必ず最初に"t:none"を指定(“t:none"はデフォルトの設定を無効にする)してから各々の設定を指定すること。
SecRule ARGS "(asfunction|javascript|vbscript|data|mocha|livescript):" "id:146,t:none,t:htmlEntityDecode,t:lowercase,t:removeNulls,t:removeWhitespace"
Transformation Functions
Transformation FunctionsはVariablesの値を指定された方法で変換します。
使用はActionsのtとセットで行われます。詳細はtを参照。
lowercase
全ての文字を小文字に変換します。
removeNulls
全てのnullを除去します。
Operators
ModSecurityでルールを作成する際に様々な条件を指定しますがその時に使うのがOperatorsです。正規表現も使用することができます。
Operatorsの書き方
SecRuleでルールを作成する時に使います。頭に@をつけて使用します。
SecRule VARIABLES “@オペレータ パラメータ" ACTIONS
オペレータ | @を付けてOperatorsを指定(省略時はrxを適用) |
パラメータ | Operatorsに必要なパラメータを指定 |
SecRule REQUEST_HEADERS:User-Agent "@rx nikto" phase:1,id:173,t:lowercase
SecRule ARGS|REQUEST_HEADERS "@rx <script" msg:'XSSAttack',deny,status:404
rx
正規表現によるパターンマッチが行われます。デフォルトがrxなのでオペレータを省略した際はrxが適用されます。
@rx 正規表現
【例】SecRule REQUEST_HEADERS:User-Agent "@rx (?i)nikto" phase:1,id:174,t:none
eq
equal(イコール)を意味します。数値と比較して等しければtrueを返す。
@eq 数値
【例】SecRule &REQUEST_HEADERS_NAMES "@eq 15" "id:153"
ipMatch
VariablesのREMOTE_ADDRに指定したIPアドレスが合致するかを検査します。
@ipMatch IPアドレス
IPアドレスの表記方法は次の通りです。
表記方法 | 表記例 |
---|---|
IPv4 アドレス | 192.168.1.100 |
IPv4 CIDR表記 | 192.168.1.0/24 |
IPv6 アドレス | 2001:db8:85a3:8d3:1319:8a2e:370:7348 |
IPv6 CIDR表記 | 2001:db8:85a3:8d3:1319:8a2e:370:0/24 |
SecRule REMOTE_ADDR "@ipMatch 192.168.1.100,192.168.1.50,10.10.50.0/24" "id:162"
pmFromFile
ファイルに保存された検査対象文字列に合致するか検査します(大文字・小文字の区別はしない)。
※検査対象が多い場合は正規表現よりもこのpmFromFileの方が適しています。
@pmFromFile 検査対象文字列のファイル名
【例】pmFromFileSecRule REQUEST_HEADERS:User-Agent "@pmFromFile /path/to/blacklist1 blacklist2" "id:167"
注:検査対象文字列のファイルについて
- ファイル内は1フレーズに対し1行であること
- 正規表現は使えない
- “/"を前後に記載することで曖昧さを回避できる(下記例参照)
# ファイル名blacklist1
# 192.168.0.1では192.168.0.11や192.168.0.12も検査に引っかかってしまう。
# /192.168.0.2/は192.168.0.21や192.168.0.22は検査に引っかからない(曖昧さ回避)。
192.168.0.1
/192.168.0.2/
ルールの作り方
ModSecurityのルール作成のシンプルな形を見ていきましょう。
ルール書き方の基本
ルールを作成するには、SecRuleに対して
- VARIABLES
- OPERATORS
- ACTIONS
の三つを設定します。これを基本にファイルを作成して該当フォルダに保存しましょう。
ルールの保存場所とファイル名
ルールの保存場所は次の通りです。
- /etc/httpd/modsecurity.d/activated_rules/
ファイル名は任意で拡張子はconfにします。
【例】rule_sample.confホワイトリストの作成
ホワイトリストを作成してルールで適用させます。まずはホワイトリストを作成しましょう。
vi /etc/httpd/conf/mod_security.d/whitelist_ip.txt
/192.168.0.1/
/192.168.0.2/
/192.168.0.3/
ホワイトリストの適用処理例です。
# /etc/httpd/modsecurity.d/activated_rules/rule_sample.conf
SecRule REMOTE_ADDR "@pmFromFile /etc/httpd/conf/mod_security.d/whitelist_ip.txt" "phase:1,id:1,nolog,allow,ctl:ruleEngine=Off,ctl:auditEngine=Off"
ブラックリストの作成
ホワイトリストと同様にブラックリストも作成します。
vi /etc/httpd/conf/mod_security.d/blacklist_ip.txt
/192.168.10.1/
/192.168.10.2/
/192.168.10.3/
ホワイトリストの適用処理例です。
# /etc/httpd/modsecurity.d/activated_rules/rule_sample.conf
SecRule REMOTE_ADDR "@pmFromFile /etc/httpd/conf/mod_security.d/blacklist_ip.txt" "phase:1,id:2,deny,log,msg:'Blacklisted IP address'"
ルールのサンプル
特定の文字列を検知させる
ここではURIに"abc"が含まれているとアクセスを拒否させるようにやってみます。
ルールファイルは次の通りです。
# /etc/httpd/modsecurity.d/activated_rules/rule_sample1.conf
SecRule REQUEST_URI "abc" "id:1001,phase:2,deny,log,status:405"
それではapacheを再起動して確認してみましょう。まずは普通にアクセスして問題なければ次のようなアドレスを入力してください。
http://サーバのIPアドレス?abc
または
http://サーバのIPアドレス/abc/
上手くいけばブラウザに次のようなメッセージが表示されます。

ログも確認しておきましょう。
–565e4c00-A–
[14/Apr/2020:11:13:22 +0900] XpUcQpyao2APvntttOQ-NAAAAAE 192.168.33.1 64217 192.168.33.13 80
–565e4c00-B–
GET /?abc HTTP/1.1
Host: 192.168.33.13
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
–565e4c00-F–
HTTP/1.1 405 Method Not Allowed
Allow: TRACE
Content-Length: 220
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1
–565e4c00-E–
–565e4c00-H–
Message: Access denied with code 405 (phase 2). Pattern match “abc" at REQUEST_URI. [file “/etc/httpd/modsecurity.d/activated_rules/rule_sample1.conf"] [line “2"] [id “1001"]
Apache-Error: [file “apache2_util.c"] [line 271] [level 3] [client 192.168.33.1] ModSecurity: Access denied with code 405 (phase 2). Pattern match “abc" at REQUEST_URI. [file “/etc/httpd/modsecurity.d/activated_rules/rule_sample1.conf"] [line “2"] [id “1001"] [hostname “192.168.33.13"] [uri “/"] [unique_id “XpUcQpyao2APvntttOQ-NAAAAAE"]
Action: Intercepted (phase 2)
Stopwatch: 1586830402068860 2696 (- – -)
Stopwatch2: 1586830402068860 2696; combined=1438, p1=544, p2=842, p3=0, p4=0, p5=52, sr=193, sw=0, 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.41 (IUS) OpenSSL/1.0.2k-fips
Engine-Mode: “ENABLED"
–565e4c00-Z–
-H-の項目内のメッセージを見ると
Access denied with code 405 (phase 2). Pattern match “abc" at REQUEST_URI.
ちゃんと機能しているようです。
IPアドレスでブロックする
特定のIPアドレスをブロックする場合は次のようになります。
# /etc/httpd/modsecurity.d/activated_rules/rule_sample2.conf
SecRule REMOTE_ADDR "@ipMatch ブロックしたいIPアドレス" "phase:1,id:21,log,deny"
apache(httpd.conf)内でルール設定
apacheの設定ファイルhttpd.confに直接ルールを記載することも出来ます。
【設定例】<Directory /var/www/html/admin>
SecRuleEngine Off
</Directory>
<Directory /var/www/html/admin>
SecRuleRemoveById 981317 950001 959073 981255 981245
SecRuleRemoveById 950901 960024 981173 973300
</Directory>
<IfModule mod_security2.c>
SecRuleRemoveById 200003
</IfModule>
phpに関する設定
php.iniの中でファイルアップロードの最大値を設定する次の項目があります。
- post_max_size
- upload_max_filesize
これらに修正をかけた場合ModSecurityでも設定を変更しないといけないっぽいです。修正するのは次の二つです。
これで正しく動作すると思います。
情報セキュリティをオンラインで学習することもできます。
Udemy 情報セキュリティ