我们用如下环境进行讲解(flask-jinja2):
from flask import Flask from flask import render_template from flask import request from flask import render_template_string app = Flask(__name__) @app.route('/') def index(): code = request.args.get('id') template = ''' <h3>%s</h3> '''%(code) return render_template_string(template) if __name__ == '__main__': app.run() 关于flask/jinja2的基础知识点这里不过多讲解,自己去查找文档学习,了解里面的路由、渲染等基础知识即可,毕竟学习还是要学会看文档的啦。关于利用payload时python知识讲解
面向对象语言的方法来自于类,对于python,有很多好用的函数库,我们经常会再写Python中用到import来引入许多的类和方法,python的str(字符串)、dict(字典)、tuple(元组)、list(列表)这些在Python类结构的基类都是 object ,而object拥有众多的子类。因此我们在利用的时候主要目的就是先寻找object类,然后通过object去寻找能实现我们目的的类,例如能实现我们文件读取的类:<class '_frozen_importlib_external.FileLoader'>(python3下),这个类下面有可以实现文件读取的函数,我们等会介绍。 下面说一下如何寻找我们的object类:先介绍一个python的魔术属性__class__,
__class__:用来查看变量所属的类,根据前面的变量形式可以得到其所属的类。 __class__ 是类的一个内置属性,表示类的类型,返回 <type 'type'> ; 也是类的实例的属性,表示实例对象的类。 示例:![](/i/l/?n=22&i=blog/2727822/202210/2727822-20221002161943229-1111029910.png)
可以看到我们的单引号属于str类,这里我们也可以换成其他的。
可以看到我们的元组类、字典类、列表类。
下面介绍另一个魔术属性__bases__,
__bases__:用来查看类的基类,也可以使用数组索引来查看特定位置的值。 通过该属性可以查看该类的所有直接父类,该属性返回所有直接父类组成的 元组 (虽然只有一个元素)。
这里我们用它来寻找我们的基类object,示例如下图:![](/i/l/?n=22&i=blog/2727822/202210/2727822-20221002162606847-894325460.png)
当然获取基类还能用 __mro__ 方法,__mro__ 方法可以用来获取一个类的调用顺序,比如
因为返回的都是元组形式,所以我们要用下标来定位我们的object类。
下面介绍魔术属性__subclasses__()
__subclasses__():查看当前类的子类组成的列表,即返回基类object的子类。
示例如下图:![](/i/l/?n=22&i=blog/2727822/202210/2727822-20221002162907367-997910626.png)
可以看到有好多的类,但是我们要寻找我们需要使用的类(自己积累),比如有文件读取函数的类,<class '_frozen_importlib_external.FileLoader'>要注意我这里时p3的环境,和p2环境有区别,不过都是同样的思路,然后我们自己写脚本来获取我们利用类的下标,比如我这里这个类的下标时99。这个东西不同环境是不一样的,所以你不能只是照抄别人的payload。找到类了,如何寻找我们的方法呢,
下面介绍魔术属性__dict__
__dict__:返回这个类中已经定义了的属性和方法
![](/i/l/?n=22&i=blog/2727822/202210/2727822-20221002170156073-772756894.png)
在这里面可以看到我们的get_data函数。(补充:利用__doc__魔术方法可以查看函数的信息)
所以payload如下''.__class__.__mro__[1].__subclasses__()[99].__dict__['get_data'](0,'/etc/passwd')注意函数参数要用小括号。
这里补充一点我自己的经验,我们找到了这个类<class '_frozen_importlib_external.FileLoader'>,再往下究竟如何找函数呢,我先是找到了_frozen_importlib_external这个py库的源码,然后找到了下面的FileLoader类,去里面找函数,如下图演示。
上面是介绍的如何读取到我们想要的文件,我们下面介绍一下经常使用的payload。比如命令执行。
关于__builtins__
__builtins__: 即时引用,在程序还为执行代码的时候就已经加载进来了。此模块并不需要导入,可以在任何模块中执行引用。内建名称空间,内建名称空间有许多名字到对象之间映射,而这些名字其实就是内建函数的名称,对象就是这些内建函数本身。即里面有很多常用的函数。
用法示例:这里可以利用eval函数
![](/i/l/?n=22&i=blog/2727822/202210/2727822-20221003000232858-1681617349.png)
或者 __builtins__.__dict__['__import__']('os').system('whoami')
关于__globals__
__globals__:使用方式是 函数名.__globals__获取function所处空间下可使用的module、方法以及所有变量。
关于url_for
url_for:flask的一个方法,可以用于得到__builtins__
利用:url_for.__globals__['__builtins__']['eval']('__import__("os").popen("ls").read()')
下面总结一下几个含有eval函数的类:
- warnings.catch_warnings
- WarningMessage
- codecs.IncrementalEncoder
- codecs.IncrementalDecoder
- codecs.StreamReaderWriter
- os._wrap_close
- reprlib.Repr
- weakref.finalize
- etc.
做题总结:
1.寻找配置信息一般利用{{config}}
2.读取文件
3.任意代码执行
4.在3的基础上env
标签:__,函数,flask,object,基础知识,SSTI,import,我们 From: https://www.cnblogs.com/meng-han/p/16749832.html