BeyondTrust Remote Support: Cómo la inyección de plantilla puede provocar la ejecución remota de código
En abril de 2025, Jorren Geurts, un hacker ético en Resillion, identificó una vulnerabilidad en BeyondTrust Remote Desktop que permitía a los atacantes aprovechar la Inyección de Plantillas del lado del servidor (SSTI) para obtener tanto ejecución remota de código autenticado como no autenticado en el sistema objetivo.
La vulnerabilidad fue revelada a BeyondTrust a través de su programa Responsible Disclosure el 6 de mayo de 2025. Unas semanas después, CVE-2025-5309 Estaba reservado y fue publicado posteriormente el 16 de junio de 2025.
La siguiente descripción, escrita por Jorren, detalla los procesos que tuvo que pasar para identificar estas vulnerabilidades.
Resumen
Las versiones web de la aplicación de BeyondTrust Remote Support 24.2.2 a 24.2.4, 24.3.1 a 24.3.4 y 25.1.1 Todos son vulnerables a RCE autenticado y no autenticado a través de SSTI.
Si bien ambos vectores representan un riesgo grave para los usuarios y los datos de la aplicación, el vector no autenticado resulta particularmente interesante debido a la naturaleza de la oferta de soporte (remoto) a los clientes de la aplicación. En esencia, ambas variantes son el resultado directo de la interacción de la entrada de usuario no confiable con el motor de plantillas subyacente y sus funciones.
BeyondTrust ha publicado un aviso de seguridad relacionado con el problema, que puede encontrarse aquí: Asesoramiento de seguridad de BeyondTrust BT25-04. Este aviso también detalla las versiones estables:
- Servicio de asistencia remota 24.2.2 a 24.2.4 con la actualización HELP-10826-2
- Servicio de asistencia remota 24.3.1 a 24.3.4 con la actualización HELP-10826-2
- Remote Support 25.1.1 con parche HELP-10826-1
El soporte remoto en pocas palabras
Antes de entrar en lo bueno, permítanme que les explique brevemente qué es el soporte remoto. Según BeyondTrust Su propio sitio web, Remote Support es “una solución de soporte remoto segura de nivel empresarial que permite a los profesionales de TI conectarse a sistemas y dispositivos remotos y controlarlos para ofrecer soporte técnico. Se utiliza por los servicios de asistencia informática, las oficinas de asistencia y los equipos de soporte para solucionar problemas técnicos de forma eficiente”.”
Para facilitar esto, se utilizan varios componentes, desde aplicaciones móviles hasta aplicaciones de escritorio y web. En el contexto de este artículo, tres aplicaciones web disponibles son relevantes:
- Interfaz administrativa: Esta interfaz generalmente es utilizada por usuarios con permisos de administrador y se puede utilizar para configurar la solución.
- Consola de Reputación Web: El centro de asistencia donde se reciben las solicitudes de soporte. Aquí, los agentes autenticados pueden aceptar, mantener, transferir y cerrar las sesiones de asistencia remota.
- Interfaz orientada al cliente: Se puede describir mejor como la ‘página de inicio’ de Remote Support. Dependiendo de la configuración específica, los usuarios finales pueden ingresar aquí su clave de soporte para iniciar la solicitud de asistencia o contactar directamente con un agente específico o disponible.
Al utilizar una combinación de estos tres componentes, se identificó la vulnerabilidad. Ahora que eso queda resuelto, vamos a profundizar en la vulnerabilidad en sí.
Parte 1: Inyección de plantilla en el servidor (SSTI)
Durante una reciente actividad, examiné las interfaces web mencionadas anteriormente. La interfaz administrativa llamó mi atención de inmediato, ya que tenía una cantidad de datos introducidos por los usuarios significativamente mayor que las demás interfaces.
Al revisar el sistema, observé que varios componentes, controlados por los administradores, permitían introducir datos que se mostraban en la interfaz de usuario. Como hacker ético especializado en aplicaciones web, el primer paso natural fue comprobar si Scripting cruzado entre sitios Vulnerabilidades de XSS. Aunque existen múltiples variantes de XSS, la variante almacenada probablemente fue la más interesante en este caso. Pronto se comprobó que, aunque se aceptaban cargas útiles, la salida estaba codificada correctamente, por lo que no se pudo identificar ningún vector de XSS claro.
Luego siguió una breve verificación de las vulnerabilidades de SSTI. SSTI, o Inyección de plantillas en el servidor, El ataque de SSTI es un ataque en el que se utiliza la sintaxis nativa de los modelos para inyectar una carga maliciosa en un modelo, que luego se ejecuta en el servidor. Al igual que el XSS, el SSTI se incluye en el grupo de ataques OWASP A03:2021 – Inyección categoría (la edición más reciente en el momento de escribir).
Se hizo evidente que los administradores podían aportar información que se interrelacionaba directamente con el motor de plantillas subyacente. Por ello, {{7*7}} apareció como 49 En la interfaz de usuario, se demostró que era posible (algunas) interacciones con el motor de plantillas utilizado.

Interpretado como carga útil predeterminada de SSTI.
Ahora, la pregunta era: “¿Qué motor de plantilla están usando?”. Según esto Flujo de trabajo proporcionado por los chicos de Portswigger, el motor podía ser Jinja2, Twig o algo completamente diferente. Al final resultó que era el último. A través de pruebas y errores llegué a la conclusión de que el motor de plantilla que se utilizaba era Blade, que es el motor de templado por defecto para el Marco de trabajo Laravel. Aunque las aplicaciones no revelaron directamente el uso del framework Laravel, esto fue confirmado más tarde – ¡pero no os perdáis la información!
Partiendo de la carga útil anterior, y sabiendo que Blade utiliza PHP, se utilizó la siguiente carga útil de demostración: {{implode(null,array_map(chr(99).chr(104).chr(114),[105,100]))}}.
Dejemos que nos demos un momento para explicar esta carga útil. Blade utiliza la función integrada chr Una función que convierte los valores decimales en sus caracteres correspondientes. A continuación, estos caracteres se insertan en un array_map y que posteriormente se unen mediante el implode función para formar una cadena. La 105 y 100 representar i y d personajes.
Como era de esperar, esto se convirtió en la cadena en la interfaz de atención al cliente. id.
Reflejado id string.
Al haber demostrado que PHP funciona de la misma manera chr, array_map y implode Se puede utilizar para mostrar una salida válida; el único paso que quedaba era hacer que Blade ejecutara nuestro payload de prueba de concepto.
Parte 2: Ejecución remota de código (RCE)
PHP Contiene varias funciones que le permiten ejecutar comandos del sistema. Para ejecutar nuestro comando, se pasó el payload anterior al passthru La función. Envolver nuestro comando en esta función resulta en {{passthru(implode(null,array_map(chr(99).chr(104).chr(114),[105,100])))}}.
Si tiene éxito, el payload ejecutará el id Comanda y muestra los ID de usuario y grupo efectivos en el sistema objetivo. ¡Dado que llegaste hasta aquí, probablemente no sea ninguna sorpresa que esto realmente haya funcionado!

Ejecución del id comando.
Con este método, un usuario autenticado con privilegios administrativos puede ejecutar comandos del sistema arbitrarios en el servidor objetivo, lo que finalmente le permite acceder al sistema como administrador.
Hablando de acceso a la interfaz de programación de aplicaciones (API), varios archivos del sistema objetivo se hicieron accesibles a través de esto y, como se sospechaba anteriormente, se confirmó que la aplicación se había construido utilizando Laravel en el composer.json archivo.

Objetivo composer.json Contenido del archivo.
¿Autenticado o no autenticado?
Desde aquí, decidí intentar profundizar un poco más para ver si esto podría ser aprovechado por alguien más que los administradores de la aplicación.
Dado que los payloads de SSTI parecen activarse en la interfaz de usuario, que normalmente son visitados por usuarios finales no autenticados, decidí centrarme en identificar oportunidades en las que los usuarios de esta interfaz particular tengan control sobre la información que ingresa a la aplicación.
Como los usuarios durante una sesión de soporte pueden chatear con su agente, el vector más obvio sería precisamente esto. Sin embargo, todos los datos recibidos parecían ser tratados correctamente por la aplicación, así que tuve que investigar más.
Al hacerlo, descubrí que los usuarios de la interfaz administrativa pueden ver el chat de las sesiones de soporte en curso y pasadas. Es importante destacar que los usuarios de la interfaz administrativa no necesariamente tienen privilegios administrativos; solo tienen acceso a la interfaz específica con otras funcionalidades. Este podría ser un vector interesante para nuestra perspectiva no autenticada.
Para empezar, establecí otra sesión de soporte entre un agente en la consola Web Rep y un usuario final no autenticado y comencé a chatear de nuevo. Tras intercambiar algunas comunicaciones, pude utilizar la perspectiva del agente para ver las comunicaciones de chat que acababan de enviarse y que aparecían exactamente tal como las había enviado desde la perspectiva del usuario final. Podríamos estar en un buen negocio…
Tras esto, era hora de intentar introducir algunos de los útiles de SSTI mencionados anteriormente. Empecé con los ya probados {{7*7}} y me emocioné cuando apareció en la transcripción del chat como 49 Lo habíamos visto antes. Esto significaba que la misma vulnerabilidad de SSTI probablemente estaba presente en la funcionalidad de chat de una sesión de soporte.

La carga útil básica de SSTI se muestra al ver un transcript de chat.
Todo parecía prometedor, así que, continuando con esto, establecí una vez más una sesión de soporte remoto, pero esta vez recurrí a la confiable {{passthru(implode(null,array_map(chr(99).chr(104).chr(114),[105,100])))}} El contenido era importante y regresé rápidamente a ver el transcripto del chat.

Interpretación del contenido de la carga útil en un transcripción de chat.
Como era de esperar, la carga útil del RCE fue interpretada nuevamente por la aplicación, revelando el RCE no autenticado. El único requisito previo en este escenario es una sesión de soporte activa y que un usuario en la interfaz administrativa pueda ver el transcript de la conversación.
¡Sin clave de sesión, sin problema!
En última instancia, este fue un gran resultado. Pasar de un usuario final no autenticado a ejecutar comandos en el servidor es un éxito significativo desde la perspectiva de un hacker ético, pero increíblemente aterrador para los usuarios de la aplicación y, en particular, para su proveedor.
Pero la historia es más que esto. La aplicación ofrece a sus administradores la opción de configurar la aplicación para que los usuarios finales puedan solicitar directamente soporte a través de un agente de soporte específico o disponible. Esto evita la necesidad de una clave de sesión y solo requiere que el agente acepte la solicitud para configurar una sesión de soporte remoto.

Configuraciones que permiten el acceso directo al soporte.
Siempre que se utilice esta configuración específica, las posibilidades de que cargas maliciosas lleguen a los usuarios deseados aumentan considerablemente. Además, dado que la visualización de los transcriptos de las conversaciones es parte de su uso previsto, cabe esperar que un ataque de este tipo resulte en una explotación exitosa.
Mitigación
Al momento de escribir este artículo, el problema de la SSTI aún no se ha solucionado, lo que podría indicar que otros ataques que aprovechen la interpretación de los modelos aún puedan ser efectivos. Sin embargo, BeyondTrust ha eliminado la posibilidad de llamar a funciones PHP peligrosas como passthru, sistema y exec (entre otros). Esto significa que al usar una carga útil como {{implode(null,array_map(chr(99).chr(104).chr(114),[105,100]))}}, aún se permite (al fin y al cabo, esto solo imprime la cadena id). Mientras que los payloads que intentan encapsular lo anterior en una función PHP peligrosa resultan en un error del servidor al llamar al payload, como {{exec(implode(null,array_map(chr(99).chr(104).chr(114),[105,100])))}}.
La versión del servicio de soporte remoto se puede consultar navegando hasta la URL base específica y añadiendo lo siguiente: /get_rdf?comp=sdcust&locale_code=es-es. Abrir el archivo descargado con un editor de texto (o cualquier otro programa que muestre el contenido del archivo) muestra la versión actual de la aplicación encima del resultado.

Consultar la versión del servicio de asistencia remota.
En última instancia, los datos procedentes de fuentes potencialmente no confiables nunca deberían ser enviados a funciones que puedan ejecutar comandos.
Cronología
- Abril de 2025 – Se descubrieron los primeros hallazgos.
- 6 de mayo de 2025 – Presentación del informe de divulgación responsable, respuesta recibida.
- 22 de mayo de 2025 – Se notificó que la vulnerabilidad había sido solucionada en Remote Support 24.3.4 y se anunció la intención de publicar este post en el blog.
- 28 de mayo de 2025 – El CVE-2025-5309 está reservado y la divulgación pública se aplaza hasta que BeyondTrust dé el visto bueno.
- 16 de junio de 2025 – Se publica CVE-2025-5309.
- 16 de junio de 2025 – Se publica el Advisory de seguridad de BeyondTrust BT25-04.
- 18 de junio de 2025 – Publicación de este artículo.
Créditos
Un agradecimiento especial a Jim Blankendaal por revisar este artículo y asesorarme durante todo el proceso de divulgación responsable.