STORES Product Blog

こだわりを持ったお商売を支える「STORES」のテクノロジー部門のメンバーによるブログです。

WebアプリケーションをWAFでサクッと守って年末年始をもっと安心に

STORES 予約の @sa2dai です。

今年は予約管理サービス「クービック」が、heyにジョインさせてもらうこととなり、サービス名称も「STORES 予約」となったそんな年でした。

今回heyアドベントカレンダー2020に参加させてもらい、13日目として本記事を作成しました。

STORES 予約では、セキュリティ対策の1つとして、WebアプリケーションをL7レベルで守るWAF (Web Application Firewall)を導入しています。

L7アプリケーションファイアウォールとかいうと導入大変そうに思えるんですが、awsを利用している方は案外簡単に導入してみることができるので、そのご紹介をします。

WAFとは

「Web Application Firewall」の略で「ワフ」と呼びます。なんかフワッとした、美味しそうな呼び名ですね。自分はサクフワっとしたやつが好きです。

WAFは名が示す通り、ウェブアプリケーション用の、OSI参照モデルでいうL7(アプリケーション)層のファイアウォールで、アプリケーションサーバの手前に設置されます。

WAFはウェブアプリケーションサーバに飛んでくるリクエストのパス・ヘッダー・ペイロードを評価し、リスクのある通信であれば通信をブロックすることで、アプリケーションサーバに到達することを防いでくれます。例えばSQLインジェクションクロスサイトスクリプティング等の攻撃を認識しブロックできます。

f:id:sa2dai:20201213091518p:plain

通常よく言う「ファイアウォール」がL4でTCP X番ポート通信を許可・拒否するに対し、同じことをL7レベルでWebアプリケーションに対して行うので「Web Application Firewall」と言います。

aws WAF

WAFベンダーが各社存在し、ハードウェアとして提供されるもの、ソフトウェアとして提供されるもの等いろいろありますが、awsでは「aws WAF」という名のサービスとして提供しています。コンソールをポチポチするだけで既存のAWS環境にWAFを導入できます。

WAFサービスを構築後、ボタンを押すだけで既存のCloudFront、ALB、Amazon API GatewayAWS AppSyncにアタッチする形で導入が完了するのでかなりお手軽に導入できます。

f:id:sa2dai:20201213091523p:plain
https://aws.amazon.com/jp/waf より引用

AWSのWAFには現状AWS WAF Classicと最新版のAWS WAF(wafv2)が存在しますがここではAWS WAF(wafv2)を紹介します。

aws WAFの構築・設定方法

例として今回、awsのApplication Load Balancer配下にあるWordpressサーバに対してOWASP1で提唱される脆弱性対策を含むWAFを適用する、としてみます。

なお、STORES 予約では通常AWSの設定はTerraformで管理しているのでWebコンソールでポチポチはしないのですが、ここではWebコンソールでの設定で説明します。もちろんTerraformでも作成・管理できます。

次の図のようにAWS WAFは、Web ACLというWAFの設定リストを持ち、そのリストに複数の制御ルールを定義し、その条件に基づき通信の許可・ブロックを行います。

f:id:sa2dai:20201213100938p:plain

従い、手順としてはざっくり次の通りです:

  • Web ACLを作成
  • Web ACLに制御ルールを追加
  • Web ACLに保護対象のリソースを追加

Web ACLを作成

リソースの保護の仕方を制御する設定リスト、Web ACL(Webアクセス制御リスト / Web Access Control List)を作成します。

このリストにより、次の条件を元に許可・拒否設定ができます:

1つのWeb ACLに複数のリソースを紐付けることが可能です。 また、全許可 or 全拒否だけでなくリクエストレート上限を設ける、的な設定も可能です。例えば特定の国からの通信にはレートリミットを設けることが可能です。

f:id:sa2dai:20201213091529p:plain

フィールド名 指定する内容
Name このWeb ACLの利用目的・内容がわかるような名前を指定します。
Description このWeb ACLの説明をDescriptionとして記載できます。
CloudWatch metric name: WAFを通るトラフィック情報や制御結果がCloudWatch メトリクスが発行されるのでそのメトリック名を指定します。
Resource Type CloudFrontかそれ以外かを選択します。今回はApplication Load Balancerなので「Regional resources」を選択します。
Region このWeb ACLを作成するリージョンを指定します。保護するリソースのリージョンに合わせます。Regionはリージョン別リソースタイプの場合のみ選択。CloudFrontの場合、グローバルアプリケーションであればリージョンは us-east-1 になります。

この時点で適用する具体的なリソース(ALB)を指定可能なのですが、追加しないで作成もできます。いきなり作成して調整前に適用されるのが怖い、という場合は指定せずに「Next」を押します。

f:id:sa2dai:20201213091533p:plain

Web ACLに制御ルールを追加

次に制御ルールを追加します。この画面の「Rules」が制御ルールとなり、ここに適用する制御を追加していきます。「Add Rules」より追加します。

f:id:sa2dai:20201213091537p:plain

選択肢 意味
Add managed rule groups AWSやセキュリティベンダーが作ったマネージドルール設定から選んで追加する
Add my own rules and rule groups 自分でルールを定義する

ここでは一旦、便利なプリセットである、マネージドルールグループを追加してみましょう。実際では自社のカスタムルールと組み合わせて運用をしています。

managed ruleはAWS製、外部ベンダー製から選んで適用できます。外部ベンダー製を利用する場合はAmazon Marketplaceで購入する必要があります。ここではAWS製を使ってみます。

f:id:sa2dai:20201213091542p:plain

よさそうなのが並んでます。リクエスト元・OSや保護対象とするアプリケーション等に応じたルールセットが提供されており、それぞれのRuleがどのような通信から守ってくれるのか記載がされています。「Add to web ACL」をすることでルールを追加できます。複数追加も可能です。

f:id:sa2dai:20201213091546p:plain

ここにでてくる「Capacity」は、WAF Capacity Unit (WCU)のことで、ルールの処理コストを数値化したものと理解してます。標準状態ではルールグループに追加されたルールのWCU合計値が1500を超えないように設定する必要があります。超えて設定したい場合はAWSのサポートに制限緩和申請が必要です。

一方で、AWSの料金詳細によると、現時点ではWCUを元に料金計算はされません。

例えば、保護対象となるアプリケーションサーバLinux上に構築されたWordpressの場合を想定し、Wordpressのアプリケーション脆弱性をついてくるような攻撃に対して保護したい場合は「Linux operating system」「Wordpress application」を選ぶ等します。

特に、OWASPで提言されている脆弱性対策の一部が含まれるCore rule set、Known bad inputs、SQL databaseや、AWSが脅威対象と認定しているIPリストのブロックをしてくれる「Amazon IP reputation list」あたりは入れておくと安心です。

但し、ルールによって正常な通信を阻害してしまう可能性もありますので、そのような場合は適用除外条件を作るなり、自前ルールを作るなりする必要があります。

その為、まずは「Set rules action to count」を選んでおくのが安全です。「Add to web ACL」を選ぶとこのトグルが出てきます。これはブロック対象と判定されたことをカウントしつつ、実際に通信は許可するオプションです。逆に言うとこれをOnにしたまま運用しても脅威からは守られないので注意しましょう。

f:id:sa2dai:20201213091554p:plain

選択がおわったら画面したの「Add rules」を押します。

最後にどのルールにもヒットしないリクエストをどうするか設定します。

f:id:sa2dai:20201213091558p:plain

今回はブロック条件のみRulesに追加したので、マッチしなかったものは許可する為「Allow」を選びます。Whitelist形式でルールを作り運用する場合は「Block(ブロック)」を選びます。

結果今回このようになりました:

f:id:sa2dai:20201213091603p:plain

次に、ルールを適用する順番を指定します。今回は特に関係ないのでそのまま進みますが、Whitelist / Blacklistのルールが混在する場合等に順番を正しくセットする必要があります。

f:id:sa2dai:20201213091608p:plain

最後の設定、Amazon CloudWatch metricsの設定です。 CloudWatchイベントとしてルールにヒットしたリクエスト数が記録できます。各ルール毎のメトリック名を指定します。 また、Request sampling optionsをEnableにするとルールに評価された直近15分間のリクエストをダッシュボードで確認できるので、ここでは「Enable」にします。

f:id:sa2dai:20201213091614p:plain

最後に、設定内容を再確認する画面で内容を確認します。問題なければ「Create web ACL」を押してWeb ACLを作成します。

f:id:sa2dai:20201213091620p:plain

f:id:sa2dai:20201213091624p:plain

これでWAFの構築自体は完了です。

Web ACLに保護対象のリソースを追加

ではいよいよ、このWAFにリソースを適用しましょう。 サイドメニューの「Web ACLs」> 今回作ったWeb ACL名をクリック > Associated AWS resourcesを選択します。

f:id:sa2dai:20201213091629p:plain

「Add AWS resources」を押していただき、今回適用したいリソースを選択し「Add」を押します。

f:id:sa2dai:20201213091633p:plain

「Success」が出ました。これで適用完了です。

f:id:sa2dai:20201213091638p:plain

「Overview」の画面を見るとALBからWAFに流れてくるリクエストがグラフに現れます。

f:id:sa2dai:20201213091643p:plain

もし追加したルールにヒットするリクエストがある場合は、そのヒット数もグラフに現れます。今回は「カウントするがブロックはしない」という設定にしていますので、「Counted Requests」が表示されます。

通信ブロックと検証

通信をブロックする

では、実際に通信をブロックしてみます。先程作成したルールを編集し「Enable count mode」をOffにします。

f:id:sa2dai:20201213091648p:plain

ブロックされるか検証する

試しに、脅威のある悪いリクエストをサーバに対して投げます。悪いリクエストの内容はここでは伏せますが、LFI(Local File Inclusion)の脆弱性を突こうとするリクエストを投げてみました。すると、このようにWAF層でブロックされ403 Forbiddenとして返答されます。

f:id:sa2dai:20201213091652p:plain

また先程の「Overview」に検知したことがグラフ化され、Sampled Requests内にどのルール適用によってブロックされたか、リクエスト元IP情報とともに表示されます。

f:id:sa2dai:20201213091656p:plain

f:id:sa2dai:20201213091701p:plain

このSampled Requestsは過去15分間のリクエストに対して、ルールに一致及びデフォルトアクションが適用された最大100リクエストのみ表示されます。

実際の運用で検証する場合は「Logging and metrics」よりログ設定をしてKinesis経由でS3等に保存して長期間のデータを見れるようにします。

f:id:sa2dai:20201213091705p:plain

とはいえ、まず「守ってみる」というのはこの手順で完了です。 これだけで様々なリクエストが飛び交う脅威から守られます。

利用料金

aws WAFは無料ではありません。ですが、手軽さと効果に対してはコスパよいと考えています。WebACL1つあたり月5.00USD、WebACLに追加するルールの数 x 1.00USDとリクエスト数 / 100万 x 0.60USDがかかります。

従い、先程の例ではWebACLが1つ、6つのマネージドルールなので1 x 5.00USD + 6 x 1.00USD = 11.0USDの月額と、サイトへのリクエスト数に対する従量課金が発生します。

料金詳細はこちら

おすすめの導入手順

WAFの仕組みとして、Webアプリケーションのコードを知らずにL7レベルで通信内容を評価する為、当然ながら正常な通信を誤ってブロックし障害となりえます。

従い、次の手順での導入がおすすめです:

  • 適用範囲をアプリケーション全体にせず、一部のみ対象とするようルールを設定する
  • Count機能を用いて投入し、ブロック対象と判定されるリクエストを記録
  • そのリクエストに正常なものが含まれていたらブロック除外とならないようルール設定を直す
  • その後Count機能で記録されるものに誤りがなければブロックするように設定する
  • 適用範囲を広げていく

最後に

アプリケーション脆弱性を外部から守る仕組みとしてWAFをご紹介しました。 とはいえ、WAF適用すればセキュリティ対策バッチリということでもないので、日々がんばりつつよい年末年始を迎えましょう。


  1. Open Web Application Security Project(国際ウェブセキュリティ標準機構)の略でウェブアプリケーションのセキュリティ対策・向上を目的とした米国に本部を持つ非営利団体。Webアプリケーションのセキュリティ脅威や危険性のトレンドの中で最も危険度が高い10トピックを「OWASP Top 10」と呼び、その内容を把握・対策することで、最新の脅威対策に役立ちます。日本ではIPAやJPCERT等がありますが、これらもOWASP Top 10をガイドラインの中で言及しています。STORES 予約でもこのOWASPに準拠して対策しています。