Contexto del incidente
El 3 de junio de 2026 el equipo de JCE (Joomla Content Editor) publicó la versión 2.9.99.5 cerrando una vulnerabilidad crítica que llevaba años latente en el flujo de importación de perfiles. Tres días después CISA la agregó a su catálogo KEV como CVE-2026-48907 con un puntaje CVSS 4.0 de 10.0 (máximo posible), fecha de remediación 19 de junio y acción obligatoria bajo BOD 26-04. La descripción oficial en NVD la cataloga como CWE-284 (Improper Access Control) y el vector de ataque es completamente remoto, sin autenticación ni interacción del usuario: AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H.
Lo que vuelve a CVE-2026-48907 particularmente grave no es sólo el puntaje. El propio aviso de JCE advierte que "el código de exploit funciona, los ataques están automatizados y un sitio sin registro público no está a salvo". El flujo es directo: un atacante no autenticado visita la URL index.php?option=com_jce&task=profiles.import en cualquier Joomla con JCE vulnerable, crea un perfil con nombre autogenerado (por ejemplo z9b1a), configura sus permisos para permitir la subida de archivos PHP, y lo usa para subir un web shell. El motor de Joomla ejecuta ese PHP con los privilegios del usuario del web server y el atacante obtiene RCE con esa identidad. Como JCE es uno de los editores WYSIWYG más usados del ecosistema Joomla —con más de 600.000 sitios activos según las métricas públicas del Joomla Extensions Directory— la superficie comprometida es enorme, y los ataques automatizados llevan semanas escaneando la internet en busca de instalaciones sin parchar.
Un editor de contenidos no debería ser un punto de entrada al servidor. Cuando lo es, la línea entre "publicar un artículo" y "tomar el control del host" deja de existir.
El detalle técnico que la mayoría de los avisos pasan por alto es que el bug no es de subida de archivos sin permiso, sino de creación de perfiles sin permiso. JCE mantiene una lista de "editor profiles" que controlan qué extensiones de archivo puede subir cada editor; el endpoint de importación aceptaba requests anónimos y creaba un perfil nuevo en la base de datos sin verificar la sesión. Una vez que el perfil existe, la lógica normal de JCE lo respeta y permite subir lo que el propio perfil diga. Es la cadena "crear rol + abusar rol" la que entrega el RCE, no un bypass aislado del filtro MIME. Esa distinción importa para defenders: la mitigación no es sólo restringir la subida, sino eliminar los perfiles fantasma que el atacante ya pudo haber plantado antes de que parchearas.
¿Cómo proteger tu infraestructura?
1. Actualizá JCE a 2.9.99.6 (o instalá el parche gratuito) ya
La versión 2.9.99.5 cerró la importación no autenticada, y la 2.9.99.6 publicada el 8 de junio agrega endurecimiento adicional (rate limiting en el endpoint profiles.import, firma de requests POST y restricción de campos sensibles en perfiles recién creados). Si tu Joomla corre con PHP 7.4 o superior y Joomla 3.10 o superior, la actualización directa a 2.9.99.6 es la ruta recomendada. Para sitios en stacks más viejos (JCE 2.7.x, 2.8.x o 2.9.x sin posibilidad de upgrade completo) el vendor publicó un parche binario gratuito que se aplica sobre la instalación existente sin tocar la base de datos. La rama 2.6.x no parece afectada en configuración por defecto (la ruta de import está bloqueada), aunque el vendor aclara que esto no fue verificado de forma independiente y la rama está fuera de soporte, así que migrar sigue siendo la decisión correcta.
2. Asumí compromiso previo y audita los perfiles de JCE
El aviso del vendor es explícito: "actualizar cierra el punto de entrada, pero no limpia un sitio que ya fue comprometido". El primer paso post-parche es entrar a Components → JCE Editor → Editor Profiles y revisar la lista. Un perfil植入 tiene tres firmas visibles: nombre autogenerado sin sentido humano (a3f9b2, profile_2026), suele estar ordenado al tope de la lista, y en su configuración interna —sección Permitted File Extensions del plugin Image Manager o File Browser— aparecen extensiones de script (php, phtml, php5, phar) que un editor legítimo jamás tendría habilitadas. Eliminá esos perfiles antes de empezar a limpiar archivos subidos, porque hasta que el endpoint vulnerable esté cerrado el mismo bot que metió el perfil puede re-crearlo.
3. Buscá shells en images/, media/ y tmp/
Cuando JCE sube un archivo sin un path configurado en el perfil, el destino por defecto es la carpeta images/ del template activo. Las carpetas images/, media/ y tmp/ no deberían contener archivos PHP en un Joomla sano. Revisá cada una con un listado recursivo de extensiones, prestando atención a nombres disfrazados: foo.php.xml, img.php.jpg, cache.phtml. Si tu servidor corre Apache, los .htaccess por defecto de Joomla no bloquean la ejecución de PHP en images/ y media/ —es un hueco conocido desde hace años que sólo se cierra agregando reglas explícitas. Mientras el panel de Imunify360, ConfigServer eXploit Scanner o Maldet no marquen la carpeta como limpia, no des por buena la auditoría.
4. Rotación total de credenciales y revisión de bases de datos
Si encontraste un perfil植入, asumí que el atacante también tuvo tiempo de dumpear la tabla #__users y el configuration.php. Rotá todas las contraseñas de administrador de Joomla, regenerá el configuration.php (nuevos secretos de cookie y password de la DB), cambiá las credenciales del usuario de la base de datos en el servidor MySQL/MariaDB, y rotá cualquier acceso FTP/SSH que use las mismas credenciales que el sitio. También revisá la tabla #__jce_profiles directamente con phpMyAdmin o por CLI —es la única forma de confirmar que no quedó un perfil con estado "oculto" que el backend gráfico no muestra. Y no te olvides de auditar usuarios administradores nuevos: SELECT id, username, email, registerDate, lastvisitDate FROM #__users WHERE registerDate > '2026-06-01'; es la consulta que te dice si alguien más ya tiene las llaves del reino.
Indicadores de compromiso (IoC)
Estos son los indicadores específicos que dejó CVE-2026-48907 en sitios comprometidos. Si los cazás en logs, WAF o EDR, el sitio está bajo ataque activo o ya fue breachado:
- Endpoint de import:
index.php?option=com_jce&task=profiles.importen los access logs. Una request a esa URL sin sesión autenticada válida es por definición actividad maliciosa —el endpoint legítimo sólo se invoca desde el panel de admin. - Método HTTP anómalo:
POST /index.php?option=com_jce&task=profiles.importseguido en menos de 5 segundos por otroPOSTalfilebrowser.uploadoplugin.uploadcon un Content-Typemultipart/form-datay un filename terminado en.phpo.phtml. - User-Agent de exploit: campañas automatizadas identificadas en mayo-junio de 2026 usan
python-requests/2.31.0oMozilla/5.0 (compatible; JCEBot/1.0)—el segundo es un UA falso pero muchos sitios lo ven en sus logs. - Archivos PHP en carpetas de medios: cualquier
*.php,*.phtml,*.pharo*.php.*dentro de/images/,/media/o/tmp/del árbol de Joomla. En sitios sanos esas carpetas sólo tienen imágenes, CSS/JS y archivos de caché sin extensión ejecutable. - Perfiles con nombre aleatorio: filas en
#__jce_profilesconnamede 4-8 caracteres alfanuméricos sin sentido, creadas después del 1 de junio de 2026. La consultaSELECT id, name, created FROM #__jce_profiles WHERE LENGTH(name) < 10 AND created > '2026-06-01';las lista en un segundo. - Tráfico outbound desde el web server: el web shell típico de la cadena CVE-2026-48907 hace
system($_GET['c'])opassthru, y el atacante empieza a enumerar y exfiltrar dentro de los primeros 60 segundos. Conexiones HTTPS salientes desde el usuariowww-dataoapachea IPs que no son tu CDN/WAF es una señal clara.
Si tu organización hospeda Joomla — propio o de clientes — y todavía no parcheaste, la ventana de exposición es nula: la fecha de remediación CISA venció el 19 de junio y los botnets automatizados llevan semanas con listas de objetivos. En este caso la pregunta no es "si me van a pegar" sino "cuándo me pegaron y todavía no me di cuenta".
# Detección rápida en logs de Apache — buscar el endpoint vulnerable
# Pre-filtro: requests POST al import task sin cookie de admin
zgrep -E 'POST .*com_jce.*profiles\.import' /var/log/apache2/*access*.log \
| awk '{print $1, $4, $7, $9}' \
| sort -u
# Archivos PHP sospechosos en carpetas de medios de un Joomla
find /var/www/joomla/images /var/www/joomla/media /var/www/joomla/tmp \
-type f \( -iname '*.php' -o -iname '*.phtml' -o -iname '*.phar' -o -iname '*.php.*' \) \
-printf '%TY-%Tm-%Td %TH:%TM %p %s bytes\n'
# Regla Snort/Suricata para WAF perimetral
alert http any any -> $JOOMLA_SERVERS any (
msg:"JCE Joomla CVE-2026-48907 anonymous profile import attempt";
flow:to_server,established;
http_method; content:"POST";
http_uri; content:"com_jce"; nocase;
http_uri; content:"profiles.import"; nocase;
classtype:web-application-attack;
sid:2026489071; rev:1;
)
# Query MySQL para listar perfiles implantados
SELECT id, name, created, checked_out_time
FROM prefix_jce_profiles
WHERE LENGTH(name) < 10
AND created > '2026-06-01 00:00:00'
ORDER BY created DESC;
🛡️ ¿Tu Joomla sigue con JCE sin parchar o ya encontraste un perfil que no reconocés?
En IPSecureNetwork hacemos triage de incidentes Joomla en menos de 24h: revisión de logs previos, hunting de web shells en el árbol del sitio, rotación completa de credenciales y endurecimiento de la configuración de PHP-FPM y Apache para que una subida a /images/ nunca más termine en ejecución. Si tu sitio es uno de los que estuvo expuesto los últimos 30 días, no esperes a que el botnet te marque de nuevo.
SOLICITAR AUDITORÍA →