知识点(SSTI漏洞/flask框架/tonado框架)
SSTI
SSTI 漏洞即服务器端模板注入漏洞(Server-Side Template Injection)。
原理
服务器端模板注入是攻击者利用应用程序中模板引擎的漏洞,通过注入恶意代码到模板中,从而在服务器端执行任意代码或获取敏感信息的攻击方式。模板引擎通常用于将动态数据与固定的模板相结合,生成最终的 HTML、XML 或其他格式的文档。
模版实际指,如:搜索框
常见的模板引擎及漏洞示例
- Jinja2:在 Python 的 Flask 框架中常使用 Jinja2 模板引擎。如果应用程序使用 Jinja2 模板且没有正确处理用户输入,攻击者可能通过构造特殊的输入来执行任意 Python 代码。例如,攻击者可以尝试注入类似于
{ { 7*7 }}
这样的表达式,如果应用程序直接将用户输入渲染到模板中,就可能会计算并显示出 49,证明存在注入漏洞。更危险的是,攻击者还可能注入如{ { config }}
这样的内容来获取应用程序的配置信息,或者注入{ { [].__class__.__base__.__subclasses__() }}
来获取系统的一些敏感信息。 - Thymeleaf:在 Java 的 Spring 框架等中较为常用。攻击者可能通过注入恶意的 OGNL(Object Graph Navigation Language)表达式来实现攻击。比如,攻击者可能尝试注入
${#rt.exec('calc.exe')}
,如果漏洞存在,就可能在服务器端执行计算器程序,当然在实际环境中可能会执行更恶意的命令。 - Velocity:也是 Java 中常用的模板引擎。攻击者可以利用它的语法进行注入攻击,例如
#set($x='freemarker.template.utility.Execute')${$x("id")}
,可能会在服务器上执行id
命令获取用户信息等。
出现漏洞原因
当应用程序没有对用户输入进行充分的验证和过滤时,攻击者就可能利用这一点注入恶意脚本,破坏应用程序的正常运行,甚至获取服务器的控制权。
防范措施
- 输入验证和过滤:对用户输入进行严格的验证和过滤,确保输入符合预期的格式和范围,不包含任何可能导致注入的特殊字符或表达式。可以使用正则表达式等方式进行验证,对危险字符进行转义或拒绝。
- 使用安全的模板引擎配置:确保模板引擎使用安全的配置选项,例如,在 Jinja2 中可以启用
autoescape
功能,自动对用户输入进行转义,防止注入攻击。 - 更新和维护软件:及时更新模板引擎和相关的框架、库,以修复已知的安全漏洞。软件开发者通常会在发现漏洞后发布安全更新,及时应用这些更新可以有效防范 SSTI 攻击。
- 最小权限原则:运行应用程序的用户或进程应具有最小的权限,避免以管理员或高权限用户身份运行,这样即使发生 SSTI 攻击,攻击者能够造成的危害也会受到限制。
- 安全审计和监控:建立安全审计机制,对应用程序的日志进行监控和分析,及时发现异常的请求和操作。如果发现有疑似 SSTI 攻击的行为,能够及时采取措施进行处理。
SSTI注入
常见模板引擎的 SSTI 注入示例:
Jinja2(Python)
Jinja2 是 Python 中常用的模板引擎。攻击者可以通过注入特殊的表达式来执行任意 Python 代码。
{
{ 7*7 }} # 若存在漏洞,会输出 49,可用于验证漏洞
{
{ config.items() }} # 尝试获取应用程序的配置信息
可以执行系统命令
{
{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }} # 读取 /etc/passwd 文件内容
Twig(PHP)
Twig 是 PHP 中常用的模板引擎。攻击者可以尝试注入 PHP 代码来执行命令。
{
{ _self.env.registerUndefinedFilterCallback("exec") }}{
{ _self.env.getFilter("id") }} # 尝试执行 id 命令
Velocity(Java)
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 应用程序开发的软件框架。
一些常见的 Web 框架:
Python 语言
- Django
- 特点:自带了众多开发 Web 应用所需的组件,如数据库 ORM(对象关系映射)、管理界面、表单处理、用户认证等。遵循 MVC(实际上是 MVT,即模型 - 视图 - 模板)架构模式,代码结构清晰,有严格的代码规范和最佳实践。
- 适用场景:适合开发大型、复杂的 Web 应用,如内容管理系统(CMS)、电子商务网站等。
- Flask
- 特点:轻量级的微框架,核心代码简单,只提供了 Web 应用的基本功能。具有高度的灵活性,开发者可以根据项目需求自由选择和集成各种扩展,如数据库操作、表单处理等。
- 适用场景:适合快速搭建小型 Web 应用、原型验证以及开发 RESTful API。
- Tornado
- 特点:高性能的 Web 框架,采用异步 I/O 和单线程事件循环机制,能够处理大量的并发连接,原生支持 WebSocket 协议。
- 适用场景:适用于开发高并发、实时性要求较高的应用,如实时聊天系统、游戏服务器等。
Java 语言
- Spring Boot
- 特点:基于 Spring 框架,简化了 Spring 应用的开发和配置过程,通过自动配置和约定优于配置的原则,让开发者可以快速搭建 Web 应用。提供了丰富的插件和工具,方便集成各种功能。
- 适用场景:广泛应用于企业级 Web 应用开发,包括金融、电商、医疗等领域。
- Struts 2
- 特点:是一个基于 MVC 架构的 Web 框架,采用了拦截器和标签库等技术,具有良好的可扩展性和可维护性。
- 适用场景:曾经在 Java Web 开发中非常流行,适合开发传统的企业级 Web 应用,但近年来逐渐被 Spring Boot 等框架所取代。
- Play Framework
- 特点:采用响应式编程模型,支持异步处理和实时通信,具有高效的开发和部署体验。提供了强大的开发工具和调试功能。
- 适用场景:适合开发高性能、实时性要求较高的 Web 应用,如在线游戏、社交网络等。
Ruby 语言
- Ruby on Rails
- 特点:遵循 MVC 架构模式,强调约定优于配置(Convention Over Configuration)的原则,能够极大地提高开发效率。具有丰富的插件和工具,社区活跃,文档完善。
- 适用场景:适合快速开发各种类型的 Web 应用,尤其在创业公司和敏捷开发项目中应用广泛。
JavaScript 语言
- Express
- 特点:基于 Node.js 的轻量级 Web 框架,具有简洁灵活的特点,提供了丰富的中间件和路由机制,方便开发者构建 Web 应用和 API。
- 适用场景:适合开发实时 Web 应用、RESTful API 以及与前端框架(如 React、Vue.js)配合使用的后端服务。
- Koa
- 特点:同样基于 Node.js,是 Express 原班人马打造的下一代 Web 框架,采用了异步函数(async/await)的方式处理异步操作,代码更加简洁和易于维护。
- 适用场景:适用于构建高性能、可扩展的 Web 应用和服务。
- Next.js
- 特点:基于 React 的服务端渲染(SSR)框架,提供了自动代码分割、静态生成、服务端渲染等功能,能够优化页面性能和搜索引擎优化(SEO)。
- 适用场景:适合开发需要良好 SEO 效果的 React 应用,如企业官网、博客等。
Flask 框架
Flask 是一个轻量级的 Web 框架,也被称为 “微框架”。开发者可以根据项目需求自由选择和集成其他扩展,具有很高的灵活性。
1)安装:
pip install flask
2)组成:WSGI系统、调试、路由
3)模板引擎:Jinja2
4)使用到装饰器:以@开头的代码方法5)语言:Python
Jinja2模版引擎
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 中,当一个整数和一个字符串进行乘法运算时,意味着将该字符串重复整数指定的次数。
特点:
- 轻量级:Flask 的核心代码简洁,不包含过多的依赖和复杂的功能,使得项目的启动速度快,代码的可维护性高。
- 易于上手:对于初学者来说,Flask 的学习曲线较为平缓,其文档清晰易懂,通过简单的几行代码就可以搭建一个基本的 Web 应用。
- 扩展性强:Flask 拥有丰富的扩展库,如 Flask-SQLAlchemy 用于数据库操作、Flask-WTF 用于表单处理、Flask-RESTful 用于构建 RESTful API 等,开发者可以根据需要灵活选择和集成这些扩展。
创建示例:
from flask import render_template
1.导入语句:
from flask import Flask, render_template
从 flask
模块导入了 Flask
类和 render_template
函数。Flask
类用于创建 Flask 应用实例,而 render_template
函数用于渲染 HTML 模板。
2.创建 Flask 应用实例:
app = Flask(__name__)
创建了一个 Flask 应用实例,__name__
是 Python 的内置变量,表示当前模块的名称。
3.定义路由和视图函数:
@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
字典中的键值对作为关键字参数传递给模板。
4.运行应用:
if __name__ == '__main__':
app.run(debug=True)
Tornado 框架
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服务器的实现。- 2.
HTTPConnection
类用来处理HTTP请求,包括读取HTTP请求头、读取POST传递的数据。 - 3.调用用户自定义的处理方法,以及把响应数据写给客户端的
socket。
判断是什么代码引擎:
1.代表性的代码(导入语句)
2.控制语句
3.运算规则
对比区别:
Jinja2模版引擎(属于Flask框架,Python语言)和其他模板引擎,例:Twig(属于Symfony框架,PHP语言), Smarty(属于Codelgniter框架,PHP语言)
1.导入或实例化代码
使用 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;
2.控制语句
Jinja2:使用 {
{ }}
来表示变量,{% %}
用于控制结构(如 if
、for
语句),{# #}
用于注释。
Twig:语法和 Jinja2 类似,同样使用 {
{ }}
表示变量,{% %}
用于控制结构,{# #}
用于注释。不过 Twig 是在 PHP 环境中使用。
Smarty:使用 {$variable}
表示变量,{if}...{/if}
、{foreach}...{/foreach}
等标签来实现控制结构,{*...*}
用于注释。
3.运算规则
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
。