AWS WAFでSQLインジェクションと特定URLをブロック

AWS WAFがCloudFrontだけでなくELBでも使えるようになり、より使いやすくなったので、SQLインジェクションや非公開ファイルへのアクセスをブロックしてWAFのメリットを確認していきましょう。

脆弱性を持ったアプリケーション

最初に、テストのためにSQLインジェクションが可能なRailsアプリケーションを作成します。普通にRuby on Railsでアプリケーションを作ると基本的なリスクヘッジがされていますが、ここではあえて脆弱性を含むコードを書いてみます。

Userモデルに名前とメールアドレスのカラムがあるという状態で、入力したメールアドレスと一致するユーザを検索をするために、プレイスホルダを使わずに文字列をそのままSQLとして渡すself.search_unsafeというメソッドを作成します。

class User < ApplicationRecord
# 危険
def self.search_unsafe(email)
User.where("email = '#{email}'")
end
# 安全
def self.search_safe(email)
User.where("email = ?",  "#{email}")
end
end

このメソッドに

' or 1=1 --'

という文字列を入力すると、発行されるSQLは

SELECT `users`.* FROM `users` WHERE (email = '' or 1=1 --'')

となり、意図せず全てのユーザリストが取得できることになります。

WAF

このRailsアプリケーションをEC2にデプロイして、ELB配下に設置します。

AWSマネジメントコンソールからWAFを選択肢、Web ACLの作成を行います。

Web ACLの名前、CloudWatchのmetric名、対象となるELBを指定します。

Webアクセスコントロールリストを作成します。今回はSQLインジェクションとURLに特定の文字列を含む場合をブロックするので、まずSQL Injection match conditionsを選択します。

名前を入力し、今回はフィルターにPart of request to filter onを「Body」、Transformationに「URL decode」を選択します。

同様にString match conditionを作成します。名前、Part of request to filter onは「URL」、Match Typeを「Contains」、Value to matchに「secret」を設定します。これで、secret.htmlなどを含むURLが要求された時にはブロックされるはずです。

次にルールを作成します。「Create rule」を押します。

名前とCloudWatchのmetric名を入力して、条件を設定します。

今回は、SQLインジェクションをブロック、特定文字列に一致したものはブロック、それ以外は許可する、というルールを作成しました。

この内容で作成を実行します。

たったこれだけで、ELBにWAFが適用されます。

/secret.htmlにアクセスしてみると、確かにELBがブロックしています。

SQLインジェクションも、検索実行した後に危険な文字列が含まれているためブロックされます。

マネジメントコンソールで確認してみると、WAFがブロックした履歴が確認できます。

まとめ

CloudFrontを使用していないケースでも、ELBでWAFが使えるというのは、従来からあるアプリケーションにも適用できるのでかなり導入のハードルが下がりました。

アプリケーションの特性にあったルールが設定できるので、AWSでアプリケーションを運用する際にはWAFを検討してみてください。

APN Consulting Partner
スーパーソフトウエアはAWSパートナーネットワーク(APN)のコンサルティングパートナーです。