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

2021年10月16日

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

一時的な設定の変更を行います。

変更可能な設定項目は次の通りです。

項目内容
auditEngineModSecurityのon/off
auditLogPartsログ取得(取得内容の指定可)
debugLogLevelerrors,warnings,notices等のログレベルの設定
forceRequestBodyVariableリクエストボディが検査項目に無い場合のみREQUEST_BODY変数に値の設定可
requestBodyAccessリクエストボディのバッファや処理を行う
requestBodyLimitリクエストボディをバッファで保持するmaxサイズを設定
requestBodyProcessorデフォルトではURLエンコード(application/x-www-form-urlencoded)と
複合型(multipart/form-data)のフォーマットを処理。JSONやXMLも可。
responseBodyAccessレスポンスボディをバッファさせる
responseBodyLimitレスポンスボディをバッファで保持するmaxサイズを設定
ruleEngineルールエンジン(検査とブロック)の起動の設定
ruleRemoveByIdIDにより適用しないルールを設定
ruleRemoveByMsg正規表現で合致したメッセージのルールは適用しないよう設定
ruleRemoveByTagタグの指定により適用しないルールを設定
ruleRemoveTargetByIdIDによりターゲットリストの削除を設定
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 検査対象文字列のファイル名

【例】pmFromFile
SecRule 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

の三つを設定します。これを基本にファイルを作成して該当フォルダに保存しましょう。

書き方

SecRule VARIABLES OPERATORS ACTIONS

VARIABLES検査したい項目(どの項目を検査したいか)
OPERATORS検査したい内容(特定の文字やIPアドレスを指定)
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 情報セキュリティ

WAFModSecurity

Posted by Bright_Noah