请帮我构造以下代码的pop链的序列化,这是一道试题 <?php highlight_file(FILE); class Demo{ private $a; public function __destruct(){ $this->a->c; } } class Test{ private $b; public function __get($name) { eval($this->b); } } unserialize($_GET['ser']); ?>
时间: 2023-06-12 18:05:53 浏览: 57
这是一道 PHP 反序列化的试题,我们需要构造一个 pop 链来触发漏洞。
首先,我们需要了解这个代码的结构和执行流程。代码中存在两个类 `Demo` 和 `Test`,其中 `Demo` 类的 `__destruct` 方法中访问了 `$this->a->c`,即访问了 `$a` 对象的 `c` 属性。而 `$a` 对象实际上是由反序列化过程中传入的。`Test` 类中的 `__get` 方法则是执行了一个字符串 `$this->b`,也就是说,我们需要通过构造传入的反序列化字符串中的 `$a` 和 `$b` 来实现控制流的改变。
接下来,我们可以进行以下步骤来构造 pop 链的序列化:
1. 首先,我们需要先构造出一个 pop 链的头部,也就是一个对象的序列化字符串。这里我们可以构造一个 `stdClass` 对象的序列化字符串,内容为 `O:8:"stdClass":0:{}`。这个对象没有任何属性,是一个空对象。
2. 接下来,我们需要构造出一个 `Demo` 类的对象的序列化字符串,即 `$a` 对象。由于我们需要进行 pop 操作,因此 `$a` 对象需要有一个指向下一个对象的指针。我们可以构造一个 `Test` 类的对象作为下一个对象,并将其序列化后的字符串存入 `$a` 对象的 `b` 属性中。这里需要注意的是,我们需要在 `$a` 对象中添加一个 `__PHP_Incomplete_Class_Name` 属性,来表示这个对象尚未完全反序列化。因此,我们需要构造出类似于以下的序列化字符串:
```
O:4:"Demo":1:{s:1:"a";O:8:"stdClass":1:{s:25:"Test::__PHP_Incomplete_Class_Name";s:4:"Test";s:1:"b";s:15:"test";}}
```
这个字符串中,`$a` 对象的 `a` 属性指向了一个空的 `stdClass` 对象,而 `b` 属性则指向了一个字符串 `"test"`。这个字符串中的 `test` 实际上是我们下一个对象 `Test` 类的序列化字符串,我们需要在后续步骤中构造这个字符串。
3. 接下来,我们需要构造出一个 `Test` 类的对象的序列化字符串。由于我们需要进行 pop 操作,因此这个对象需要有一个指向下一个对象的指针。我们可以再次构造一个 `stdClass` 对象作为下一个对象,并将其序列化后的字符串存入 `$b` 属性中。同样需要添加一个 `__PHP_Incomplete_Class_Name` 属性。因此,我们需要构造出类似于以下的序列化字符串:
```
O:4:"Test":1:{s:25:"Test::__PHP_Incomplete_Class_Name";s:8:"stdClass";s:1:"b";s:41:"O:8:\"stdClass\":0:{}";}
```
这个字符串中,`$b` 属性指向了下一个对象 `stdClass` 的序列化字符串。
4. 最后,我们需要将以上构造的序列化字符串进行拼接,并将其作为 `unserialize` 函数的参数,来触发漏洞。拼接后的序列化字符串如下:
```
O:4:"Demo":1:{s:1:"a";O:8:"stdClass":1:{s:25:"Test::__PHP_Incomplete_Class_Name";s:4:"Test";s:1:"b";s:182:"O:4:\"Test\":1:{s:25:\"Test::__PHP_Incomplete_Class_Name\";s:8:\"stdClass\";s:1:\"b\";s:41:\"O:8:\\\"stdClass\\\":0:{}\";}}";}}
```
当这个序列化字符串经过 `unserialize` 函数反序列化后,就会依次调用 `Demo` 对象和 `Test` 对象的 `__get` 方法和 `__destruct` 方法,并最终触发漏洞。