
Prueba de concepto local segura para la vulnerabilidad de inyección de objetos PHP en Cotonti CommentsWidget (CAN-2026-2035973 / CVE-2026-71294).
Prueba de concepto local segura para el problema de inyección de objetos PHP identificado en la implementación de CommentsWidget de Cotonti.
plugins/comments/inc/CommentsWidget.phpLa ruta de código vulnerable acepta el parámetro GET ci y pasa datos controlados por el atacante a través de base64_decode() hacia unserialize() de PHP sin restringir qué clases pueden instanciarse.
Conceptualmente, la operación vulnerable es:
$ci = @unserialize(base64_decode($ci));
Cuando se proporciona un objeto serializado, PHP puede instanciar la clase controlada por el atacante e invocar métodos mágicos como . En una aplicación más grande esto puede volverse peligroso cuando hay clases gadget adecuadas disponibles.
__wakeup()La corrección enviada cambia la deserialización a:
$ci = @unserialize(base64_decode($ci), ['allowed_classes' => false]);
y valida que el valor resultante tenga la estructura de array esperada antes de usarlo.
poc.php realiza tres pruebas locales:
unserialize() sin restricciones instancia DangerousGadget y desencadena su método __wakeup().allowed_classes => false impide que se instancie la clase gadget y por lo tanto previene el efecto secundario de __wakeup().El PoC usa /tmp/pwned_by_cotonti_poc.txt solo como un centinela inofensivo que muestra que __wakeup() se ejecutó. No ejecuta un comando del sistema operativo. La cadena id && whoami existe solo como un valor de marcador de posición en la propiedad command del gadget.
serialize() / unserialize()No se requiere una instalación de Cotonti porque el comportamiento de deserialización vulnerable y corregido se reproduce directamente.
Desde el directorio del repositorio:
php poc.php
La salida esperada es similar a:
[!] DangerousGadget::__wakeup() triggered
[TEST 1] VULNERABLE: __wakeup() executed during unrestricted unserialize().
[TEST 2] FIXED: object instantiation was blocked; no sentinel was created.
[TEST 3] FIXED: invalid serialized structure rejected by validation.
Summary:
- Vulnerable path allows a serialized attacker-controlled object to be instantiated and invokes __wakeup().
- Fixed path uses allowed_classes=false, preventing the gadget class from being instantiated.
- Structural validation rejects values that do not match the expected array shape.
- No real command execution is performed by this PoC; the command property is only a placeholder.
El script elimina su archivo centinela antes de salir.
No deserialice datos controlados por el atacante con unserialize() de PHP sin restricciones.
Para esta ruta de código, la mitigación demostrada es deshabilitar la instanciación de clases:
unserialize($data, ['allowed_classes' => false]);
El valor deserializado también debe validarse contra la estructura exacta esperada por la aplicación antes de que se use su contenido.
Este repositorio está destinado a la investigación de seguridad, verificación y pruebas defensivas. Ejecute el PoC solo en entornos que posea o esté explícitamente autorizado a probar. No lo use para atacar sistemas sin permiso.
Harsh Raj Singhania — investigación de vulnerabilidades, prueba de concepto y divulgación.