Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


2024年3月29日に発覚した「XZ Utils」というライブラリへ仕掛けられていたバックドアについて、ロシアのセキュリティ企業であるカスペルスキーが分析記事を投稿しました。
Kaspersky analysis of the backdoor in XZ | Securelist
https://securelist.com/xz-backdoor-story-part-1/112354/

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


XZは多くのLinuxディストリビューションで使用されている圧縮ツールで、今回は特にOpenSSHのサーバープロセスである「sshd」をターゲットに攻撃が行われました。「Ubuntu」「Debian」「RedHat/Fedora」などのディストリビューションではsshdの起動時に「systemd」経由でXZが呼び出され、sshdにリモートでコードが実行できるバックドアが仕掛けられます。
今回のバックドアが設置されて発覚するまでのタイムラインは以下の記事で確認できます。
XZ Utilsにバックドア攻撃が行われるまでのタイムラインまとめ - GIGAZINE

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


XZは圧縮ツールのため、XZのリポジトリには圧縮・解凍のコードをテストして動作を確認するためのテストファイルが含まれています。攻撃者はこれに目を付け、バックドアを埋め込むためのコードを隠した2つのテストファイルを追加しました。
その後、テスト用のファイルからコードを取り出すためのコードをビルド用スクリプトに挿入。下図の上段のように一見無害なコードに見えるよう難読化されていましたが、読みやすく書き直すと下段のようにテストファイルを読み込み、trコマンドで壊れたデータを修正して「xz -d」で解凍するという内容になっていました。

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


解凍されたスクリプトは下図のように、Linuxマシン上で実行されていることや、意図したビルドプロセス上で実行されていることを確認し、別のテストファイルを解凍します。このテストファイルの解凍後のデータは一見ジャンクデータに見えるものの、実は1024バイトのジャンクデータと2048バイトの悪意あるデータが順番に並んでいるものでした。このスクリプトは悪意あるデータを抽出し、trコマンドで難読化を解除してからシェルで実行します。

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


次のシェルスクリプトでも再び実行環境の確認が行われています。必要なファイルやツールが利用できるかなど多くのチェックが行われているとのこと。

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


その後テストファイルからバックドア実行用のバイナリファイルを抽出しています。

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


上図の一番下の行に書かれているコードを読みやすく展開すると下図の通り。最初にXZを使用して悪意あるバイナリファイルを隠してあるテストファイルを複合化し、次にデータの先頭から一定のバイトを削除した後に実行ファイルとしてディスクに保存しています。また、XZのファイルを編集して「__get_cpuid」関数の呼び出しを「_get_cpuid」関数の呼び出しに置き換え、実行ファイルがライブラリにリンクできるようにしているとのこと。

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


ビルドプロセス全体の感染チェーンは下図の通り。

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


XZではデータのCRCを計算するために「lzma_crc32」「lzma_crc64」という2つの特別な関数を使用しています。どちらの関数もglibcのIFUNC(間接関数)型のELFシンボルテーブルに格納され、ダイナミックリンカが共有ライブラリをロードする際に開発者が使用する関数を動的に選択できるようになっています。
XZはプロセッサの機能に応じて関数の最適なバージョンを選択するためにIFUNCを使用しており、プロセッサが特定の機能を持つか確認するために「__get_cpuid」を呼び出します。前述のシェルスクリプトによってこの__get_cpuidの呼び出しがアンダースコアを一つ消した「_get_cpuid」の呼び出しに書き換えられており、実際にはバックドアが仕込まれたオブジェクトファイルが呼び出されます。
「lzma_crc32」「lzma_crc64」の両方が同じ「_get_cpuid」関数を使用するため、バックドアのコードは2回呼び出されます。このうち2回目の呼び出しでバックドアのエントリーポイントにリダイレクトが行われ、実際の悪意ある活動が開始されるとのこと。

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


バックドアは当該マシンへの全ての接続を監視できる機能をフックしようとすると同時に、可能な限りステルス性を保とうとしています。次のコードで示されているように、「sshd」内で実行されていない場合はマルウェアの動作が停止するほか、全てのプロセス環境変数を確認して内部テーブル内の文字列と一致するプロセスが見つかった場合にも動作を停止するようになっています。

Linux環境で使用されている圧縮ツール「XZ Utils」のバックドアはどのように埋め込まれるのかをセキュリティ企業のカスペルスキーが解説 - 画像


今回のバックドアはバイナリ自体のコードだけでなくXZリポジトリへの何段にもおよぶ埋め込みも含めて非常に複雑で、検出を回避するために高度な方法を使用しています。カスペルスキーは「バックドアの内部についてはまだ調査するべき事がたくさんある」として今回の解説は「パート1」だと述べています。
なお、カスペルスキー製品はこの攻撃に関連する悪意のあるオブジェクトを「HEUR:Trojan.Script.XZ」および「Trojan.Shell.XZ」として検出するほか、Kaspersky Endpoint Security for Linuxにおいてはsshdプロセスメモリ内の悪意あるコードを「MEM:Trojan.Linux.XZ」として検出可能とのことです。

ジャンルで探す