
Element Web v1.12.29 - Alta - Remota - XSS - El enlace navigation.json de Univention ICS se convierte en un href de menú javascript:
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · element-ics-javascript
Análisis: https://abraxaslabs.tech/research/element-ics-javascript
Element Web v1.12.29 - Element / New Vector
Clase: XSS Alcance: Remoto
El módulo de banner de Univention obtiene el navigation.json de ICS, acepta el link de cada entrada como z.string() sin comprobar el esquema, y Menu.tsx coloca esa cadena en un <a href> con estilo. La configuración estática del menú usa z.url() para link_url. La ruta de ICS no lo hace. La vista previa de URL en el mismo pin ya rechaza javascript: (previewFromBundle, GHSA-9r5h). Esto no es el app.element.io predeterminado. Requiere modules/banner con menu.type univention, además de un ICS en el que confíe el despliegue.
Cualquiera que pueda modificar ese navigation.json inserta javascript: o data:. Un usuario con sesión iniciada que abra el menú del banner y haga clic en el elemento ejecuta script en el origen de Element.
| ID | aún sin CVE |
| CWE | CWE-79 / CWE-20 |
| CVSS | Medio: 6.8 CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:N |
| Producto | Element Web |
| Afectado | Etiqueta v1.12.29 v1.12.29 (2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e). Condicionado: banner de Univention + ICS. |
| Autenticación | Operador del ICS / compromiso del ICS. La víctima es un usuario con sesión iniciada que hace clic en el elemento del menú. |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1 |
Comprometer u operar el ICS en el que confía el despliegue de Element. Colocar una URL javascript: (o data:) en navigation.json. Esperar a que un usuario con sesión iniciada abra el menú del banner y haga clic en el elemento. Eso es la toma de control de la cuenta de Matrix: token de acceso, almacén criptográfico, la sesión. No es RCE del sistema operativo. El escritorio sigue teniendo nodeIntegration desactivado y un sandbox.
| Privilegio | Método / sink | Reconocimiento / integridad / disponibilidad | Probado en laboratorio o inferido |
|---|---|---|---|
Renderizar un <a href="javascript:…"> del menú del banner en el origen de Element | ICS navigation.json entries[].link -> navigationToConfig link_url -> Menu.tsx LinkButton href={link.link_url} | Integridad del DOM del menú | Probado en laboratorio. El enlace de ICS simulado javascript:ELEMENT-ICS-JAVASCRIPT-WITNESS se convirtió en ese href. El enlace https del portal seguía renderizándose |
| Ejecutar script como el origen de Element tras un clic | La víctima hace clic en el elemento del menú (UI:R) | Integridad | Inferido a partir del sink del href. El laboratorio no accionó un clic de navegador ni robó un token de Matrix real |
| Leer el token de acceso de Matrix / el almacén criptográfico (toma de control de la cuenta) | Script en el origen frente a localStorage / sesión de IndexedDB | Reconocimiento / integridad | Inferido a partir del XSS en el origen de Element. El testigo del laboratorio es la cadena del href |
| Navegar la pestaña de Element a una página de phishing | iframe sin sandbox de SilentLogin.tsx src={new URL("silent", icsUrl)} | Integridad | Probado en laboratorio que el iframe no tiene sandbox. No se ejercitó la navegación superior |
La misma inserción mediante data: | z.string() acepta cualquier esquema | Integridad | Inferido. El laboratorio solo insertó javascript: |
Cerrado en este pin: app.element.io por defecto (sin banner de Univention). RCE / LPE del SO (Escritorio nodeIntegration: false, sandbox, contextIsolation). XSS en HTML de la línea de tiempo. javascript: en la vista previa de URL (GHSA-9r5h previewFromBundle requiere http:/https:). XSS en la exportación HTML (GHSA-wqmv). Token de medios de widget (GHSA-3jm3). El banner estático link_url: z.url() es configuración del operador, no ICS; z.url() tampoco es una lista de permitidos http/https.
Restos del mismo pin: limpieza de invitado por fragmento, letra de unidad de Windows vector:.
Fijé Element Web v1.12.29 tras la publicación de GitHub del 22 de septiembre de 2026. La vista previa de URL ya había aprendido http:/https: a la mala. El link de ICS de Univention sigue siendo z.string(). La configuración del menú estático usa z.url(). La ruta de obtención nunca pasa por esa comprobación.
Callejones sin salida ya registrados: tratar app.element.io por defecto como la víctima (Univention está restringido); tratar z.url() como una lista de permitidos de esquemas (el constructor de URL acepta javascript:); inflar el XSS de clic a RCE del SO. Una reverse shell. Teatro.
Gadget de las funciones del pin más un navigation.json de ICS simulado. No es un contenedor de Element Web en vivo. how=gadget. Aplicar la lista de permitidos http/https de la vista previa de URL (previewFromBundle) eliminó el href javascript y mantuvo el enlace https del portal.
python3 element-ics-javascript-Abraxas-Labs.py
o
cd lab
./run.sh
Dirígete solo a http://127.0.0.1:19620. Compón el proyecto element-ics-javascript. El stack se desmonta después de la ejecución.
SUCCESS element-ics-javascript how=gadget href-scheme=javascript menu-a-javascript=yes allowlist-rejects=yes silent-no-sandbox=yes ELEMENT-ICS-JAVASCRIPT-WITNESS
Permitir http: y https: en el link de ICS de la misma forma en que lo hace previewFromBundle. Rechazar javascript:, data: y otros esquemas antes de href=. Aislar el iframe silencioso (sandbox="" o al menos sin allow-top-navigation). No tratar z.url() como una lista de esquemas permitidos.
navigation.tsMenu.tsxSilentLogin.tsxpreviewFromBundle