Web Application Firewall(WAF)に意味は無いという話ではないです。ただ、私は費用対効果が薄いので否定的な気持ちです。運用を行える労力と金が許すなら入れればいいのではと思います。
なぜか仕事でWAFの導入相談をされることがあり、その時の考えを2022年の終わりぐらいから書き散らしては塩漬けを繰り返していたのですが、今も気持ちは変わってないので公開してみます。
要約
私の記事には新規性はないです。mod_securityなど具体的なWAF製品には触れません。
こんな記事を見るより、以下をお読みください。
2011年にIPAもWAFの導入に関する手引きを書かれています。WAFのメリット、導入判断、運用についても触れられています。
2008年に徳丸先生が以下の記事を書かれています。
古い記事に見えますが、現状はあまり変わってないと私は感じます。
このあたり読んでおけば判断できるはずです。ありがとうございました。
私の感想
Azure FrontDoorとAzure ApplicationGatewayのWAFを少し運用している程度のペーペーの一意見としてください。
私は「WAFは費用対効果が薄いのでは」という立場です。
- WAFは効果はあるが万能ではない
- WAFは入れてお終いではなく、WAFのための運用も必要(マネージドでも必要)
- コストが掛かるし、オーバーヘッドも掛かる
徳丸先生の記事で以下の記述がありました。
割高で あてにならぬも 負担増
私の感覚ですが、この状況は今もさほど変わっていないように思います。
クラウドサービスの台頭で必要な時にすぐ導入でき、コストも月5000円程度から使えるようになっており導入はしやすくなりました。何かあったときに困るからとにかく入れておけ、という選択もさほど悪くないとも思います。金があるなら入れるといいでしょう。(AzureもFrontDoor Classic時代は安価に始められたのですが、それが廃止予定になってしまい現状の最低ラインは月$300からであり、ちょっと「ウッ」となる金額感)
しかしまだ運用があります。手元では動いても動作環境だとリクエストをふさがれてしまい、ため息をつきながら除外ルールを書くという作業が増えたりといったことも。それでいて絶対ではない。
そんな感じで、WAFはめちゃくちゃ高くてお手入れが必要な「おまもり」という認識です。
蛇足:「セキュリティ」という言葉について
WAFとはあまり関係ないですが、次の動画で竹迫先生が「セキュリティという言葉を使わずにやりたいことを説明してみる」とおっしゃっていました。
セキュリティというワード自体はメジャーになっているが故か、アプリケーション開発するときにお客様とか上司とかから「セキュリティは大丈夫?」と口を出されることがよくありました。
これに対してYES/NOで答えるには難しく、セキュリティに絶対はないと思っているのでYESと言い切れないし、かといってNOとは言えないので、「頑張ってます。アハハハ」と返すこともありました。
とはいえ「具体的に何を気にされています?」と掘り下げると、時間を食いつぶす話題でもあり、その割には得られるものが少なかったり発言が有識者に偏るみたいな状態になったり、うまく回せない。みんなそんなことより早く開発進めてスケジュール通りにリリースしたいよな、と思ったり。でも蔑ろにできないもどかしさがあったり。壁打ちできる相手がほしい。でもコミュニティは怖い
ただやっぱりセキュリティというワードは広すぎるので、1個1個具体的にして潰していくしかないのだなと思ってます。(浅い感想)
以降も書き散らし。
WAFの意味
WAFはクライアント→サーバ間のリクエストの内容を検証し、問題があればアラートをあげたりリクエストを遮断するための装置。
WAFは基本的にルールベースで防ぐ手法であり、わかりやすいのはkey=onload=alert(1)
みたいなクエリ文字列に特定の文字列が入っていると引っ掛かるなどがある。
セキュリティでは「多層防御」という考え方がある。WAFは多層防御の手段の一つであり確かに効果がある。
人が安全なアプリを正しく実装できていない可能性を前提として防ぐ
脆弱性がないことを示すのは非常に困難である。しかしアプリに脆弱性があったとしてもリクエストをアプリまで到達させなければ攻撃として成立しなくなる。そのためのWAF。
潜在的な脆弱性に対する攻撃を防ぐ
例えば「SQLインジェクションの脆弱性があるライブラリ」があるとして、それがまだ表面化していないケースがある。
そういったものはWAFで弾ける可能性がある。SQLインジェクションはメジャーな脆弱性であり検知するためのパターンが多く用意されている。
未知だった脆弱性に対する攻撃を防ぐ
未知だった攻撃がWAFのアップデートにより勝手に対応できる場合がある。例えばlog4shellの時は1日ぐらいで各WAFサービスが対応を公表していた。
逆を言えば対応するまではWAFは何の役にも立たない。既知のモノしか弾けない。それでも勝手に対応してくれるのは嬉しいかもしれない。
付加価値がある
例えばレートリミットをつけるWAFもある。攻撃者はたいてい手当たり次第攻撃してくるため、リクエスト数が明らかに多くなることから、レートリミットをかけるのは有効と言える。この閾値を決めるのがつらいですがね。やたらリクエスト飛ばしてくると思ったらただのヘビーユーザーだったとか。
ロードバランサを兼ねることもある。他に色々あるでしょう。
脆弱性対応できないので入れる
お、おう…既存の振る舞いが壊れないといいですね…
WAFの運用
導入して終わりではない
WAFは導入してお終いではない。WAFはアップデートされていく。
WAFのポリシーアップデートの作業を手動で行う必要がある。WAFのアップデート起因でリクエストが通らなくなるリスクがある。引っ掛かるということはそもそも相当問題があるリクエストだったともいえるけど、急に振る舞いが変わることは覚悟しなくてはならない。
開発と本番の差異の戦い
開発中はほとんどWAFを使って動作の検証をすることはない。そのため、本番に反映したら動かないといったことが起きる。動かないだけならまだマシで、ほとんど動くけど特定のユーザの操作が動かないといった報告をもらった日には最悪だ。攻撃者も含まれた検知ログから特定のユーザのリクエストを見つけ出し、どういうルールが引っ掛かったのか調べ、アプリ上これは許容すべきか考えたり、該当のルールを除外するか、独自ルールを書いて特別対応で通過させるかなどしないといけない。こうした日々の運用で対処していくこととなる。
そして、どでかいファイルは処理できないことも。ちゃんと等価環境を用意して検証しましょう。
システム要件とWAFの誤検知の戦い
経験上、ユーザが自由入力できる系のシステムでは誤検知(False Positive)が非常に多くなる。例えばコメントを書く、名前を設定する、メールアドレスを設定する等。この中に特定のワードが(onclick等)があった瞬間ブロックされる。
これらを誤検知として除外することは簡単だが、その中には本当は通したら不味いケースが潜んでいてその検知が漏れる(False Negative)といった可能性がある。
また、WAFはエンドポイント単位でルール除外ができないことが多い。そうなると、基本的にチェックしてほしいけどこのAPIのために除外しないといけないという場合はカスタムルールを書いたりする。ルール職人の誕生である。
何も考えずシステムを動かすために除外を選ぶとリクエストは通るようになるが、WAFの意味がなくなっていく。
そういったリスクの天秤をずっとかけ続けないといけない。誰が?
ところで検知モードのままで運用していませんか?
WAFサービスにはたいてい検出だけして防止しないモード(検知モード)が用意されています。これは以下のように使えます。
- 検知モードにする
- デプロイ後に正常なリクエストをしばらく流す
- おもむろに検知ログを確認する
- 検知ログに検知の痕跡がある場合、どういう条件(ルール等)で引っ掛かったか確認し、通すべきか否かを検討する
- ルールを変更した場合、再検査する
- 満足したら検知モードをオフにする(防止モードにする)
この最後の戻す作業を忘れるとWAFは機能しません。
もしくは「WAFが防いでるのはわかるけど、すぐ動かすようにしないと…とりあえず検知モードにして動作を優先させよw」とした後に戻す手順を忘れるということもあります。
WAFの闇
WAFの説明を受けた人は素敵なものだと思うかもしれません。しかし、WAFは入れれば幸せになるものではありません。
万能ではない
WAFはリクエストデータをアプリがどのように扱うかといった文脈までは理解できる造りにはなっていない。とにかくヤバそうなパターンにどれだけ一致するかでスコアリングして弾く戦略になっている。これは誤検知(False Positive)や検知漏れ(False Negative)を生む。
検知漏れが厄介で、ちょっとした細工で回避できてしまうケースがある。Log4Shellの時は${jndi:
だと引っ掛かるが${${lower:J}ndi:
とすると突破できちゃうというのがしばらくあった。なんか気取ってリクエストデータをBASE64で符号化したりしていませんか?WAFはそこまで見てくれないですよ。
脆弱性を生むのは人間であり、WAFのルールを書いているのもまた人間なのだ。
そもそも外部から取りうる値は決まっていることが多いはずである。なので値を限定して受け付けるように実装すべき。つまりバリデーションである。(バリデーションが完ぺきならWAFは要らねえ!という思想がちょっとあります)
スループットの低下、レイテンシの増加
WAFは、TLSの暗号化された内容を復号化し、ヘッダを読み、リクエストデータを読み、バッファに載せて起き、パターンにマッチするかどうか分析し、問題がなければリクエスト先にバッファしたデータを流すということをする。
これだけのことをするのだから、それなりのオーバーヘッドが掛かる。
なお、レスポンス時もブラウザで表示したらアウトな攻撃(主にXSS)があるので、このチェックにもオーバーヘッドがかかる。
アタックサーフェスを増やすかも
WAFの設定ミスで事故になった事例がある。
SSRF攻撃によるCapital Oneの個人情報流出についてまとめてみた - piyolog
「なんでリクエストの内容を検証するだけのものがそんな動きするんだよ」という不思議なこともあるのですが、それはログを記録するだけのLog4jの時にもあったように、今や何が脆弱性になるのかわからん時代です。
ただ、上の件はAWS WAFではない独自のWAFを立てていたらしく、そこが悪用されたという話のようで、このケースが特殊なだけという見方もできる。
とはいえ、脆弱性をつくなら1個でも穴があれば突けることも多いので穴となる箇所は減らすのも大事。「ある」のがいけない。でもWAFでアプリに存在する穴を塞ぐこともできる。どっちなんだ!
コンサルの金儲け
「何かあったら信用を失いますから、そのリスクをより低減させるためにWAFを入れるべき」と不安を煽り導入させる人がいる。
もちろん、攻撃を防ぐ手段が増えて良いものではあるので導入するのは間違ってはいない。が、その効果や後ろにある運用があまり語られない。WAFについて検索してみると、紹介程度の記事が多くひっかかるでしょう。なおIPAの記事は2ページ目で善戦している。
スループットが落ちたりSPOFを防ぐために、冗長構成を提案してさらに倍プッシュしてくることも。
でも「なんかあったときどうするんだ!」と言われるともう何も言えません。なんかってなんだよ…もう面倒だなぁ…WAFと運用の金を出してくれるなら別にやりますけど…
WAFはSaaSもあり昔よりも手頃にはなってきたが、どんなに小規模でも5000円/月ぐらいはかかる。そして扱うルール数やリクエスト数に比例することが多いのでさらにかかる。特にAzureのWAFの価格設定は高すぎる。
どうしていくべきか?
答えは人それぞれだと思います。
私は「WAFは既知のものしか弾けず、コスト的にも運用的にも導入の割に合わない」と考えています。
そもそも、よくわからない特殊なリクエストを受けるような前提でアプリを作らないはずなので、当たり前のことをやっていけばWAFなんてなくてもいいのではと思っています。
- 脆弱性はない前提でアプリ開発をする。
- 脆弱性を仕込まないようにセキュアなコーディングを心がける
- 外からくるデータは信頼しない(バリデーションする)
- 採用するライブラリはメンテナンスされているものを使う。もしくは全貌が把握できる程度の小さめなライブラリを選び面倒を見るつもりで採用する。
- WAFを入れても攻撃を受ける時は受けるので「ドーンと構えようや」という気持ち
- いつでもすぐに修正しデプロイできる環境を作る
- 自動テストを整える
- デプロイの自動化
- いつでもすぐに修正しデプロイできる環境を作る
- 情報のアンテナを張る。Twitter(現X)でITエンジニアをフォローしておくとデカめな脆弱性があると勝手に騒いでくれる。Twitterも業務と言い張れる
とはいえ、想像の上を行く攻撃もあったり、そもそも実装が至らず攻撃を受けることはあります。そういったものはWAFがあれば防げるかもしれないのもまた事実でもあります。悩みましょう。
もうやることやって脆弱性診断かけて引っかからなければそれでよくないか…?ダメ…?「その脆弱性診断、1発100万とかしますけど」という声も聞こえる。なんかあったときに信用を落とすことを考えれば安いともいえますかね?だったらWAFを…うーん。
蛇足ですが、私が所属している会社はパートナー契約をしているとかで、お客の毎月の支払いに応じたインセンティブがちゃりちゃり入るので導入できるならしたかったりします。働かずに金ほしい。でも誠実じゃないよね。