LoginSignup
47
39

More than 5 years have passed since last update.

ModSecurityのルール設定を読めるようになりたい!

Last updated at Posted at 2016-12-08

ラクス Advent Calendar 2016の9日目です。

昨日は@nyakomeさんの「Selenideでテストコードを書いてみた」でした。

何を書こうか迷ったのですが、WAF(Web Application Firewall)について書いてみようと思います。個人的に興味がありつつも漠然とした知識しかなかったので、この機会に調べてみました。

WAFにも色々あるようですが、オープンソースのModSecurityというWAFがあるので、今回はこれを選択しました。

WAFの概要

WAF(わふ)は「Web Application Firewall」の略で、その名の通り、Webアプリケーションを悪意のある通信から守ることを目的としています。

万が一、Webアプリケーションに脆弱性があった場合に、SQLインジェクションやクロスサイトスクリプティングなどの攻撃から守ってくれたりします。もちろん絶対ではないですが。

Webアプリケーションを改修することなく設置できる反面、守る対象のWebアプリケーションに特化した作りではないため、正常な通信を悪意のある通信と誤検知する可能性もあります。実運用の前に充分なテストが不可欠です。

ModSecurityのインストールと動作確認

ModSecurityのインストールと動作について簡単に触れておきます。

動作環境としてCentOS7.2を用意。Apacheのモジュールとして動作させてみます。Apacheはセットアップ済みの状態です。

ModSecurityをインストールするだけだと最低限のルールしか設定されていませんので、CRSと呼ばれるルールセットも一緒にインストールします。

yum -y install mod_security mod_security_crs

私の環境では下記のバージョンがインストールされました。

  • ModSecurity 2.7.3
  • CRS 2.2.6

Apacheを再起動した後、怪しげにアクセスしてみます・・・
スクリーンショット 2016-12-05 22.10.49.png
おおお!しっかりブロックされました。
ちゃんと動いているようです。

検知ログもちゃんと出てますね。SQLインジェクションのルールに先に当たってしまったようですが。。
スクリーンショット 2016-12-08 23.41.08_2.png

ModSecurityのルール設定

サクサクっとCRSを入れてしまいましたが、どんなルールが入ってるのでしょうか。
分からないと正しいリクエストもブロックされてしまいそうで、安心して使えませんよね。

CRSではたくさんのルールが設定されています。
すべてを解説できると良いのですが、あまりに多いので、ルール設定の読み方などを簡単にご紹介したいと思います。

phase

まずphaseについて説明します。

ModSecurityによる遮断などの処理を実行できるタイミングは、リクエスト処理中のある1点だけではありません。次の5つのタイミングのいずれかで実行することができます。

1: Phase リクエストヘッダー
2: Phase リクエストボディ
3: Phase レスポンスヘッダー
4: Phase レスポンスボディ
5: Phase ロギング

これらはphaseと呼ばれており、それぞれ番号が付いています。

リクエストの内容次第で通信を遮断したければ、12phaseを指定して実行させます。

またリクエストだけではなく、レスポンスの内容に特定の文字が入っていたら通信を遮断する、といったことがしたければ、34phaseで実行させることもできるようです。

5 のロギングのphaseは他と違って、通信を遮断したりすることはできないようですね。
すでにレスポンスを返した後のタイミングでの実行となります。

詳しくは本家のProcessing_Phasesの図を見ると掴みやすいかも知れません。

設定ディレクティブ

ルールの設定をするディレクティブを3つだけ紹介します。

SecRule

概要: 遮断などの処理を実行するルールを設定します。
構文: SecRule VARIABLES OPERATOR [ACTIONS]
 VARIABLES: ModSecurityで扱える変数を指定
 OPERATOR: VARIABLESに対する検査方法を指定。
  @の後にOPERATORを書きます。
  @OPERATORを省略すると、@rx(正規表現マッチ)とみなされます。
 ACTIONS: VARIABLESOPERATORの条件にマッチした場合に実行する処理を指定
 ACTIONSを省略すると、後述のSecDefaultActionが効きます。

SecAction

概要: 無条件で処理を実行します。変数の初期化などに使うようです。
構文: SecAction ACTIONS
 ACTIONS: 実行する処理を指定

SecDefaultAction

概要: 検知パターンにマッチした時のデフォルトのアクションを定義します。
構文: SecDefaultAction ACTIONS
 ACTIONS: 実行する処理を指定

おまけ:SecRuleEngine

概要: 動作モードを指定します。
構文: SecRuleEngine On|Off|DetectionOnly
 OnOffは言わずもがなですね。
 DetectionOnlyは検知だけのモードです。
 実態としてはDisruptive actionsに分類されるACTIONS
 (block, deny, drop, allow, proxy and redirect)
 がすべて動作しないモードのようですので、allowなどは注意が要るかも知れません。
 知らないと「allowで検査が止まらない!なんでだ!」みたいな混乱をしそうです。

 DetectionOnlyは検知ログを出力しつつブロックしないので、
 誤検知されないか検証環境のWebアプリケーションで確認する際に重宝しそうです。
 誤検知確認の時にいちいちブロックされていたら、
 スムーズに検証できないケースもあるかと思いますので。

CRSで定義されているルール

では実際にCRSに入っているルールを見てみます。

CRSのSecDefaultAction

modsecurity_crs_10_config.conf
SecDefaultAction "phase:1,deny,log"

SecDefaultActionとして下記のActionが定義されています。

phase:1
 1(=リクエストヘッダー)のphaseで実行する
deny
 ルールの処理を停止し、トランザクションをインターセプトする
log
 ApacheのerrorログとModSecurityのAuditログに出力する

CRSのSecActionの一例

modsecurity_crs_10_config.conf
SecAction \
  "id:'900001', \
  phase:1, \
  t:none, \
  setvar:tx.critical_anomaly_score=5, \
  setvar:tx.error_anomaly_score=4, \
  setvar:tx.warning_anomaly_score=3, \
  setvar:tx.notice_anomaly_score=2, \
  nolog, \
  pass"

ここでは定数の定義にSecActionを利用しています。深刻度のスコア計算に使う値をセットしているようですね。

id:'900001'
 ルールのID(900000~999999はCRSのために予約されています)
phase:1
 1(=リクエストヘッダー)のphaseで実行する
t:none
 tは変換関数の実行を表します。
 noneはそれまでに掛かっている変換関数の効果を消す関数です。
 SecDefaultActionから変換関数の影響を受けている可能性があるので,
 依存しないように初めにこれを書くのが作法らしいのですが、
 このACTION構成のSecActionで実行する効果はよく分かりませんでした(汗)すみません。
setvar:tx.critical_anomaly_score=5
 setvarは変数の操作です。
 tx.critical_anomaly_scoreという変数を作成し、5を代入しています。
 後で閾値にでも使うのですかね。
setvar:tx.error_anomaly_score=4
 上とほぼ同じ。
setvar:tx.warning_anomaly_score=3
 上とほぼ同じ。
setvar:tx.notice_anomaly_score=2
 上とほぼ同じ。
nolog
 ApacheのerrorログにもModSecurityのAuditログにも出力しません。
pass
 次のルール検証に進みます。
 これがないとSecDefaultActiondenyが指定されているため、ルール検証が止まります。

CRSのSecRuleの一例

activated_rules/modsecurity_crs_41_sql_injection_attacks.conf
SecRule \
  REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* \
  "(/\*!?|\*/|[';]--|--[\s\r\n\v\f]|(?:--[^-]*?-)|([^\-&])#.*?[\s\r\n\v\f]|;?\\x00)" \
  "phase:2, \
  rev:'2', \
 ver:'OWASP_CRS/2.2.6', \
 maturity:'8', \
 accuracy:'8', \
 id:'981231', \
 t:none, \
 t:urlDecodeUni, \
 block, \
 msg:'SQL Comment Sequence Detected.', \
 severity:'2', \
 capture, \
 logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}', \
 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', \
 setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}, \
 setvar:tx.sql_injection_score=+1, \
 setvar:'tx.msg=%{rule.msg}', \
 setvar:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"

SQLインジェクション攻撃の一種にSQLコメントを含むものがありますが、それを検知しようというルールです。

構文(SecRule VARIABLES OPERATOR ACTIONS)と照らし合わせてみますと、

REQUEST_COOKIES|!...の行がVARIABLES

"(/\*!?|...の行がOPERATORです。
@OPERATORが無いので正規表現マッチですね。

"phase:2, \...以降がACTIONSです。
詳しくは本家サイトにお任せするとして :sweat_smile:
setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}, \の箇所で、上述のSecActionで定義されたtx.critical_anomaly_scoreがスコアのカウントアップに使われているのが分かります。

まとめ

ModSecurityのインストールと、ルールの構文について、簡単にご紹介しました。とりあえずこれくらいの知識があれば、構文を本家サイトで調べつつ読み進めて行けるのではないかと思います。

調べるとキリがないくらい機能が盛り沢山ですが、これから導入を検討されている方に、最初の一歩として少しでも参考になれば幸いです。

今回はWAF導入に当たっての検証の必要性にはあまり触れませんでしたが、まずは検証環境で、どれくらい負荷が掛かるのか、誤検知がないかなどを確認されることを最後にお勧めしておきます。

参考サイト

47
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
39