PHP序列化及常见魔术方法


每日一记

序列化

【数组序列化】
<?php
$a=null;
echo serialize($a);
?>
a:参数数量:{i:0;s:字符串长度:"字符串";}

$a=null;         N;
$b=123456;       i:123456;
$c=1.2;          d:1.2;
$d=true;         b:1;
$e=false;        b:0;
$f='benben';     s:长度:字符串;


【对象序列化】
<?php
class lei{
    public $chengyuan='zifuchuan';
    function hanshu(){
        echo $this->chengyuan;
    }
}
$a=new lei();
echo serialize($a);
echo urlencode(serialize($a));
?>
O:类名长度:"类名":1:{s:成员长度:"成员名";s:值长度:"值";}

修饰符public公有,private私有
私有的成员属性要在前后都加上二进制的%00,在urlencode时可以看见


【对象序列化的嵌套】
<?php
class test{
    public $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
class test2{
    var $ben;
}
$b=new test();
$a=new test2();
$a->ben=$b;
echo serialize($a);
?>
O:5:"test2":1:{s:3:"ben";O:4:"test":1:{s:3:"pub";s:6:"benben";}}

当在对象内调用对象时,会出现嵌套:
实例化后的对象$a的成员变量'ben'调用实例化后的对象$b

反序列化

1.反序列化后的内容为一个对象,与序列化相反
2.反序列化生成的对象内的值,由反序列化里的值提供,与原有类预定义的值无关
3.反序列化不触发类的成员方法,需要调用方法之后才能触发

<?php
class test{
    public $a='benben';
    protected $b=666;
    private $c=false;
    public function displayVar(){
        echo $this->a;
    }
}
$d=new test();
$d=serialize($d);
echo urlencode($d);
$a=urlencode($d);
$b=unserialize(urldecode($a));
$b->displayVar();
var_dump($b);
?>

benbenobject(test)#1 (3) {
  ["a"]=>
  string(6) "benben"
  ["b":protected]=>
  int(666)
  ["c":"test":private]=>
  bool(false)
}

魔术方法

概念:
预定好的,在特定的情况下处罚的行为方法。
反序列化成因(作用):
反序列化过程中unserizlize()接收的值(字符串)可控;
通过更改这个值(字符串),所得到的代码;
通过调用方法,触发代码执行。
相关机制:
触发时机(先决条件)->功能(最重要)->参数(尤其是pop链)->返回值
详解:

1.__construct()
构造函数
在实例化对象时,自动执行的方法
只有当new时触发,不需要特地调用
2.__destruct()
析构函数
在对象的所有引用都被删除或者对象被显式销毁时才触发
new和unserialize之后会触发
3.__sleep()
清理对象
可以传入成员属性,serialize之前触发
并返回一个包含对象中所有需要被序列化的变量名称的数组
如果无返回则NULL被序列化,产生E_NOTICE错误
4.__wakeup()
预先准备对象资源,返回void
在unserialize前触发
5.__tostring()
表达方式错误
把对象当成字符串调用时触发,如echo,print
6.__invoke()
格式表达错误
把对象当成函数调用时触发,如echo $a() -> hanshu
7.__call()
不存在方法
不存在调用的方法时触发
8.__callStatic()
不存在方法
静态调用或调用成员常量不存在时使用
9.__get()
不存在方法
检查成员属性是否存在
10.__set()
不存在方法
给不存在的成员属性赋值时触发
11.__isset()或__empty()或__unset()
不可访问
对不可访问的属性访问时会触发
如protect属性(不可读)或根本不存在的属性
12.__clone()
复制
使用clone关键字拷贝完成一个对象后,
新对象会自动调用定义的魔术方法__clone()

注意:
1.只有该类或对象包含了该魔术方法才能被使用或触发
2.先分析尾部代码看看有什么执行的步骤
3.接着从触发的方法及其顺序判断漏洞的利用地点
4.最后构造playload
5.比较长的代码建议使用反推法进行分析
6.一定要先实例化(new)

POP链

反序列化中成员变量可以被控制,使用有一种漏洞叫面向属性编程(POP)
POP链是利用魔术方法在里面多次跳转然后获取敏感信息的一种playload

POC编写

概念验证(POC)是漏洞验证程序,只是为了证明提出者观点的一段代码


评论
  目录