
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
Element Web v1.12.29 - Element / New Vector
Clase: XSS Alcance: Remoto
El módulo de banner de Univention obtiene el ICS navigation.json, acepta el link de cada entrada como z.string() sin comprobación de 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 del ICS no. La vista previa de URL en el mismo pin ya rechaza javascript: (previewFromBundle, GHSA-9r5h). Esto no es el app.element.io por defecto. Necesita modules/banner con menu.type univention, más un ICS en el que confíe el despliegue.
Cualquiera que pueda cambiar ese navigation.json planta 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 | sin CVE todavía |
| 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 | v1.12.29 tag v1.12.29 (2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e). Condicionado: banner de Univention + ICS. |
| Auth | 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 |
| Lab | 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 toma de control de la cuenta de Matrix: token de acceso, almacén criptográfico, la sesión. No es RCE del SO. El escritorio sigue teniendo nodeIntegration desactivado y un sandbox.
| Privilegio | Método / sink | Recon / integridad / disponibilidad | Probado en lab 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 lab. El enlace ICS simulado javascript:ELEMENT-ICS-JAVASCRIPT-WITNESS se convirtió en ese href. El enlace del portal https 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 del sink del href. El lab no condujo un clic de navegador ni robó un token de Matrix en vivo |
| Leer el token de acceso de Matrix / almacén criptográfico (toma de control de cuenta) | Script en el origen contra localStorage / sesión de IndexedDB | Recon / integridad | Inferido del XSS en el origen de Element. El testigo del lab 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 lab que el iframe no tiene sandbox. La navegación superior no se ejercitó |
Mismo plantado vía data: | z.string() acepta cualquier esquema | Integridad | Inferido. El lab solo plantó javascript: |
Cerrado en este pin: app.element.io por defecto (sin banner de Univention). RCE del SO / LPE (Escritorio nodeIntegration: false, sandbox, contextIsolation). XSS del HTML de la línea de tiempo. javascript: en la vista previa de URL (GHSA-9r5h previewFromBundle requiere http:/https:). XSS de exportación HTML (GHSA-wqmv). Token de medios del widget (GHSA-3jm3). El link_url: z.url() del banner estático es configuración del operador, no ICS; z.url() tampoco es una allowlist de http/https.
Restos del mismo pin: fragment guest wipe, vector: Windows drive-letter.
Fijé Element Web v1.12.29 tras el lanzamiento de GitHub del 22 de septiembre de 2026. La vista previa de URL ya había aprendido http:/https: a las malas. El link del ICS de Univention sigue siendo z.string(). La configuración estática del menú usa z.url(). La ruta de obtención nunca pasa por esa comprobación.
Giros equivocados ya registrados: tratar el app.element.io por defecto como la víctima (Univention está condicionado); tratar z.url() como una allowlist de esquemas (el constructor 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 ICS simulado navigation.json. No es un contenedor de Element Web en vivo. how=gadget. Aplicar la allowlist http/https de la vista previa de URL (previewFromBundle) eliminó el href javascript y mantuvo el enlace del portal https.
python3 element-ics-javascript-Abraxas-Labs.py
o
cd lab
./run.sh
Objetivo solo http://127.0.0.1:19620. Proyecto de Compose element-ics-javascript. El stack se desmonta tras 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
Aplicar una allowlist de http: y https: en el link del ICS de la misma forma que lo hace previewFromBundle. Rechazar javascript:, data: y otros esquemas antes de href=. Poner el iframe silencioso en sandbox (sandbox="" o al menos sin allow-top-navigation). No tratar z.url() como una allowlist de esquemas.
navigation.tsMenu.tsxSilentLogin.tsxpreviewFromBundleGNU Affero GPL v3.0. Ver LICENSE. Solo lab en loopback. Sin garantía.