浅析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; // 返回对象的字符串表示
    }
}

六、反序列化漏洞利用要点

  1. 关键方法

    • __wakeup():反序列化时自动执行,是主要攻击入口
    • __destruct():对象销毁时执行,也是常见攻击点
  2. 利用链构造

    • 通过控制序列化数据中的属性值
    • 触发魔术方法中的危险操作(如文件操作、代码执行等)
  3. 典型利用代码

class Exploit {
    public $filename;
    public $data;
    
    function __wakeup() {
        file_put_contents($this->filename, $this->data);
    }
}

$payload = serialize(new Exploit());
unserialize($payload); // 触发文件写入操作

七、防御措施

  1. 不要反序列化不可信的输入
  2. 使用json_encode()/json_decode()替代序列化
  3. 实现严格的输入验证
  4. 对魔术方法中的敏感操作进行权限检查

通过深入理解这些魔术方法的触发条件和执行顺序,可以更好地分析和利用PHP反序列化漏洞。

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