ThinkPHP RCE漏洞分析合集

更多黑客技能 公众号:暗网黑客

作者:掌控安全-veek

一. ThinkPHP 5.0.10-3.2.3 缓存函数设计缺陷可导致代码执行

0x00 背景

网站为了提高访问效率往往会将用户访问过的页面存入缓存来减少开销。

而Thinkphp 在使用缓存的时候是将数据序列化,然后存进一个 php 文件中,这使得命令执行等行为成为可能。

0x01 实验环境

系统环境

服务器主机:centOS 7

php 5.4版本,apache2,ThinkPHP 5.0.10

0x02 漏洞利用

将 application/index/controller/Index.php 文件中代码更改如下:

 <?php
 namespace app\index\controller;
 use think\Cache;
 class Index
 {
   
 public function index()
 {
   
 Cache::set("name",input("get.username"));
 return 'Cache success';
 }
 }


访问 http://localhost/tpdemo/public/?username=xxx%0d%0aphpinfo();//,即可将 webshell 等写入缓存文件。
在这里插入图片描述
在这里插入图片描述

0x03 漏洞分析

首先,查看缓存调用的方法
图片

跟进set方法,可见此处动态实例化了一个类
图片

从这个代码中我们可以看出来,这里获取外部一个配置的数组然后传
进了方法,而默认的cache.type为“File”,这个方法会根据我们的配置数据来动态的调用类执行不同的缓存操作

图片

查看connect函数,这里通过一系列判断,根据cache.type的值,找到cache驱动为File,对应44行的think\cache\driver\File类。然后在51行进行实例化,并将其return。
图片

跟进到file类的set函数,可以看到 data 数据没有经过任何处理,只是序列化后拼接存储在文件中,这里的 $this->options[‘data_compress’] 变量默认情况下为 false ,所以数据不会经过 gzcompress 函数处理。虽然在序列化数据前面拼接了单行注释符 // ,但是我们可以通过注入换行符绕过该限制。
图片

最后查看一下文件名的生成方法,可以看到文件名是通过调用 getCacheKey 方法获得的。
缓存文件的子目录和文件名均和缓存类设置的键有关(如本例中缓存类设置的键为 name )。
程序先获得键名的 md5 值,然后将该 md5 值的前 2 个字符作为缓存子目录,后 30 字符作为缓存文件名。
如果应用程序还设置了前缀 $this->options[‘prefix’] ,那么缓存文件还将多一个上级目录。
图片

总结一下,在源码中找到Cache::set(name, value, expire),其中缓存文件名是跟name相关联的,因此可以看作是一个已知条件。

漏洞的关键点就是是否开启缓存,value是否可控。

0x04 修复方案

从重现过程可以看出,在缓存文件里攻击者通过换行写入了恶意代码。可以参考引用文章中的修复方法:

1,打开文件:thinkphp\library\think\cache\driver\File.php
2,找到:public function set($name, $value, e x p i r e = n u l l ) 方 法 3 , 添 加 : expire = null) 方法 3,添加: expire=null)3data = str_replace(PHP_EOL, ”, $data); 即去掉换行。

0x05 参考资料

[ThinkPHP 5.0.10-3.2.3 缓存函数设计缺陷可导致 Getshell]
Thinkphp缓存函数设计缺陷getshell漏洞重现及分析

二. ThinkPHP 5.x 变量覆盖导致的文件包含&任意代码执行

0x00 背景

影响版本:5.0.0<=ThinkPHP5<=5.0.18 、5.1.0<=ThinkPHP<=5.1.10。

ThinkPHP在加载模版解析变量时存在变量覆盖的问题,且没有对 $cacheFile 进行相应的消毒处理,导致模板文件的路径可以被覆盖,从而导致任意文件包含漏洞的发生。

0x01 漏洞复现

环境:centOS 7, php 5.4, ThinkPHP 5.0.10

首先将 application/index/controller/Index.php 文件代码设置如下:

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
   
 public function index()
 {
   
 $this->assign(request()->get());
 return $this->fetch(); 
 }
}

创建 application/index/view/index/index.htm

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值