Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ほんとうに大事なサービスを守れるのか!? 実運用に向けてAWS WAFを検討してみた

ほんとうに大事なサービスを守れるのか!? 実運用に向けてAWS WAFを検討してみた

2018/08/03 Security JAWS 【第10回】勉強会での、安東・徳田の講演資料になります

Recruit Technologies

August 03, 2018
Tweet

More Decks by Recruit Technologies

Other Decks in Technology

Transcript

  1. 自己紹介 氏名 所属 お仕事 徳田 聡介 (とくだ そうすけ) 株式会社リクルートテクノロジーズ インフラソリューション部

    ・セキュアインフラ基盤の運用 ・社内向アプリのエンハンス対応 備考 ・セキュリティに興味をもちREDチームに半年間所属 ・この期間に AWS WAF 検証担当として参画
  2. 自己紹介 安東 美穂 (あんどう みほ) 株式会社リクルートテクノロジーズ セキュリティオペレーションセンター(SOC) 氏名 所属 日経コンピュータ連載記事に寄稿

    (書籍:「現場で使えるセキュリティ事故対応」) 好きなコマンド:nmap ・リクルートのサービスのセキュリティ監視、解析(IDS/WAF) ・WAF監視導入支援 など お仕事 課外活動:ミニ四駆
  3. Recruit-CSIRTについて IRG Incident Response Group SEG SOC Security Operation Center

    サイバー攻撃への対応をリード ・事故発生時の対応支援 ・外部関連機関との連携 ・Recruit-CSIRTの運営、各社展開 サイバー攻撃を早期検知し、被害拡大を防止 ・グループ共通インフラのセキュリティ監視 ・未知マルウェアの監視、解析、一次対応 ・被害発生時のフォレンジック (NWおよびPC) ・内部不正のモニタリング 平時からセキュリティを向上、被害を未然に 防止 ・脆弱性診断、開発者教育などのセキュア開発支 援 ・セキュリティパッチの情報収集および各社展開 ・早期警戒(脅威情報の収集および対策検討) Security Engineering Group
  4. 検証環境の構成 AWS WAF EC2 CloudFront ELB 通常: “200” OK 遮断時:

    “403” Forbidden 投げたリクエストに対するレスポンスのステータスコードから AWS WAF が遮断したかを判定
  5. 攻撃用データ① Sqlmap 1. 脆弱なサーバを用意して Sqlmap (=攻撃) を実行 2. プロキシとして Burp

    Suite を経由させて攻撃ログを取得 3. burpProHistory2Flat.py を使ってログから攻撃リクエストを復元 • ※ 元のスクリプトを少し使いやすく修正 burpProHistory2Flat.py Burp Suite Pro 1. 脆弱なサーバを用意して Burp Suite Pro の Scan (=攻撃) を実行 2. デフォルトでは攻撃ログが残らないので拡張モジュールを導入 • Logger++ 3. Logger++のログからツールで攻撃リクエストを復元 • ※ 簡易なものを自作 loggerPlusPlus2Flat.py
  6. AWS WAFのルール構成 Web ACL Managed Rule(by ベンダー) Condition XSS Get

    match SQL Injection IP match Size constraints Regex match Custom Rule (by AWS) … … …
  7. Managed ルール • AWS Marketplaceでベンダーより提供されているルールセット • 細かい設定が不要ですぐに使える 詳しくは 「AWS Marketplace

    ルールグループ」を参照 https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/waf-managed-rule- groups.html • Managed ルールセットは自動更新のため運用負荷が小さい • ただし脆弱性が公開されてからどのくらいの時間で更新されるか不 明なので、ベンダーに確認が必要。(ベストエフォート??) 料金については 「AWS WAF 料金表」 を参照 https://aws.amazon.com/jp/waf/pricing/
  8. Managed ルール ルール名 ※⼀部省略 ベンダー 検証対象? Web Application CVE Signatures

    F5 Yes Bot Detection Signatures F5 Yes Web Exploits Rules F5 Yes General and Known Exploits Fortinet Fortinet Yes Malicious Bots Fortinet Fortinet Yes SQLi/XSS Fortinet Fortinet Yes Complete OWASP Top 10 Fortinet Fortinet Yes ModSecurity Virtual Patching TrustWave Yes OWASP Top 10 for WordPress Alert Logic No Impervaʼs Managed Rules for WordPress Protection Imperva No Managed Rules for IP Reputation Imperva No Content Management System (CMS) Trend Micro No WebServer (Apache, Nginx) Trend Micro No CMS Virtual Patches TrustWave No • Managed ルールは全部で14種類(※2018年 7月現在) • 今回の検証では汎用的に使えそうな8種類に絞り込んだ
  9. カスタム ルール • Condition は全部で6種類(※2018年 7月現在) • XSS • SQL

    Injection • IP • Geolocation (国) • 正規表現 • サイズ (Bytes) • 今回の検証では汎用に使えそうな以下2種類に絞り込んだ • XSS • SQL Injection
  10. カスタム ルール • Rule は複数の Condition を AND 条件で組合せて作成する •

    1つのRuleに複数のconditionを入れると全てにマッチしないと検知しない ので注意 • 今回の検証では“One Rule One Condition” とした Rule① (XSS & SQLi) Rule① (XSS) Rule② (SQLi) わるい例 よい例
  11. カスタム ルール • WebACL は Ruleを OR 条件で組合せて作成する (最大10個) •

    ※ ただしManaged ルールは1つしか組み込む事はできない • 今回は検証では“One WebACL One Rule” とした ※ 1つのWebACLに2つ以上のManagedルールを追加して保存しようとすると失敗する
  12. Condition 設定手順② • https://console.aws.amazon.com/waf/home#/xssmatchsets/new Part of the request to filter

    on: ・検知対象とするHTTPリクエストの部位を指定 Transformation: ・HTTPリクエストの変換方法 参考: https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/web-acl-xss-conditions.html
  13. 検証アウトプット • CSVファイルに Response Status (200 or 403) を一覧出力 •

    攻撃リクエストに対して 403 応答していると Good! • 正常リクエストに対して 403 応答していると Bad! (=誤検知) リ ク エ ス ト 番 号 リクエスト詳細 と ルール名
  14. 検証結果 • CSVファイルに Response Status (200 or 403) を一覧出力 •

    攻撃リクエストに対して 403 応答していると Good! • 正常リクエストに対して 403 応答していると Bad! (=誤検知) リ ク エ ス ト 番 号 リクエスト詳細 と ルール名  攻撃はそれなりにブロック  誤検知も少ない =なかなかの成績
  15. とある遮断された正常系リクエスト POST http://localhost:8080/ HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5;

    Linux) KHTML/3.5.8 (like Gecko) Accept: */* Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Encoding: x-gzip, x-deflate, gzip, deflateAccept-Language: en Content-Length: 1269 Connection: close {'requests':{'g0':{'resource':'mail','operation':'create','params':{'id':100},'body':{'subject':'[Substr ああああああああああ ああ] ああああああああああああああああああああああああ ああああああああああああああホケ(ああああああああああああああホケ 8)','body':'ああああああああああああああああああああああああああああああ¥n¥nあああああああああああああああああああああ あああああああああああああああ¥nああああああああああああああホケ8ああああああああホケ ああああああああああああああホケ¥nあ あああああああああああああああああああああああああああああああああああああああああああああああああああああああホケ¥n¥n ああああああああああああああホケ8¥n¥n¥nあああああああああああああああああああああああああああああああああああああああ あああああああああああああああああああああああああああああああああああああああ¥n¥nあああああああああああああああああ あああああああああああああああああああああああああああホケ'}}},'context':{}} ※実際のログのため一部文字を変更しています
  16. 遮断された正常系リクエストの1つ POST http://localhost:8080/ HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5;

    Linux) KHTML/3.5.8 (like Gecko) Accept: */* Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Encoding: x-gzip, x-deflate, gzip, deflateAccept-Language: en Content-Length: 1269 Connection: close {'requests':{'g0':{'resource':'mail','operation':'create','params':{'id':100},'body':{'subject':'[Substr ああああああああああ ああ] ああああああああああああああああああああああああ ああああああああああああああホケ(ああああああああああああああホケ 8)','body':'ああああああああああああああああああああああああああああああ¥n¥nあああああああああああああああああああああ あああああああああああああああ¥nああああああああああああああホケ8ああああああああホケ ああああああああああああああホケ¥nあ あああああああああああああああああああああああああああああああああああああああああああああああああああああああホケ¥n¥n ああああああああああああああホケ8¥n¥n¥nあああああああああああああああああああああああああああああああああああああああ あああああああああああああああああああああああああああああああああああああああ¥n¥nあああああああああああああああああ あああああああああああああああああああああああああああホケ'}}},'context':{}} “あああ” という文字が原因... ?? ※実際のログのため一部文字を変更しています
  17. 遮断された正常系リクエストの1つ POST http://localhost:8080/ HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5;

    Linux) KHTML/3.5.8 (like Gecko) Accept: */* Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Encoding: x-gzip, x-deflate, gzip, deflateAccept-Language: en Content-Length: 1269 Connection: close {'requests':{'g0':{'resource':'mail','operation':'create','params':{'id':100},'body':{'subject':'[Substr ああああああああああ ああ] ああああああああああああああああああああああああ ああああああああああああああホケ(ああああああああああああああホケ 8)','body':'ああああああああああああああああああああああああああああああ¥n¥nあああああああああああああああああああああ あああああああああああああああ¥nああああああああああああああホケ8ああああああああホケ ああああああああああああああホケ¥nあ あああああああああああああああああああああああああああああああああああああああああああああああああああああああホケ¥n¥n ああああああああああああああホケ8¥n¥n¥nあああああああああああああああああああああああああああああああああああああああ あああああああああああああああああああああああああああああああああああああああ¥n¥nあああああああああああああああああ あああああああああああああああああああああああああああホケ'}}},'context':{}} ではなかった ※実際のログのため一部文字を変更しています
  18. “あああ” 除外しても遮断される POST http://localhost:8080/ HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (compatible;

    Konqueror/3.5; Linux) KHTML/3.5.8 (like Gecko) Accept: */* Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Encoding: x-gzip, x-deflate, gzip, deflateAccept-Language: en Content-Length: 1269 Connection: close {'requests':{'g0':{'resource':'mail','operation':'create','params':{'id':100},'body':{'subject':'[Substr] (8)','body':'8 red8'}}},'context':{}} ※実際のログのため一部文字を変更しています
  19. POST http://localhost:8080/ HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux)

    KHTML/3.5.8 (like Gecko) Accept: */* Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Encoding: x-gzip, x-deflate, gzip, deflateAccept-Language: en Content-Length: 1269 Connection: close [Substr] (8) もっと絞っても遮断される ※実際のログのため一部文字を変更しています
  20. POST http://localhost:8080/ HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux)

    KHTML/3.5.8 (like Gecko) Accept: */* Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Encoding: x-gzip, x-deflate, gzip, deflateAccept-Language: en Content-Length: 1269 Connection: close Substr() さらに絞っても遮断される ※実際のログのため一部文字を変更しています
  21. POST http://localhost:8080/ HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux)

    KHTML/3.5.8 (like Gecko) Accept: */* Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Encoding: x-gzip, x-deflate, gzip, deflateAccept-Language: en Content-Length: 1269 Connection: close Substr) やっと遮断されなくなった ※実際のログのため一部文字を変更しています
  22. 誤遮断のリスク • あるルールでは特定の SQL関数を遮断する可能性アリ • concat() • substr() • cast()

    • あるルールでは特定の SQL構文を遮断する可能性アリ • select ~ from • insert into • drop table
  23. 誤遮断のリスク • あるルールでは特定の SQL関数を遮断する可能性アリ • concat() • substr() • cast()

    • あるルールでは特定の SQL構文を遮断する可能性アリ • select ~ from • insert into • drop table  AWS WAFに適さないサイトもある。事前に正常系の通信で要検証。 • ユーザーの自由入力でソースコードや関数が入るケース • “Select Shop from LA ”がもしリクエストに含まれたらNG  誤遮断の発生時の調査の仕組みや、ユーザー対応などの検討 • ソーリーページ、サポートとの連携など
  24. { "Request": { "ClientIP": ”XX.XX.XX.XX", "Country": "JP", "URI": "/test/WAF/editar.jsp", "Method":

    "POST", "HTTPVersion": "HTTP/1.1", "Headers": [ { "Name": "Host", "Value": ". *************cloudfront.net" }, { "Name": "Content-Length", "Value": "295" }, { "Name": "POST http", "Value": "//*************.cloudfront.net/test/WAF/editar.jsp HTTP/1.1" }, 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 一部抜粋 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 { "Name": "User-Agent", "Value": "Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.8 (like Gecko)" }, }, "Weight": 3, "Timestamp": "2018-05-15T06:09:42.321000+00:00", "Action": "COUNT" }, AWS WAF APIの“GetSampledRequests” • 送信元IPアドレス • リクエストメソッド • リクエストヘッダー(URI, UA, Content-Length) • 検知時刻 • アクション ※一部伏字&修正しています
  25. ログの課題 • 検知ログをみるならばSampled Log • 5,000件のうちの500件が出力可能 →全ての検知ログが出ないため、検知をしたか確認できないことがある • 保存期間は3時間 →3時間以上過去の調査ができない

    • 検知箇所(文字列)、リクエストbody、レスポンスは含まれない →POSTの場合のリクエスト特定や攻撃の影響調査が難しい “Gets detailed information about a specified number of requests--a sample--that AWS WAF randomly selects from among the first 5,000 requests that your AWS resource received during a time range that you choose. You can specify a sample size of up to 500 requests, and you can specify any time range in the previous three hours.” 出典:https://docs.aws.amazon.com/ja_jp/waf/latest/APIReference/API_GetSampledRequests.html
  26. ログの課題 • 検知ログをみるならばSampled Log • 5,000件のうちの500件が出力可能 →全ての検知ログが出ないため、検知をしたか確認できないことがある • 保存期間は3時間 →3時間以上過去の調査ができない

    • 検知箇所(文字列)、リクエストbody、レスポンスは含まれない →POSTの場合のリクエスト特定や攻撃の影響調査が難しい “Gets detailed information about a specified number of requests--a sample--that AWS WAF randomly selects from among the first 5,000 requests that your AWS resource received during a time range that you choose. You can specify a sample size of up to 500 requests, and you can specify any time range in the previous three hours.” 出典:https://docs.aws.amazon.com/ja_jp/waf/latest/APIReference/API_GetSampledRequests.html  検知リクエストの特定、詳細分析はWAFのログだけでは難しい  もっとログが欲しい場合は工夫が必要
  27. ログの工夫例 ログの保管期間の延長 • AWS WAFのイベントをCloudWatchでモニタリング • CloudWatchでLambdaを実行しAWS WAFのログをS3に保管 参考:「AWS WAFのログが3時間しか見れないのでなんとかしてみる

    」 https://speakerdeck.com/tmorinaga/aws-waffalseroguga3shi-jian-sikajian- renaifalsedenantokasitemiru 詳細ログの取得 • Lambda@edge(Cloudfront+lambda)を使用しフロントで リクエストとレスポンスのログ取得 • AWS WAFはALBに関連づけて動作
  28. チューニング 動作検証 ポリシーチューニング 機器構築・回線敷設 初期設定 サイト設定・ポリシー設定 監視開始後の 運用 ポリシー更新 SWバージョンアップ

    ライセンス更新 ..etc 検証 監視開始 商用WAF(オンプレ) 基本的な導入時の流れ(商用WAF/オンプレ/非インライン)の例との比較 セキュリティ運用はどうなる?(導入時)
  29. チューニング 動作検証 ポリシーチューニング 機器構築・回線敷設 初期設定 サイト設定・ポリシー設定 監視開始後の 運用 ポリシー更新 SWバージョンアップ

    ALB/Cloudfrontに関連づけ ライセンス更新 ..etc ACL作成・ルール設定 検証 監視開始 商用WAF(オンプレ) AWS WAF 基本的な導入時の流れ(商用WAF/オンプレ/非インライン)の例との比較 カスタムルール追加 セキュリティ運用はどうなる?(導入時)
  30. チューニング 動作検証 ポリシーチューニング 機器構築・回線敷設 初期設定 サイト設定・ポリシー設定 監視開始後の 運用 ポリシー更新 SWバージョンアップ

    ALB/Cloudfrontに関連づけ ライセンス更新 ..etc ACL作成・ルール設定 検証 監視開始 商用WAF(オンプレ) AWS WAF WAF自体のメンテナンスは 不要 countモードで 検知状況を確認 基本的な導入時の流れ(商用WAF/オンプレ/非インライン)の例との比較 カスタムルール追加 ポリシーの 中身はお任せで、 必要なものは カスタムで追加 セキュリティ運用はどうなる?(導入時)
  31. 検知 二次調査 対象サイトのアセット情報を確認 NWフォレンジック調査 (攻撃の成否・影響の解析) WAFで検知 一次調査 検知ログ調査 (攻撃内容の解析) 事後対応

    FW遮断 脆弱性の修正 商用WAF(オンプレ) ..etc 攻撃成功 攻撃失敗/過検知 ポリシー チューニング 基本的なアラート対応の流れ(商用WAF/オンプレ/非インライン)の例との比較 セキュリティ運用はどうなる?(アラート対応)
  32. 検知 二次調査 対象サイトのアセット情報を確認 NWフォレンジック調査 (攻撃の成否・影響の解析) WAFで検知 一次調査 検知ログ調査 (攻撃内容の解析、検知リクエストの特定) 事後対応

    FW遮断 脆弱性の修正 商用WAF(オンプレ) AWS WAF WAFで検知&遮断 ..etc 攻撃成功 攻撃失敗/過検知 ポリシー チューニング ポリシーチューニング 基本的なアラート対応の流れ(商用WAF/オンプレ/非インライン)の例との比較 セキュリティ運用はどうなる?(アラート対応)
  33. 検知 二次調査 対象サイトのアセット情報を確認 NWフォレンジック調査 (攻撃の成否・影響の解析) WAFで検知 一次調査 検知ログ調査 (攻撃内容の解析、検知リクエストの特定) 事後対応

    FW遮断 脆弱性の修正 商用WAF(オンプレ) AWS WAF WAFで検知&遮断 ..etc 攻撃成功 攻撃失敗/過検知 ポリシー チューニング ポリシーチューニング 基本は 特になし 細かい チューニングは できない 検知ログがあれ ば見る 基本的なアラート対応の流れ(商用WAF/オンプレ/非インライン)の例との比較 セキュリティ運用はどうなる?(アラート対応)
  34. AWS WAF向きなユースケース • PCI対応 • AWS WAF はPCI DSS 3.2に準拠

    • “ガートナーのレポートによると25-30パーセントはPCI対応のために AWS WAFを導入” 出典:https://www.slideshare.net/AmazonWebServicesJapan/20171122-aws- blackbeltawswafowasptop10 • 特定のリクエストの遮断 • 判明している脆弱性の攻撃を防ぎたい • 特定のUser-Agentでくるbotを遮断したい (カスタムルールの正規表現を使って対応) • 動的なFWとして活用 • ブラックリストIP/ホワイトリストIP • MPの製品との組み合わせ • SIEM連携 ..etc