WAF(Cloud Armor) で HTTP PUT がエラーになった理由
はじめに
結論としては設定ミスだったのですが、遭遇するのが2回目だったので、なぜそうなっているかを調べてみました。
背景
新規プロダクト開発で WAF を導入しました。WAF(Web Application Firewall)とは不正な攻撃からWebアプリケーションを保護するものです。GCP 環境なので Cloud Armor を使っていますが、環境に依存しない話なので以下 WAF とします。
ステージング環境に適用してみると問題なく動いていたのですが、一部の変更APIが失敗してしまいました。WAF 以外変更していなかったので、 WAF が悪さしているんだろうということはすぐに分かりました。以前別チームのプロダクトでも同様の事象があったんですよね。
確認してみると、案の定 WAF で、引っかかっていたのはmethod-enforcement
という設定でした。
method-enforcement
とは?
この設定は、HTTP メソッドの中で、許容するメソッドをGET
,HEAD
,POST
,OPTIONS
に絞るというものです。つまり、上記のメソッド以外はエラーとします。
設定しているのだからひっかかるのは当たりまえです。
対応策としては、カスタマイズしてPUT
,DELETE
を追加するか、この設定自体を外して、アプリ側でチェックを固めるかになります。
では、なぜその設定をデフォルトのまま入れてしまったのか?
こちらに、事前構成済み WAF ルールとして記載されているからです。
一通りこの辺は設定するんだな、と思って設定したところ、method-enforcement
が今回の要件に合っていなかったというわけです。
PUT
とDELETE
を制限するのか?
なぜRESTful API で実装しているので、これらのメソッドは使えて当たり前だと思っていました。
なぜデフォルトで制御するんだろうと調べてみたのですが、一般的なウェブサイトではGET
、HEAD
、POST
、OPTIONS
があれば良いよね、ということみたいです。
By default the Core Rule Set only allows the GET, HEAD, POST and OPTIONS HTTP methods. For many standard sites this will be enough but if your web applications also use restful APIs or WebDAV, then you will need to add the required methods. Change rule 900200, and add the HTTP methods mentioned in the comments in crs-setup.conf.
デフォルトでは、コアルールセットはGET、HEAD、POST、OPTIONS HTTPメソッドのみを許可します。多くの標準的なサイトではこれで十分ですが、Webアプリケーションでrestful APIやWebDAVも使用する場合は、必要なメソッドを追加する必要があります。ルール900200を変更し、crs-setup.confのコメントにあるHTTPメソッドを追加する。(DeepL翻訳)
https://blog.frehi.be/2022/04/10/web-application-firewall-modsecurity-and-core-rule-set/
確かにウェブサービスではなく、ウェブサイトであれば表示とフォームくらいなので問題ないですね。
Google のドキュメントでは HTTP 動詞の改ざんを回避するために使用するとありました。
HTTP 動詞の改ざんを回避するには、メソッド適用ルールセット(プレビュー)を使用します。evaluatePreconfiguredExpr('methodenforcement-stable') ルールを使用して、GET メソッド、HEAD メソッド、POST メソッド、OPTIONS メソッド以外の HTTP リクエスト メソッドを禁止します。
https://cloud.google.com/architecture/owasp-top-ten-mitigation-2017?hl=ja
こちらは、例えば意図していないメソッドの認証漏れなどにより、攻撃されないためということみたいです。特にPUT
とDELETE
はリソースを変更してしまうので、攻撃されてしまうと影響が大きいです。
この様な理由で、method-enforcement
はPUT
,DELETE
を制限しているようです。
まとめ
冒頭で書いた通り、結局はただの設定ミスだったわけですが、なぜデファクトスタンダードで設定するような内容で引っかかってしまうのかが分かってすっきりしました!
Discussion