[WAF]Modsecurity設定見直し-IPアドレスでアクセスしてくるもの(ruleId:920350)を遮断

※ 当サイトではアフィリエイト広告を利用しています。リンクは広告リンクも含みます。

この記事は約29分で読めます。

🔍 ModSecurity設定の見直し:IPアドレスでアクセスしてくるリクエスト(ruleId:920350)を遮断するまでの記録

最近、アクセスログを確認していると、ModSecurityがルールにマッチしているにもかかわらず、ステータスコードが200(正常)で返っているケースが多く見られました。これは「警告」扱いであり、実際には遮断されていない状態です。

この記事では、IPアドレスで直接アクセスしてくるリクエストを遮断するという目的のもと、ModSecurityの設定を見直し、ruleId:920350の挙動を調査・検証した過程を記録しています。無料版AIツール(ChatGPT、Claude、Gemini、Copilot)を活用しながら試行錯誤した内容も含め書きます。AIの回答をベースに間違ったことを言っている場合は赤字で明示しています。

広告

IPアドレスでアクセスしてくるとは?

厳密には、すべての通信はIPアドレスを経由して行われます。しかし、ModSecurityのルール 920350 が検出対象としているのは、HTTPリクエストの「Hostヘッダー」にIPアドレスが含まれている場合です。

通常、ブラウザやクライアントは以下のようなHostヘッダーを送信します:

Host: example.com
私のサイトに来る人の場合
Host: kikuichige.com

これは、DNSで名前解決されたドメイン名です。一方、Botやスキャンツールなどは次のように直接IPアドレスを指定してアクセスすることがあります:

Host: 192.168.1.1

このようなアクセスは、RFC違反ではありませんが、自動化されたクライアントや攻撃的な挙動の兆候とみなされるため、OWASP CRSでは 920350 というルールで検知対象になっています。

このルールは、Hostヘッダーが以下の形式に一致するかを正規表現でチェックしています:

  • IPv4アドレス(例:192.168.0.1
  • IPv6アドレス(例:[2001:db8::1]
  • それらにポート番号が付いた形式(例:192.168.0.1:8080

🔍 つまり、「IPアドレスでアクセスしてくる」とは、HostヘッダーにIPアドレスが含まれているリクエストを指しており、これは通常のブラウザアクセスとは異なる挙動です。

わざわざIPアドレスにしている理由は、おそらく番号なので手当たり次第にIPアドレスを変えて攻撃すれば実在するサイトにアクセスできるからだと思います。ドメイン名だと文字列なので適当な文字列だと、存在しない可能性が高くなり、無駄打ちが多数発生するからかも。

SecRuleEngine Onはどこで設定されているのか?

アクセスログを見ているとステータスコード200だが、{“transaction”~,”ruleId”:”920350“,~があった。ruleId”:”920350″はHostヘッダーがIPアドレスである場合にトリガーされます。
検出対象:プロトコル違反。Botや攻撃者がドメイン名ではなくIPアドレスでアクセスすることが多いため、これを検出します。
ステータスコード200:WAF(ModSecurity)がルールにマッチしているにもかかわらず、200が返っているのは、ルールが DetectionOnly モードになっている可能性があります。
ということなので調べた。→/etc/modsecurity.d/modsecurity-override.confにより上書きされ元々ONだったので、この作業は意味なしでした。また、Onになっていても警告と遮断に分かれる仕組みがある。(後述)

owasp/modsecurity-crs:nginx-alpine イメージを使っている場合、ModSecurityの設定ファイルは通常 /etc/modsecurity.d/modsecurity.conf にあります。SecRuleEngine のモードを確認するには、以下の手順でコンテナ内をチェック変更できます

root権限でコンテナに入る

通常の docker exec では root にならない場合があります。以下のように --user root を付けてみてください:

sudo docker exec -it --user root <コンテナ名> /bin/sh

SecRuleEngine の確認方法(Dockerコンテナ内)

設定ファイルを確認 cat /etc/modsecurity.d/modsecurity.conf | grep SecRuleEngine 出力例: SecRuleEngine DetectionOnly このように DetectionOnly と表示されていれば、ModSecurityは検知のみで遮断はしていません。

結果、SecRuleEngine DetectionOnlyでしたが、私のシステムの場合/etc/modsecurity.d/modsecurity.confは、/etc/nginx/conf.d/modececurity.confを経由して読み込まれていることが分かりました。さらに、 modsecurity-override.confを読み込むようになっていて、そこでSecRuleEngine Onになっています。
実際の/etc/nginx/conf.d/modececurity.confは以下のようになっていました。

遮断モードに変更するには(modsecurity-override.confでOnになっているので意味なし)

設定ファイルの該当行を以下のように変更します:

vi /etc/modsecurity.d/modsecurity.conf
キー操作
j:下に移動
k:上
l:右に移動
h:左
x:1文字削除
i:インサートモード
変更箇所
SecRuleEngine DetectionOnly → SecRuleEngine Onesc:コマンドモード(インサートモードから抜ける)
:wq保存終了
exit

設定変更後は、以下で反映されているか確認:

grep SecRuleEngine /etc/modsecurity.d/modsecurity.conf

変更後は Nginxの再起動 が必要です:

sudo docker restart <コンテナ名>

modsecurity-override.conf の挙動

/etc/modsecurity.d/modsecurity-override.conf

owasp/modsecurity-crs:nginx-alpine イメージにおける modsecurity-override.conf のデフォルト状態は、環境変数ベースで柔軟に制御されるよう設計されています。

このイメージでは、modsecurity-override.conf はテンプレートファイルとして存在し、起動時に envsubst によって環境変数を展開して生成されます。

envsubst < /etc/nginx/templates/modsecurity.d/modsecurity-override.conf.template > /etc/modsecurity.d/modsecurity-override.conf

つまり、環境変数によって内容が決定されるということです。


🔧 主な環境変数と初期値の例

以下のような環境変数が使われています:

環境変数初期値説明
MODSEC_RULE_ENGINEonSecRuleEngine の動作モード(遮断)
MODSEC_AUDIT_ENGINERelevantOnlyログ出力の条件
MODSEC_RESP_BODY_LIMIT1048576レスポンスボディの最大サイズ
MODSEC_REQ_BODY_LIMIT_ACTIONRejectリクエストボディ制限超過時の挙動
MODSEC_STATUS_ENGINEOffステータスエンジンの有効/無効

➡ つまり、デフォルトでは遮断モード(SecRuleEngine On)で起動する構成になっています。


実際の挙動を確認するには

コンテナ内で以下のように確認できます:

docker compose exec nginx /bin/bash
env | grep MODSEC
実際に実行すると
MODSEC_TAG=modsecurity
MODSEC_RULE_ENGINE=on
以下略

補足:テンプレートの柔軟性

テンプレートファイル /etc/nginx/templates/modsecurity.d/modsecurity-override.conf.template には、以下のような記述があり、環境変数で置換されます:

SecRuleEngine ${MODSEC_RULE_ENGINE}
SecAuditEngine ${MODSEC_AUDIT_ENGINE}
...

Include の順序によって、後に読み込まれる override.conf の内容が優先されるため、 たとえ modsecurity.confDetectionOnly があっても、override.confOn があれば遮断モードになります。

Includeしているところを探してIncludeの順番を確認しました。
cat /etc/nginx/conf.d/modsecurity.conf
modsecurity on;
modsecurity_rules_file /etc/modsecurity.d/setup.conf;

cat /etc/modsecurity.d/setup.conf
Include /etc/modsecurity.d/modsecurity.conf
Include /etc/modsecurity.d/modsecurity-override.conf

ということでmodsecurity-override.confが優先されSecRuleEngineはデフォルトでOnになっていた。

結局ruleidで検出しているのにステータスコード200の原因をさらに調査すると
ruleId 920350 は「検知専用ルール」で、単独ではブロック動作をしないため、HTTP ステータスは 200 になるようです。これを遮断するには、さらに別の設定変更が必要です。

ruleId 920350 は「検知専用ルール」になっていた。

ChatGptに聞いた。
状況を整理すると:

  • 使用イメージ: owasp/modsecurity-crs:nginx-alpine
  • SecRuleEngine On を指定している
  • アクセスログでは ステータスコード 200
  • しかし、ModSecurity のログには ルールID 920350 にヒット している

1. ルールID 920350 とは?

CRS(Core Rule Set)の 920350 は「Invalid character in request(リクエスト内に無効な文字が含まれる)」を検知するルールです。←copilotに聞いたらHostヘッダーがIPアドレスである場合と答えていた。https://github.com/coreruleset/coreruleset/blob/main/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.confには以下なのでHostヘッダーがIPアドレスだろう。
私の場合

vi /etc/modsecurity.d/owasp-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
で見れました。ファイルが大きいのでcatでは、ちゃんと表示しない。

🔹 ルール 920350 の位置

OWASP CRS の rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf に定義されています。

# Check that the host header is not an IP address
# This is not an HTTP RFC violation but it is indicative of automated client access.
# Many web-based worms propagate by scanning IP address blocks.
#
# -=[ Rule Logic ]=-
# This rule triggers if the Host header contains an IPv4 or IPv6 address, optionally
# extended with a port number. In the case of IPv6 we covering the address with square
# brackets and the address without square brackets.
#
# The regex consists of three main parts and said optional group:
#
# * IPv4 address
# * IPv6 address with square brackets
# * IPv6 address without square brackets
# * optional colon and port number
#
# Please note that the regex does not test the validity of the IP addresses.
# It just tries to detect a potential IP address.
#
# -=[ References ]=-
# https://technet.microsoft.com/en-us/magazine/2005.01.hackerbasher.aspx
#

SecRule REQUEST_HEADERS:Host "@rx (?:^([\d.]+|\[[\da-f:]+\]|[\da-f:]+)(:[\d]+)?$)" \
    "id:920350,\
    phase:1,\
    block,\
    t:none,\
    msg:'Host header is a numeric IP address',\
    logdata:'%{MATCHED_VAR}',\
    tag:'application-multi',\
    tag:'language-multi',\
    tag:'platform-multi',\
    tag:'attack-protocol',\
    tag:'paranoia-level/1',\
    tag:'OWASP_CRS',\
    tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\
    tag:'capec/1000/210/272',\
    ver:'OWASP_CRS/4.19.0-dev',\
    severity:'WARNING',\
    setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"

実際の定義はこんな感じです(要約):

要素意味
SecRuleModSecurityのルール定義の開始
REQUEST_HEADERS:Hostリクエストヘッダーの Host フィールドを対象にする
@rx ...正規表現(regex)によるマッチングを行う
(?:^...$)文字列全体がIPアドレス形式かどうかをチェックする(非キャプチャグループ)
  • ruleId 920350 は phase:1 で動作します。
  • つまり HTTPリクエストの Host ヘッダーが IPアドレス形式かどうかを検出→ スコア加算。

🔹 CRS の各 phase について

  • phase:1 → リクエストヘッダ(HTTP リクエストライン、ヘッダ情報)を処理
  • phase:2 → リクエストボディ(POST データなど)を処理
  • phase:3 → レスポンスヘッダ
  • phase:4 → レスポンスボディ

2. なぜステータスコードが 200 なのか

ModSecurity でルールにヒットしても 「そのルールがブロック動作につながる」設定になっていなければ、リクエストは通過し、Nginx は通常通り処理を返します

CRS の多くのルールは以下のように構成されています:

  • SecRuleEngine On → 検知を有効化
  • 各ルールは基本的に「ログ(log)」か「検知フラグ」を設定
  • 重大なルールがトリガーされた場合に “phase:2, deny” のようなアクションを発動

つまり、920350 自体は「検知(警告)」であり、それ単独では deny を実行しないため、HTTP レスポンスは 200 のままです。

3. 本当にブロックされる条件

CRS の仕組みでは以下のようなフローがあります:

  • 各ルールが「検知のみ」でフラグを積み上げる
  • 「攻撃の可能性が高い」と判断されると、最終的に Anomaly Score が閾値を超えた時点でブロック
  • このときレスポンスコードは 403 Forbidden になるのが一般的

もし 200 のまま なら、

  • SecDefaultActionlog になっていて deny が効いていない
  • Anomaly Scoring の閾値(例:tx.inbound_anomaly_score_threshold=5)を超えていない
  • もしくはルールセットの paranoia level が低いため警告で終わっている

結論
ruleId 920350 は「検知専用ルール」で、単独ではブロック動作をしないため、HTTP ステータスは 200 のままになります。
本当にブロックしたい場合は:

  • SecRuleEngine On の確認に加え、
  • modsecurity.confmodsecurity-override.confSecDefaultActiondeny,log,status:403 にする
  • または Anomaly Score の閾値を調整する

Anomaly Scoring モードと Traditional モードの違い

  • CRS 3.x 以降(現在主流の v4 系も)
    Anomaly Scoring モードがデフォルト で、Traditional モードはサポートされていません。
  • 切り替えスイッチのような設定項目はなく、
    SecDefaultAction の書き方と「評価ルール(949110/959100)」の有無で挙動が決まります。

仕組み

  1. Anomaly Scoring モード
    • 各ルールが setvar:tx.anomaly_score=+X のように「スコア加算」する。
    • 最後に 949110 (Inbound Anomaly Score Exceeded)959100 (Outbound Anomaly Score Exceeded) が動いて、スコアが閾値を超えていれば deny
    • デフォルトの crs-setup.conf はこの方式。
  2. Traditional モード(CRS 2.x 時代の挙動)
    • ルールごとに deny を書き、ヒットしたら即時ブロック。
    • 今の CRS ではこのモードは推奨されておらず、設定ファイルにサンプルもありません。

私の場合

/etc/modsecurity.d/owasp-crs/crs-setup.conf

SecDefaultAction "phase:1,pass,log,tag:'modsecurity'"
SecDefaultAction "phase:2,pass,log,tag:'modsecurity'"
この設定は、リクエストの処理フェーズ1(phase:1)とフェーズ2(phase:2)において、デフォルトのアクションを定義しています。

pass: ルールが一致しても即座に処理を停止せず、次のルール評価に進むことを意味します。これがAnomaly Scoring Modeの肝で、各ルールがスコアを付与するだけで、すぐに拒否しないようにしています。

log: ルールが一致した際にエラーログに記録します。

tag:'modsecurity': ログにmodsecurityというタグを付与します。

と書かれていたので、Anomaly Scoring 用のルール(949110/959100)が動けない状態です。
つまり「Anomaly Scoring モードに入っているが、pass にしているせいでブロックしない」状態です。

✅ まとめると:ルール 920350 について

  • これは phase:1 (リクエストヘッダ解析フェーズ) で動作するルールです。
  • マッチした時点では deny はせず、tx.anomaly_score を加算します。(理由:SecDefaultAction "phase:1,pass,log..." が設定されているため)

最終的な判定

  • CRS では 直ちにブロックせず、最後に「評価ルール」でまとめて判断します。
  • その役割をするのが REQUEST-949-BLOCKING-EVALUATION.conf にあるルール群です。

代表的なのがこれ:

SecRule TX:BLOCKING_INBOUND_ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" \
    "id:949110,\
    phase:2,\
    deny,\
    t:none,\
    msg:'Inbound Anomaly Score Exceeded (Total Score: %{TX.BLOCKING_INBOUND_ANOMALY_SCORE})',\
    tag:'anomaly-evaluation',\
    tag:'OWASP_CRS',\
    ver:'OWASP_CRS/4.19.0-dev'"

なぜ phase:2 なのか

  • CRS 3.x までは 949110 が phase:1 にあったので、リクエストヘッダ解析後すぐにブロック判定していました。
  • CRS 4.x では設計が変わり、最終的なスコア判定は phase:2(リクエストボディ/全体解析後)で実施するようになっています。
    • 理由:ヘッダだけでなく、リクエストボディや他フェーズの検知も含めて総合的に anomaly score を評価するため。
    • つまり、全体を見終わってから「スコアが閾値を超えたか?」を判定する設計です。

観測した動き(200 になる)

  • 920350(phase:1 ルール)でスコア加算。
  • でも 949110 は phase:2 なので、この時点ではまだブロックしない。
  • その後、949110 が走るが、もし TX.BLOCKING_INBOUND_ANOMALY_SCORE < 5 なら deny されない。
  • 結果、リクエストは「200 OK」となる。

確認ポイント

  1. ログに TX.BLOCKING_INBOUND_ANOMALY_SCORE がいくつ記録されているか←{“transaction”に、この表記はないが"severity":"4" と出ている。3ではなく4なのは最後まで分からなかったが4以下なので状況は同じ。
    [error](status code403など)のときTX.BLOCKING_INBOUND_ANOMALY_SCOREは記録されている。
    • ここが 5 以上ならブロックされるはず。
    • 4 以下ならスルーされて 200
  2. 920350 の severity(重大度)
    • CRS のデフォルトだと
      • CRITICAL = +5
      • ERROR = +4
      • WARNING = +3
      • NOTICE = +2
    • もし 920350 が WARNING なら +3 なので、単発では threshold=5 に届かない。

✅ まとめ

  • CRS 4.x では 949110 が phase:2 に移動 → 全フェーズのルールが走り終わってから判定する。
  • 920350 は phase:1 のスコアルール → それだけではブロックしない。
  • 実際の挙動は severity と threshold の組み合わせ次第

CRS の severity と anomaly score

CRS のルールは「severity」と「加算される anomaly スコア」がマッピングされています。
デフォルトはだいたいこんな対応です:

severityanomaly score
CRITICAL5
ERROR4
WARNING3
NOTICE2

920350 の場合

  • ドキュメントやルールファイルのコメントでは WARNING とされているケースが多いですが、
  • 実際のログに "severity":"4" と出ているなら、それは ERROR 扱い → anomaly score +4 が加算されている、という意味です。

これは CRS のバージョン差やルール調整によって変わることがあります。
(CRS 3.3 系と 4.x 系で severity が違うルールがいくつか存在します)


だから今の状況では

  • inbound threshold = 5
  • 920350 = +4 (ERROR)

👉 単発では 5 に届かずスルー(200 OK)
👉 もし別の小さいルール (+1 や +2) と組み合わされれば 合計 ≥5 でブロック


対応の選択肢

  1. threshold を 4 に下げる
    • 920350 単発でブロック可能。
    • ただし他の ERROR 級ルールも単発でブロック → 誤検知リスク上昇。
  2. 920350 だけを強制 deny にするSecRuleUpdateActionById 920350 "deny,log"←これを最終的に採用
    • threshold は 5 のまま維持。
    • 920350 だけは Traditional 方式で即ブロック。
  3. severity を上書きして CRITICAL (5) にするSecRuleUpdateTargetById 920350 "severity:CRITICAL"
    • そうすれば単発で threshold=5 を満たす。

✅ まとめ
ログに "severity": "4" と出ているなら、CRS 4.x では 920350 は ERROR(スコア+4) になっている。
→ threshold=5 のままでは単発ではブロックされない。
→ 「確実に落としたい」なら threshold を下げるよりも、920350 を個別に deny か severity=CRITICAL に上書きするほうが安全

anomaly score の閾値(threshold)

crs-setup.conf にある

SecAction \
  "id:900110, \
   phase:1, \
   nolog, \
   pass, \
   t:none, \
   setvar:tx.inbound_anomaly_score_threshold=5,  \
   setvar:tx.outbound_anomaly_score_threshold=4"

が、anomaly score の閾値(threshold)を決めている設定です。

詳しくいうと
  • tx.inbound_anomaly_score_threshold=5
    • リクエスト(inbound)側のスコア合計が 5 以上になると、
      REQUEST-949-BLOCKING-EVALUATION.conf の 949110 で deny されます。
  • tx.outbound_anomaly_score_threshold=4
    • レスポンス(outbound)側のスコア合計が 4 以上になると、
      RESPONSE-959-BLOCKING-EVALUATION.conf の 959100 で deny されます。

ポイント
  • この値は crs-setup.conf の 900110 ルールで初期化されるので、
    他の設定で再定義しない限り、この値が使われます。
  • デフォルトの CRS 配布物でも同じ記述が入っていて、これをコメントアウトすれば「スコア加算はするがブロック判定は動かない」状態になります。
  • 実運用では、まず高め(例: 100)に設定して「誤検知を潰しながら」少しずつ下げていくのが推奨されています。

✅ まとめ

  • はい、tx.inbound_anomaly_score_thresholdtx.outbound_anomaly_score_threshold の値は crs-setup.conf の SecAction(id:900110) で決まります
  • デフォルトは inbound=5, outbound=4。
  • これが「何点でブロックするか」を最終的に決める基準値です。

👉 もし「920350 の単発検知で必ずブロックしたい」なら、threshold を 5 に保ちつつ 920350 の severity を CRITICAL(5) に上げるか、Traditional モードのようにそのルールだけ deny を直書きする方法があります。

inbound thresholdを下げたら?

1. 仕組みのおさらい
  • ルール 920350phase:1 のルールで、
    anomaly scoring モードでは スコアを加算するだけ
  • それが「CRITICAL (5点)」なら、今の inbound threshold=5 で 単発でもブロックされます。
  • 逆に「WARNING (3点)」や「NOTICE (2点)」なら、今の設定 (5点以上でブロック) だと スルーされる → 200 OK。

2. inbound threshold を下げたらどうなる?
  • 例:setvar:tx.inbound_anomaly_score_threshold=3 にすると、
    • WARNING(3) 単発で即ブロックされる。
    • ただし、他の WARNING 級ルールも単発でブロックされるようになるので、誤検知が増えるリスクが高い。

3. 安全な方法

「920350 だけ確実にブロックしたい」という目的なら、threshold を下げるよりも次の方法が推奨です:

  1. カスタムルールで上書き
    modsecurity-override.conf に例えばこう書く: SecRuleUpdateActionById 920350 "deny,log" これで 920350 だけ Traditional モード風に即ブロックできます。
  2. threshold は 5 のまま維持して、他のルールは anomaly scoring でまとめて判定。

4. まとめ
  • threshold を下げる方法
    • 簡単だけど「他の軽微なルールでも即ブロック」になりやすく、誤検知リスクが高い。
  • 特定ルールだけ deny を追加する方法
    • より安全で実運用向き。

解決策(失敗)

docker-compose.yml で:

- ./modsecurity/modsecurity-override.conf:/etc/modsecurity.d/modsecurity-override.conf 

modsecurity-override.confの中身
SecRuleUpdateActionById 920350 "deny,log"

sudo docker compose down
sudo docker compose up -d
sudo docker logs コンテナ名 -f --tail=5 | awk '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10}'

ログ:

90-copy-modsecurity-config.sh: error: can not modify /etc/modsecurity.d/modsecurity-override.conf (read-only file system?)

これは コンテナ起動時に entrypoint スクリプトが /etc/modsecurity.d/modsecurity-override.conf を「書き換えよう」としているのに、そこに volume をマウントしているため「Read-only file system」と見なされて失敗している という状態です。


代替解決方法(やってないが多分ダメ)

modsecurity-override.confvolume でマウントするのではなく、別ディレクトリをマウントする 形にするのが安全です。

例えば docker-compose.yml で:

services:
  nginx:
    image: owasp/modsecurity-crs:nginx
    volumes:
      - ./modsecurity-override.conf:/etc/modsecurity.d/override/modsecurity-override.conf:ro

そして、コンテナ側の modsecurity.conf または crs-setup.conf の最後に include します:

Include /etc/modsecurity.d/override/modsecurity-override.conf

こうすると、エントリポイントの 90-copy-modsecurity-config.sh が触る /etc/modsecurity.d/modsecurity-override.conf はデフォルトのままにしておけるので、エラーになりません。
modsecurity.confは書き換えてももとに戻ってしまう。crs-setup.conf はやっていないが多分同じだろう。

解決策(成功)

# docker-compose.yml  
    volumes:
      - ./modsecurity/z-custom-rules.conf:/etc/modsecurity.d/owasp-crs/rules/z-custom-rules.conf:ro 
# ./modsecurity/z-custom-rules.conf
# ファイル名を z- で始めることで最後に読み込まれます
SecRuleUpdateActionById 920350 "deny,log"

ファイル名を z- で始めることで、CRSの他のルールファイルよりも後に読み込まれ、SecRuleUpdateActionById が確実に適用されます。

ローカルからテスト

Host ヘッダーを 192.168.1.1 に偽装したリクエストを送ってみる。

Windows11のAnacondaプロンプトを立ち上げ
curl.exe -k -H "Host: 192.168.1.1" サーバーのIP

"Host: 192.168.1.1"は適当な値(下と同じでもいい)
サーバーのIPは、サーバーのちゃんとしたIPをかかないとつながりません。

対策前
私のIP - - [05/Sep/2025:09:09:00 +0900] "GET / HTTP/1.1" 301 162
{"transaction":{"client_ip":以下略
httpsではなくhttpでの送信なので200ではなく301リダイレクトになってる。

対策後
私のIP - - [05/Sep/2025:09:06:54 +0900] "GET / HTTP/1.1" 403 15
403 Forbiddenなので遮断できました。

補足

自分のIPは除外するときに書いてる場所に以下のように書いてもよさそうですが、

# /etc/nginx/conf.d/jikken1.conf
modsecurity_rules '
    SecRule REMOTE_ADDR "@ipMatch 自分のIP" "phase:1,id:777,nolog,allow,ctl:ruleEngine=Off,ctl:auditEngine=Off"
    # ルール920350を遮断に変更
    SecRuleUpdateActionById 920350 "deny,log,status:403"
';

注意点:

  • SecRuleUpdateActionByIdはCRSのルールが読み込まれた後に実行される必要があります
  • もしCRSがmodsecurity_rulesより後に読み込まれる場合は、この方法では効果がない可能性があります

この点を確認すると以下のように上書きされる可能性が高い。

検討:

/etc/nginx/nginx.confに以下があり
include /etc/nginx/conf.d/*.conf;
/etc/nginx/conf.d/には以下がある。
default.conf      default.conf.bak  jikken1.conf      logging.conf      modsecurity.conf

modsecurity.confで
modsecurity_rules_file /etc/modsecurity.d/setup.conf;

/etc/modsecurity.d/setup.confで
Include /etc/modsecurity.d/owasp-crs/rules/*.conf
があるので、/etc/nginx/conf.d/jikken1.confの設定て重複しているものがあれば、/etc/modsecurity.d/setup.conf内のInclude /etc/modsecurity.d/owasp-crs/rules/*.confで上書きされてしまう。

対策に成功したz-custom-rules.confは、/etc/modsecurity.d/owasp-crs/rules/*.confにあるので最後の方で読み込まれる。

所感

今回の方法で、他のruleidも追加で遮断できそうです。AIは便利ですが、自分が今、何をやっているか把握しながら質問していかないと変な方向に誘導されます。
結局920350のWARNING値が3か4は分からなかった。

この記事を書いたイチゲを応援する(質問でもokです)
Vプリカでのお支払いがおすすめです。

タイトルとURLをコピーしました