
Preuve de concept d'exploitation pour une vulnérabilité XSS réfléchie dans le plugin WordPress Groundhogg, démontrant une injection de script non authentifiée via des paramètres d'URL spécialement conçus.
Plugin WordPress
Nom du composant WordPress CRM, Email & Marketing Automation for WordPress | Award Winner — Groundhogg
Version vulnérable <= 3.7.3.2
Slug du composant groundhogg
Lien du composant https://wordpress.org/plugins/groundhogg/
Classe de vulnérabilité A3 : Injection
Type de vulnérabilité Cross Site Scripting (XSS)
Non authentifié
Les versions 3.7.3.3 et inférieures du plugin Groundhogg contiennent une vulnérabilité de Cross Site Scripting réfléchi (Reflected XSS) due à une validation insuffisante des entrées et à un traitement d'échappement insuffisant des paramètres d'URL. Cette vulnérabilité se produit lors de l'utilisation de la fonctionnalité de filtrage de recherche dans les menus « Contacts », « Funnels » et « Logs » du tableau de bord du plugin.
Grâce à cette vulnérabilité, un utilisateur non authentifié peut créer une URL contenant des scripts malveillants, et lorsque d'autres utilisateurs accèdent à cette URL, le script s'exécute dans leur navigateur, ce qui peut entraîner une fuite d'informations de cookies. Cela représente un risque de sécurité sérieux car cela peut être exploité notamment pour détourner les sessions des utilisateurs disposant de privilèges d'administrateur.
Préparez un site WordPress avec le plugin « Groundhogg » <=3.7.3.2 activé.
Comme ce plugin utilise l'API REST, le permalien doit être défini sur
Nom de publication.
Ensuite, l'accès aux liens de chaque menu ci-dessous déclenchera une vulnérabilité XSS réfléchie.
Menu Contacts (/wp-admin/admin.php?page=gh_contacts)
http://localhost:8080/wp-admin/admin.php?page=gh_contacts&filters=W1t7ImlkIjoiIiwidHlwZSI6ImZpcnN0X25hbWUiLCJjb21wYXJlIjoiZXF1YWxzIiwidmFsdWUiOiI8aW1nIHNyYz1cInhcIiBvbmVycm9yPVwiYWxlcnQoZG9jdW1lbnQuY29va2llKVwiPiJ9XV0

Menu Funnels (/wp-admin/admin.php?page=gh_funnels)
Pour reproduire la vulnérabilité XSS dans ce menu, au moins 1 Funnel doit exister.
http://localhost:8080/wp-admin/admin.php?page=gh_funnels&status=inactive&include_filters=W1t7ImlkIjoiMTBjY2FmZmUtZjE0YS00MTg5LWE0MzctYjA2MTFhMTQ2ZDk1IiwidHlwZSI6InRpdGxlIiwidmFsdWUiOiI8aW1nIHNyYz1cInhcIiBvbmVycm9yPVwiYWxlcnQoZG9jdW1lbnQuY29va2llKVwiPiIsImNvbXBhcmUiOiJlcXVhbHMifV1d

Menu Logs (/admin.php?page=gh_events)
http://localhost:8080/wp-admin/admin.php?page=gh_events&tab=emails&include_filters=W1t7ImlkIjoiIiwidHlwZSI6ImZyb21fYWRkcmVzcyIsInZhbHVlIjoiPGltZyBzcmM9XCJ4XCIgb25lcnJvcj1cImFsZXJ0KGRvY3VtZW50LmNvb2tpZSlcIj4iLCJjb21wYXJlIjoiZXF1YWxzIn1dXQ

Lors de l'exécution de recherches de filtrage dans les menus « Contacts », « Funnels » et « Logs » du tableau de bord du plugin Groundhogg, les paramètres de filtrage sont encodés en Base64 avant d'être transmis comme paramètres d'URL.
Par exemple, lors de la définition d'une recherche de filtrage dans le menu « Contacts » où « Prénom » est défini sur « Test », le paramètre d'URL filters reçoit les données suivantes :
W1t7ImlkIjoiMjM3NzdjMGItYTQ1Ni00M2JlLWExZGMtODkzN2E1MDk0M2I5IiwidHlwZSI6ImZpcnN0X25hbWUiLCJjb21wYXJlIjoiZXF1YWxzIiwidmFsdWUiOiJUZXN0In1dXQ

Lorsque la valeur saisie dans le paramètre d'URL filters est décodée en Base64, vous pouvez voir les données suivantes.
[[{"id":"23777c0b-a456-43be-a1dc-8937a50943b9","type":"first_name","compare":"equals","value":"Test"}]]

Lorsqu'une recherche de filtrage est demandée, la fonction scripts de la classe Contacts_Page dans le fichier /wp-content/plugins/groundhogg/admin/contacts/contacts-page.php est exécutée.
À ce stade, le paramètre d'URL filters encodé en Base64 est décodé et transmis à la variable ContactSearch dans la zone JavaScript de la réponse HTTP.

Par conséquent, vous pouvez vérifier que dans les données de réponse HTTP, les données encodées en Base64 transmises au paramètre d'URL filters sont décodées avant d'être livrées.

Ensuite, les données décodées sont directement insérées dans les éléments DOM qui affichent les résultats de la recherche de filtrage via la logique JavaScript.

Grâce à cela, le terme de recherche de filtrage (<img src="x" onerror="alert(document.cookie)">) saisi dans le PoC est transmis comme variable dans le code JavaScript sans traitement d'échappement et est inséré et exécuté dans les éléments DOM par la logique client.


En conséquence, en raison d'un traitement d'échappement insuffisant des données de recherche de filtrage, des valeurs contenant des scripts malveillants peuvent être exécutées directement, et cette vulnérabilité se produit de la même manière dans tous les menus « Contacts », « Funnels » et « Logs ».