
Aviso de seguridad detallado para CVE-2026-36669: subida de archivos arbitraria sin autenticación en Feng Office, permitiendo stored XSS y secuestro de sesión. Incluye análisis técnico, PoC y pasos de remediación.
Existe una vulnerabilidad de carga arbitraria de archivos sin autenticación en ck_upload_handler.php en Feng Office Community Edition (versión 3.11.13.11). Esta falla permite que atacantes remotos no autenticados carguen archivos arbitrarios (incluyendo scripts maliciosos .html o .php) en un directorio accesible desde la web. Cuando se combina con la falta de protecciones de cookies administrativas (HttpOnly), esta vulnerabilidad puede conducir a Cross-Site Scripting (XSS) Almacenado y secuestro de sesión administrativa.
| Métrica | Detalles |
|---|
| Identificador CVE | CVE-2026-36669 |
| Tipo de Vulnerabilidad | Carga sin restricciones de archivos con tipo peligroso (CWE-434) |
| Debilidad Asociada | Falta de autenticación para función crítica (CWE-306) |
| Producto Afectado | Feng Office Community Edition |
| Versiones Afectadas | Versión 3.11.13.11 (y potencialmente versiones anteriores) |
| Estado de Explotación | Prueba de Concepto Verificada |
| Estado de Mitigación | Sin parche (Proveedor notificado, no se proporcionó parche dentro del período de divulgación estándar) |
El punto final ck_upload_handler.php actúa como un script independiente. No carga ni hereda el middleware de autenticación ni las listas de control de acceso (ACL) de la aplicación principal. En consecuencia, cualquier solicitud externa enviada directamente a este script se trata como autenticada.
En el código fuente de ck_upload_handler.php, la lógica de validación de archivos del lado del servidor (líneas 21–25) diseñada para restringir las cargas a formatos de imagen específicos (.jpg, .png, .gif) ha sido explícitamente comentada:
// $pattern = "/\.(jpg|png|gif)$/i";
// if (!preg_match($pattern,$_FILES['upload']['name'])) {
// ...
// }
Debido a que esta restricción de expresión regular está inactiva, el mecanismo de carga de archivos acepta cualquier extensión proporcionada por el usuario.
El script utiliza la función copy() de PHP para escribir los archivos cargados directamente en el directorio /tmp/, el cual está configurado para ser accesible desde la web.
El archivo de configuración global application/config/config.php no aplica la bandera HttpOnly en las cookies de sesión. Cuando un atacante carga un archivo .html que contiene bloques de scripts del lado del cliente, cualquier administrador que visualice el archivo ejecutará el script en el contexto de su sesión activa. Esto permite a los atacantes extraer silenciosamente tokens de sesión administrativa activos.
Aviso: Esta Prueba de Concepto se proporciona únicamente con fines educativos y de auditoría defensiva.
Para verificar la vulnerabilidad, envíe una solicitud POST multiparte que contenga un archivo de verificación inofensivo (por ejemplo, test.html) al punto final, añadiendo el parámetro CKEditorFuncNum requerido:
curl -i -X POST \
-F "[email protected]" \
"http://<dominio-objetivo>/ck_upload_handler.php?CKEditorFuncNum=1"
Donde test.html contiene un marcado HTML básico de prueba de concepto:
<!DOCTYPE html>
<html>
<body>
<script>
alert("Vulnerabilidad Verificada: " + document.cookie);
</script>
</body>
</html>
Si es vulnerable, el servidor responderá con un estado 200 OK y mostrará un bloque JavaScript indicando la ruta de carga:
<script type="text/javascript">
window.parent.CKEDITOR.tools.callFunction("1", "/tmp/test.html", "");
</script>
Si ejecuta una versión afectada de Feng Office, aplique los siguientes parches manuales para asegurar el punto final de carga de archivos:
Asegúrese de que ck_upload_handler.php verifique sesiones administrativas activas antes de procesar cualquier lógica de carga de archivos.
Descomente y aplique estrictamente las comprobaciones de extensión. Rechace cualquier carga que no coincida explícitamente con los tipos MIME de imagen no ejecutables esperados:
$pattern = "/\.(jpg|jpeg|png|gif)$/i";
if (!preg_match($pattern, $_FILES['upload']['name'])) {
header("HTTP/1.1 403 Forbidden");
exit("Tipo de archivo no válido.");
}
Modifique su configuración de PHP o la configuración de arranque de la aplicación para asegurar que las cookies de sesión no sean accesibles a través de APIs de scripting del lado del cliente:
session.cookie_httponly = On
Soufiane LAGZIRI