
En esta sección, analizaremos qué es la inyección de plantillas del lado del servidor y describiremos la metodología básica para explotar las vulnerabilidades de inyección de plantillas del lado del servidor. También sugeriremos formas de asegurarse de que su propio uso de plantillas no lo exponga a la inyección de plantillas del lado del servidor.
Esta técnica fue documentada por primera vez por PortSwigger en nuestro artículo de investigación de 2015 sobre el tema. Si está interesado en cómo pudimos explotar algunas de estas vulnerabilidades en sitios web en vivo, hay un artículo completo disponible en nuestra página de investigación.
¿Qué es la inyección de plantillas del lado del servidor?
La inyección de plantilla del lado del servidor es cuando un atacante puede usar la sintaxis de plantilla nativa para inyectar una carga útil maliciosa en una plantilla, que luego se ejecuta en el lado del servidor.
Los motores de plantillas están diseñados para generar páginas web combinando plantillas fijas con datos volátiles. Los ataques de inyección de plantillas del lado del servidor pueden ocurrir cuando la entrada del usuario se concatena directamente en una plantilla, en lugar de pasarla como datos. Esto permite a los atacantes inyectar directivas de plantillas arbitrarias para manipular el motor de plantillas, lo que a menudo les permite tomar el control total del servidor. Como sugiere el nombre, las cargas útiles de inyección de plantillas del lado del servidor se entregan y evalúan del lado del servidor, lo que puede hacerlas mucho más peligrosas que una inyección de plantilla típica del lado del cliente.
¿Cuál es el impacto de la inyección de plantillas del lado del servidor?
Las vulnerabilidades de inyección de plantillas del lado del servidor pueden exponer los sitios web a una variedad de ataques según el motor de plantillas en cuestión y cómo lo usa exactamente la aplicación. En ciertas circunstancias excepcionales, estas vulnerabilidades no representan un riesgo real para la seguridad. Sin embargo, la mayoría de las veces, el impacto de la inyección de plantillas del lado del servidor puede ser catastrófico.
En el extremo más severo de la escala, un atacante puede potencialmente lograr la ejecución remota de código, tomando el control total del servidor back-end y usándolo para realizar otros ataques en la infraestructura interna.
Incluso en los casos en los que no es posible la ejecución remota completa del código, un atacante a menudo puede usar la inyección de plantillas del lado del servidor como base para muchos otros ataques, lo que podría obtener acceso de lectura a datos confidenciales y archivos arbitrarios en el servidor.
Solicita una cotización del mejor escaner de vulnerabilidades de sitios web y aplicativos expuestos, con precios por anualidad e intercambio de targets, BURP SUITE ENTERPRISE es el único que lo ofrece, cambia YA!
¿Cómo surgen las vulnerabilidades de inyección de plantillas del lado del servidor?
Las vulnerabilidades de inyección de plantillas del lado del servidor surgen cuando la entrada del usuario se concatena en plantillas en lugar de pasarse como datos.
Las plantillas estáticas que simplemente proporcionan marcadores de posición en los que se representa el contenido dinámico generalmente no son vulnerables a la inyección de plantillas del lado del servidor. El ejemplo clásico es un correo electrónico que saluda a cada usuario por su nombre, como el siguiente extracto de una plantilla de Twig:
$output = $twig->render("Dear {first_name},", array("first_name" => $user.first_name) );
Esto no es vulnerable a la inyección de plantillas del lado del servidor porque el nombre del usuario simplemente se pasa a la plantilla como datos.
Sin embargo, como las plantillas son simplemente cadenas, los desarrolladores web a veces concatenan directamente la entrada del usuario en las plantillas antes de la representación. Tomemos un ejemplo similar al anterior, pero esta vez, los usuarios pueden personalizar partes del correo electrónico antes de enviarlo. Por ejemplo, es posible que puedan elegir el nombre que se utiliza:
$output = $twig->render("Dear " . $_GET['name']);
En este ejemplo, en lugar de pasar un valor estático a la plantilla, parte de la plantilla en sí se genera dinámicamente mediante el GET
parámetro name
. Dado que la sintaxis de la plantilla se evalúa en el lado del servidor, esto permite potencialmente que un atacante coloque una carga útil de inyección de plantilla del lado del servidor dentro del name
parámetro de la siguiente manera:
http://vulnerable-website.com/?name={{bad-stuff-here}}
Las vulnerabilidades como esta a veces son causadas por accidente debido a un diseño de plantilla deficiente por parte de personas que no están familiarizadas con las implicaciones de seguridad. Como en el ejemplo anterior, puede ver diferentes componentes, algunos de los cuales contienen información del usuario, concatenados e incrustados en una plantilla. De alguna manera, esto es similar a las vulnerabilidades de inyección SQL que ocurren en declaraciones preparadas mal escritas.
Sin embargo, a veces este comportamiento se implementa intencionalmente. Por ejemplo, algunos sitios web permiten deliberadamente que ciertos usuarios privilegiados, como los editores de contenido, editen o envíen plantillas personalizadas por diseño. Esto claramente plantea un gran riesgo de seguridad si un atacante puede comprometer una cuenta con tales privilegios.
Construcción de un ataque de inyección de plantilla del lado del servidor
La identificación de vulnerabilidades de inyección de plantillas del lado del servidor y la elaboración de un ataque exitoso generalmente implica el siguiente proceso de alto nivel.
Detectar
Las vulnerabilidades de inyección de plantillas del lado del servidor a menudo pasan desapercibidas no porque sean complejas sino porque solo son realmente evidentes para los auditores que las buscan explícitamente. Si puede detectar que existe una vulnerabilidad, puede ser sorprendentemente fácil explotarla. Esto es especialmente cierto en entornos sin zona de pruebas.
Como con cualquier vulnerabilidad, el primer paso hacia la explotación es poder encontrarla. Quizá el enfoque inicial más simple sea tratar de fuzzear la plantilla mediante la inyección de una secuencia de caracteres especiales comúnmente utilizados en expresiones de plantilla, como ${{<%[%'"}}%\
. Si se genera una excepción, esto indica que el servidor está interpretando potencialmente la sintaxis de la plantilla inyectada de alguna manera. Esta es una señal de que puede existir una vulnerabilidad a la inyección de plantillas del lado del servidor.
Las vulnerabilidades de inyección de plantillas del lado del servidor ocurren en dos contextos distintos, cada uno de los cuales requiere su propio método de detección. Independientemente de los resultados de sus intentos de fuzzing, es importante probar también los siguientes enfoques específicos del contexto. Si el fuzzing no fue concluyente, una vulnerabilidad aún puede revelarse utilizando uno de estos enfoques. Incluso si fuzzing sugirió una vulnerabilidad de inyección de plantilla, aún necesita identificar su contexto para poder explotarla.
Solicita una cotización del mejor escaner de vulnerabilidades de sitios web y aplicativos expuestos, con precios por anualidad e intercambio de targets, BURP SUITE ENTERPRISE es el único que lo ofrece, cambia YA!
Contexto de texto sin formato
La mayoría de los lenguajes de plantilla le permiten ingresar contenido libremente ya sea usando etiquetas HTML directamente o usando la sintaxis nativa de la plantilla, que se representará en HTML en el back-end antes de que se envíe la respuesta HTTP. Por ejemplo, en Freemarker, la línea render('Hello ' + username)
se representaría como Hello Carlos
.
Esto a veces se puede explotar para XSS y, de hecho, a menudo se confunde con una vulnerabilidad XSS simple. Sin embargo, al establecer operaciones matemáticas como el valor del parámetro, podemos probar si este también es un punto de entrada potencial para un ataque de inyección de plantilla del lado del servidor.
Por ejemplo, considere una plantilla que contenga el siguiente código vulnerable:
render('Hello ' + username)
Durante la auditoría, podemos probar la inyección de plantillas del lado del servidor solicitando una URL como:
http://vulnerable-website.com/?username=${7*7}
Si la salida resultante contiene Hello 49
, esto muestra que la operación matemática se está evaluando en el lado del servidor. Esta es una buena prueba de concepto para una vulnerabilidad de inyección de plantilla del lado del servidor.
Tenga en cuenta que la sintaxis específica necesaria para evaluar con éxito la operación matemática variará según el motor de plantilla que se utilice. Discutiremos esto con más detalle en el paso Identificar .
Contexto del código
En otros casos, la vulnerabilidad queda expuesta cuando la entrada del usuario se coloca dentro de una expresión de plantilla, como vimos anteriormente con nuestro ejemplo de correo electrónico. Esto puede tomar la forma de un nombre de variable controlable por el usuario que se coloca dentro de un parámetro, como:
greeting = getQueryParameter('greeting')
engine.render("Hello {{"+greeting+"}}", data)
En el sitio web, la URL resultante sería algo como:
http://vulnerable-website.com/?greeting=data.username
Esto se representaría en la salida a Hello Carlos
, por ejemplo.
Este contexto se pasa por alto fácilmente durante la evaluación porque no da como resultado un XSS obvio y es casi indistinguible de una simple búsqueda de hashmap. Un método para probar la inyección de plantillas del lado del servidor en este contexto es establecer primero que el parámetro no contiene una vulnerabilidad XSS directa mediante la inyección de HTML arbitrario en el valor:
http://vulnerable-website.com/?greeting=data.username
En ausencia de XSS, esto generalmente dará como resultado una entrada en blanco en la salida (solo Hello
sin nombre de usuario), etiquetas codificadas o un mensaje de error. El siguiente paso es intentar salir de la declaración utilizando la sintaxis de plantillas común e intentar inyectar HTML arbitrario después:
http://vulnerable-website.com/?greeting=data.username}}
Si esto nuevamente da como resultado un error o una salida en blanco, ha utilizado la sintaxis del lenguaje de plantilla incorrecto o, si ninguna sintaxis de estilo de plantilla parece ser válida, la inyección de plantilla del lado del servidor no es posible. Alternativamente, si la salida se representa correctamente, junto con el HTML arbitrario, esta es una indicación clave de que existe una vulnerabilidad de inyección de plantilla del lado del servidor:
Hello Carlos
Identificar
Una vez que haya detectado el potencial de inyección de plantilla, el siguiente paso es identificar el motor de plantilla.
Aunque hay una gran cantidad de lenguajes de plantillas, muchos de ellos usan una sintaxis muy similar que se elige específicamente para que no entre en conflicto con los caracteres HTML. Como resultado, puede ser relativamente simple crear cargas útiles de sondeo para probar qué motor de plantilla se está utilizando.
Simplemente enviar una sintaxis no válida suele ser suficiente porque el mensaje de error resultante le dirá exactamente cuál es el motor de plantilla y, a veces, incluso qué versión. Por ejemplo, la expresión no válida <%=foobar%>
desencadena la siguiente respuesta del motor ERB basado en Ruby:
(erb):1:in `
from /usr/lib/ruby/2.5.0/erb.rb:876:in `eval’
from /usr/lib/ruby/2.5.0/erb.rb:876:in `result’
from -e:4:in `
De lo contrario, deberá probar manualmente diferentes cargas útiles específicas del idioma y estudiar cómo las interpreta el motor de plantillas. Usando un proceso de eliminación basado en qué sintaxis parece ser válida o no válida, puede reducir las opciones más rápido de lo que piensa. Una forma común de hacer esto es inyectar operaciones matemáticas arbitrarias utilizando la sintaxis de diferentes motores de plantilla. A continuación, puede observar si se evalúan con éxito. Para ayudar con este proceso, puede usar un árbol de decisión similar al siguiente:
Debe tener en cuenta que la misma carga útil a veces puede devolver una respuesta correcta en más de un idioma de plantilla. Por ejemplo, la carga útil {{7*'7'}}
regresa 49
en Twig y 7777777
en Jinja2. Por lo tanto, es importante no saltar a conclusiones basadas en una sola respuesta exitosa.
Explotar
Después de detectar que existe una vulnerabilidad potencial e identificar con éxito el motor de plantillas, puede comenzar a intentar encontrar formas de explotarla.
Cómo prevenir vulnerabilidades de inyección de plantillas del lado del servidor
La mejor manera de evitar la inyección de plantillas del lado del servidor es no permitir que ningún usuario modifique o envíe nuevas plantillas. Sin embargo, esto a veces es inevitable debido a los requisitos comerciales.
Una de las formas más sencillas de evitar la introducción de vulnerabilidades de inyección de plantillas del lado del servidor es usar siempre un motor de plantillas «sin lógica», como Moustache, a menos que sea absolutamente necesario. Separar la lógica de la presentación tanto como sea posible puede reducir en gran medida su exposición a los ataques basados en plantillas más peligrosos.
Otra medida es ejecutar solo el código de los usuarios en un entorno aislado donde los módulos y funciones potencialmente peligrosos se han eliminado por completo. Desafortunadamente, el código no confiable de sandboxing es intrínsecamente difícil y propenso a omitirse.
Finalmente, otro enfoque complementario es aceptar que la ejecución de código arbitrario es casi inevitable y aplicar su propio espacio aislado implementando su entorno de plantilla en un contenedor Docker bloqueado, por ejemplo.
Solicita una cotización del mejor escaner de vulnerabilidades de sitios web y aplicativos expuestos, con precios por anualidad e intercambio de targets, BURP SUITE ENTERPRISE es el único que lo ofrece, cambia YA!
Accion
Encuentre vulnerabilidades SSTI utilizando el escáner de vulnerabilidades web de Burp Suite
Si te ha gustado, ¡compártelo con tus amigos!
Por favor déjanos saber qué piensas sobre este artículo
¿Cómo calificarías este contenido?
Promedio de puntuación 0 / 5. Recuento de votos: 0
Hasta ahora, ¡no hay votos!. Sé el primero en puntuar este contenido.
¡Siento que este contenido no te haya sido útil!
Dime, ¿cómo puedo mejorar este contenido?