Prototype pollution côté client via les APIs du navigateur

Prototype pollution en el lado cliente usando APIs del navegador

Contexte du lab

Ce laboratoire est vulnérable à une DOM XSS déclenchée via une pollution de prototype côté client. Les développeurs ont repéré un gadget potentiel et ont tenté de le corriger, mais il est possible de contourner le patch.

Objectif :

  • Trouver une source permettant d’ajouter des propriétés arbitraires à Object.prototype

  • Identifier une propriété gadget menant à l’exécution de JavaScript

  • Combiner les deux pour déclencher alert()

1) Source : pollution de Object.prototype via l’URL

Injection depuis la query string

On teste la pollution via l’URL :

Vérification dans la console

Dans la console du navigateur :

Résultat : bar Cela confirme qu’on arrive à injecter une propriété dans le prototype global.

2) Comprendre l’impact : modifier le comportement des objets

Exemple de modification du prototype via un objet :

Puis :

Tous les objets héritent maintenant de country, ce qui montre bien l’effet global de la pollution.

3) Gadget : chargement dynamique d’un script via une propriété héritée

Le fichier intéressant est :

/resources/js/searchLoggerConfigurable.js

Comportement clé du script (résumé)

  • Il construit un objet config contenant :

    • params (issus de l’URL)

    • transport_url initialisé à false

  • Il verrouille config.transport_url avec Object.defineProperty(... configurable:false, writable:false)

  • Puis :

    • si config.transport_url est truthy → il crée un <script> et fait script.src = config.transport_url

Pourquoi ça marche malgré le patch

Comme transport_url n’est pas vraiment défini avec une valeur utilisable, le code peut aller chercher une valeur héritée depuis le prototype (pollué).

Donc si on injecte la bonne propriété dans Object.prototype, elle est utilisée comme source du script.

4) Exploitation : forcer script.src via le prototype

Étape 1 : prouver le gadget

En injectant :

On observe que le navigateur crée :

Le src est contrôlable.

Étape 2 : exécuter du JS via une URL data:

Payload final :

Résultat observé :

Le navigateur interprète data:,alert(1) et exécute alert(1) : DOM XSS réussie.

Mis à jour