• ssti 前置学习


    python venv环境

    可以把它想象成一个容器,该容器供你用来存放你的Python脚本以及安装各种Python第三方模块,容器里的环境和本机是完全分开的

    创建venv环境安装flask

    #apt install python3.10-venv

    #cd /opt

    #python3 -m venv flask1

    #cd /opt   选择路径
    #python3 -m venv flask1   创建名为flask1的venv环境
    #Is
    #cd falsk1  多一个文件夹flask1
    #ls   包含所有python组件

    #vim demo.py 

    #vim demo.py
    print("this is test")    在/opt下创建demo.py
    #python3 demo.py   直接使用python是系统的组件
    执行flask1路径下的python
     

    方法一

    #/opt/flask1/bin/python3 demo.py绝对路径
    方法二

    #cd flask1    进入flask1虚拟环境
    #source ./bin/activate
    ##python3 demo.py
    #deactivate     退出虚拟环境

    安装flask

    pip3 install flask --root-user-action=ignore mediapipe -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 

    #python3
    >>>import flask
    >>>quit()

    python flask

    Flask是一个使用 Python 编写的轻量级 Web 应用框架
    其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。

    Flask的特点: 良好的文档、丰富的插件、包含开发服务器和调试器 (debugger) 、集成支持单元测试、RESTful请求调度、支持安全cookies、基于Unicode。
    Python可直接用flask启动一个web服务页面。

    1. 进入虚拟环境flask1
    2. #/opt
    3. #vim demo.py 在/opt路径下编辑demo.py
    4. from flask import Flask 启动flask模块,创建一个Flask类
    5. app = Flask(__name__) name 是系统变量,指的是本py文件的文件名
    6. @app.route('/')路由
    7. def hello():
    8. return "hello benben"
    9. if __name_=='__main__'
    10. app.run() 只能被python直接运行而不能被作为组件或模块被调用。

    监听所有物理端口

    添加端口为80

    ssti漏洞成因


    渲染模板时,没有严格控制对用户的输入;
    使用了危险的模板,导致用户可以和flask程序进行交互,可能造成任意文件读取和RCE远程控制后台系统

    演示

    这段代码最大的漏洞,就是通过 format() 方法直接对页面的 {0} 参数进行替换,这将造成当用户对参数 id 按照 flask 框架的语法进行赋值时,模板引擎渲染时将会把用户输入当作 python 代码进行执行(但并不能直接执行 python 代码)

    1. from importlib.resources import contents
    2. import time
    3. from flask import Flask,request,render_template_string
    4. app = Flask(__name__)
    5. @app.route('/',methods =['GET'])
    6. def index():
    7. str = request.args.get('ben') //str值通过format0)函数填充到body中间
    8. html_str ='''
    9. {0} //0里可以定义任何参数
    10. '''.format(str)
    11. return render_template_string(html_str) //return render template string会把内的字符串当成代码指令
    12. if __name__== '__main__':
    13. app.debug = True
    14. app.run('127.0.0.1','8080')

    __name__ 是python的内置属性,是系统全局变量!每一个py文件都有一个属于自己的__name__:

    如果py文件作为模块被导入(import),那么__name__就是该py文件的文件名(也称 模块名);

    如果py文件直接运行时(Ctrl+Shift+F10),那么__name__默认等于字符串”__main__”;

    举个简单的例子:假如你名字是张三,在朋友眼中,你是张三(__name__ == '张三');在你自己眼中,你是你自己(__name__ == '__main__')

     

    {{7*7}}可用来检测漏洞 

     

    模板分析

     

    python继承关系和魔术方法

    几种魔术方法

    在 python 中,魔术方法是一种两边以双下划线 __ 包裹的特殊方法,利用这些方法,我们可以实现类的寻找,初始化对象的成员,以及最后的利用。

    1. __class__# 查找当前类型的所属对象
    2. __base__# 沿着父子类的关系往上走,用来查看类的基类,注意是类的基类,所以格式为变量.__class__.__bases__,同时也能加上数组,比如变量.__class__.__bases__[0]来获得第一个基类。
    3. __mro__ # 查找当前类对象的所有继承类,显示类和基类
    4. __subclasse__()# 查找父类下的所有子类,格式变量.__class__.__bases__[0].__subclasses__()
    5. 这个类也可以加数组来查看指定的索引值,例如变量.__class__.__bases__[0].__subclasses__()[1]
    6. __init__ : 构造函数,当类被实例化时可以用它来快捷的初始化一些属性。SSTI 中可以用它获取选定子类的初始化方法。
    7. __globals__ #函数会议字典的形式返回当前对象的全部全局变量。当其在 __init__ 后使用时,即获取初始化方法的全局变量字典。这些变量可能是模块、方法、变量。
    8. __builtins__ #提供对Python的所有"内置"标识符的直接访问
    9. eval()计算字符串表达式的值
    10. popen()执行一个 shell 以运行命令来开启一个进程

    通过以上魔术方法,再配合一些系统命令,就可以构造出基本的 payload 了

    举个栗子

    1. name={{''.__class__.__mro__[-1].__subclasses__()[199].__init__.__globals__['os'].popen("ls -l /opt").read()}}

    payload 前的 '' 表示一个空字符串,类似的,还可以使用:"" 字符串 () 元组 [] 列表 {} 字典。它们都是数据类型的实例对象。

    继承关系

    在 python 中,类之间是会有继承关系的,也就是派生类(子类)与基类(父类)的关系,这可以理解为父子关系。在这个父子关系中的最高级,就是 object 。也就是说,object 是祖宗类。
    一般来说,SSTI 构造 payload 的思想,就是要通过各个数据类型 Numbers(数字)String(字符串)List(列表)Tuple(元组)Dictionary(字典) 这些子类,一直往上找到 object ,然后再通过找 object 类可以利用的子类。可以利用的子类,就是这个子类的方法(popen() eval()等方法)或属性可以利用。

    子类调用父类下的其他子类
    Python flask脚本没有办法直接执行python指令

    1. class A:pass
    2. class B(A):pass
    3. class C(B):pass
    4. class D(B):pass
    5. c=C()
    6. print(c.__class__)

    当前类C 

     

    当前类C的父类B

    print(c.__class__.__base__)

     

    父类的父类 

    print(c.__class__.__base__.__base__)

     

    层层递进 

    print(c.__class__.__base__.__base__.__base__)

     

     

    罗列所有父类关系
    C-B-A-object

    print(c.__class__.__mro__)

     B下的所有子类(数组形式)

    print(c.__class__.__base__.__subclasses__())

     

    调用子类D 

    print(c.__class__.__base__.__subclasses__()[1])

     

  • 相关阅读:
    漏洞复现-phpmyadmin_SQL注入 (CVE-2020-5504)
    IP地址冲突解决办法
    项目上线后,老板喜提法拉利
    一.基础算法
    .NET周刊【5月第4期 2024-05-26】
    wpf中的StaticResource和DynamicResource
    基于双向长短期神经网络bilstm的径流量预测,基于gru神经网络的径流量预测
    “拍视频”成为小程序的基础能力
    本地录像视频文件如何推送到视频监控平台EasyCVR进行AI视频智能分析?
    微机-------输入/输出接口(第六章)
  • 原文地址:https://blog.csdn.net/2202_75317918/article/details/133656678