
Dépôt de PoC pour CVE-2025-68147 : Cross-Site Scripting stocké (XSS) dans OpenSourcePOS. La vulnérabilité permet une élévation de privilèges via l'injection de JavaScript malveillant dans le module Store Config. Inclut les détails de la charge utile et la vérification du correctif (v3.4.0). Chercheur en sécurité : Aditya Singh (Nixon-H).
| Métadonnées | Détails |
|---|---|
| Identifiant CVE | CVE-2025-68147 |
| Sévérité | Élevée CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:N |
| Type de vulnérabilité | Cross-Site Scripting stocké (CWE-79) |
| Versions concernées | OpenSourcePOS v3.4.0, v3.4.1 |
| Version corrigée | v3.4.2 |
| Composant vulnérable | Module de configuration du magasin (champ Return Policy) |
| Signaleur | Aditya Singh (Nixon-H) |
Une vulnérabilité de type Cross-Site Scripting (XSS) stocké a été découverte dans le module de configuration du magasin d'OpenSourcePOS. L'application ne parvenait pas à assainir correctement les données saisies par l'utilisateur dans le champ « Return Policy » avant de les stocker dans la table ospos_app_config de la base de données.
Cette faille permettait à un attaquant authentifié disposant de privilèges de configuration (ou à un attaquant exploitant une chaîne CSRF distincte) d'injecter des payloads JavaScript arbitraires. Étant donné que la « Return Policy » est rendue dynamiquement sur chaque reçu de vente, le payload injecté s'exécute automatiquement dans le navigateur de n'importe quel utilisateur—y compris les caissiers à faibles privilèges, les autres administrateurs ou les clients—dès qu'un reçu est généré ou consulté.
La vulnérabilité se situe dans le modèle de vue des reçus : app/Views/sales/receipt_default.php.
L'application récupère la chaîne « Return Policy » depuis le tableau de configuration global ($this->config['return_policy']) et la prépare pour l'affichage.
nl2br() pour convertir les sauts de ligne en balises HTML (<br>).nl2br() n'assainit pas les caractères spéciaux HTML. Elle laisse les balises comme <script>, `` et les attributs onload totalement intacts.Code vulnérable (avant correctif) :
<div id="sale_return_policy">
<?php echo nl2br($this->config['return_policy']); ?>
</div>
Lorsqu'un administrateur enregistre la configuration, le payload est stocké brut dans la base de données.
ospos_app_configreturn_policyPolicy Text... <script>alert('XSS')</script>Comme il n'y a ni assainissement des entrées côté contrôleur (Config.php), ni échappement des sorties côté vue (receipt_default.php), l'application est vulnérable au XSS stocké.
L'attaque cible le panneau de configuration du magasin mais affecte le module Ventes/Reçus.
http://[TARGET]/config (requête POST pour enregistrer la configuration)http://[TARGET]/sales/receipt/[SALE_ID]Étape 1 : L'injection Nous nous sommes connectés en tant qu'administrateur et avons navigué vers Configuration du magasin -> Général. Dans la zone de texte « Return Policy », nous avons injecté le payload spécifique suivant :
Standard Return Policy: No Refunds.
<script>alert('XSS_BY_NIXON_SUCCESSFUL')</script>
Étape 2 : Persistance
En cliquant sur « Submit », l'application a envoyé une requête POST à /config/save. Le payload a été correctement enregistré dans la base de données.
Étape 3 : Le déclenchement Pour vérifier l'impact sur d'autres utilisateurs :
http://localhost/sales/receipt/1). Le navigateur analyse le div return_policy, rencontre la balise <script> et exécute immédiatement le JavaScript.Résultat observé :
Une boîte d'alerte du navigateur est apparue avec le message : XSS_BY_NIXON_SUCCESSFUL.
Capture d'écran 1 : Le déclenchement de l'alerte
Capture d'écran 2 : Payload dans la configuration
🎥 Démonstration vidéo : Cliquez pour télécharger / regarder la vidéo du PoC
Il s'agit d'une vulnérabilité à portée modifiée (S:C) car l'attaque est stockée sur le serveur mais s'exécute dans le contexte du navigateur de la victime.
/sales/receipt/105). Le script s'exécute silencieusement et envoie document.cookie (contenant l'identifiant ospos_session) au serveur de l'attaquant./employees/save.hacker / password123) est créé instantanément en arrière-plan. La victime ne voit que le reçu, tandis que l'attaquant obtient une porte dérobée permanente.La vulnérabilité a été corrigée dans OpenSourcePOS v3.4.2.
Le mainteneur a appliqué un correctif qui implémente un encodage de sortie contextuel (Context-Aware Output Encoding). La valeur de configuration est désormais encapsulée dans la fonction globale d'assistance esc() de CodeIgniter avant d'être transmise à nl2br().
Le correctif (commit 22297a) :
<div id="sale_return_policy">
<?php echo nl2br(esc($this->config['return_policy'])); ?>
</div>
Vérification : Après la mise à niveau vers v3.4.2, le même payload est rendu sous forme de texte inoffensif :
Standard Return Policy: No Refunds. <script>alert('XSS_BY_NIXON_SUCCESSFUL')</script>
22297a) et vérifié par le chercheur.