浅析PHP反序列化漏洞之PHP常见魔术方法(一)
字数 1175 2025-08-29 08:31:53
PHP反序列化漏洞之常见魔术方法详解
一、魔术方法概述
PHP中的魔术方法是以双下划线__开头的方法,它们在特定情况下会被自动调用。这些方法在反序列化漏洞利用中扮演着重要角色。
二、构造与析构方法
1. __construct()
- 作用:在创建对象时自动调用的构造方法
- 特点:
- 最先执行的方法
- 用于初始化对象属性
class test {
function __construct($filename, $data) {
$this->filename = $filename;
$this->data = $data;
echo 'construct function in test class';
}
}
$a = new test('test.txt', 'data');
2. __destruct()
- 作用:在对象销毁时自动调用的析构方法
- 特点:
- 最后执行的方法
- 常用于资源释放、文件操作等
class test {
function __destruct() {
echo 'destruct function in test class';
}
}
三、属性重载方法
1. __set()
- 触发条件:给不可访问或不存在的属性赋值时调用
- 参数:
$key(属性名),$value(属性值)
2. __get()
- 触发条件:读取不可访问或不存在的属性时调用
- 参数:
$key(属性名)
3. __isset()
- 触发条件:对不可访问或不存在的属性调用
isset()或empty()时 - 参数:
$key(属性名)
4. __unset()
- 触发条件:对不可访问或不存在的属性调用
unset()时 - 参数:
$key(属性名)
class test {
private $data = array();
function __set($key, $value) {
$this->data[$key] = $value;
}
function __get($key) {
return $this->data[$key] ?? null;
}
function __isset($key) {
return isset($this->data[$key]);
}
function __unset($key) {
unset($this->data[$key]);
}
}
四、方法重载方法
1. __call()
- 触发条件:调用不可访问或不存在的方法时
- 参数:
$funcname(方法名),$args(参数数组)
2. __callStatic()
- 触发条件:调用不可访问或不存在的静态方法时
- 参数:
$funcname(方法名),$args(参数数组)
class test {
function __call($funcname, $args) {
echo "Called $funcname with args: ".implode(', ', $args);
}
static function __callStatic($funcname, $args) {
echo "Static called $funcname with args: ".implode(', ', $args);
}
}
五、序列化相关方法
1. __sleep()
- 触发条件:在对象被序列化(
serialize())时调用 - 作用:返回需要被序列化的属性名数组
- 用途:清理或选择需要保存的数据
2. __wakeup()
- 触发条件:在对象被反序列化(
unserialize())时调用 - 用途:常用于重新建立数据库连接或执行其他初始化操作
- 漏洞利用:反序列化漏洞的关键切入点
class test {
function __sleep() {
return ['filename', 'data']; // 指定需要序列化的属性
}
function __wakeup() {
// 反序列化后执行的操作
// 漏洞利用常在此处构造恶意代码
}
}
3. __toString()
- 触发条件:当对象被当作字符串使用时
- 用途:定义对象的字符串表示形式
- 漏洞利用:常用于触发其他魔术方法或执行代码
class test {
function __toString() {
return $this->data; // 返回对象的字符串表示
}
}
六、反序列化漏洞利用要点
-
关键方法:
__wakeup():反序列化时自动执行,是主要攻击入口__destruct():对象销毁时执行,也是常见攻击点
-
利用链构造:
- 通过控制序列化数据中的属性值
- 触发魔术方法中的危险操作(如文件操作、代码执行等)
-
典型利用代码:
class Exploit {
public $filename;
public $data;
function __wakeup() {
file_put_contents($this->filename, $this->data);
}
}
$payload = serialize(new Exploit());
unserialize($payload); // 触发文件写入操作
七、防御措施
- 不要反序列化不可信的输入
- 使用
json_encode()/json_decode()替代序列化 - 实现严格的输入验证
- 对魔术方法中的敏感操作进行权限检查
通过深入理解这些魔术方法的触发条件和执行顺序,可以更好地分析和利用PHP反序列化漏洞。