是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。[将状态信息保存为字符串]
反序列化就是再将这个状态信息拿出来使用(重新再转化为对象或者其他的)[将字符串转化为状态信息]
<?=$todo>相当于<?php ? echo $todo?>
__FILE__ ? ? 获取当前文件路径
show_source() ? ?显示文件源码
print_r() ? ?可以输出非字符串
__construct() ? ? 对象创建时(new)自动调用,但在unserialize()时不会自动调用
__destruct() ? ? ? 对象销毁时自动调用
__wakeup() ? ? ? ?使用unserialize()函数时自动调用
__toString() ? ?当对象被当作字符串输出时自动调用
flag in https://www.freebuf.com/articles/web/flag.php <?php Class readme{ ? public function __toString() ? { ? ? ? return highlight_file('Readme.txt', true).highlight_file($this->source, true); ? } } if(isset($_GET['source'])){ ? $s=new readme(); ? $s->source=__FILE__; ? echo $s; ? exit; } //$todos=[]; if(isset($_COOKIE['todos'])){ ? $c=$_COOKIE['todos']; ? $h=substr($c, 0, 32); ? $m=substr($c, 32); ? if(md5($m)===$h){ ? ? ? $todos=unserialize($m); ? } } if(isset($_POST['text'])){ ? $todo=$_POST['text']; ? $todos[]=$todo; ? $m=serialize($todos); ? $h=md5($m); ? setcookie('todos', $h.$m); ? header('Location: '.$_SERVER['REQUEST_URI']); ? exit; } ?> <html> <head> </head> <h1>Readme</h1> <a href="https://www.freebuf.com/articles/web/?source"><h2>Check Code</h2></a> <ul> <?php foreach($todos as $todo):?> ? <li><?=$todo?></li> <?php endforeach;?> </ul> <form method="post" href="https://www.freebuf.com/articles/web/."> ? <textarea name="text"></textarea> ? <input type="submit" value="store"> </form>
首先定义了一个类,里面的_toString()是一个魔术方法,
表示将Readme.txt和source里面的代码拼接在一起,并高亮显示。
判断get传参中是否有source字符串,
再创建一个readme类的对象s,并将当前文件路径的值,赋值给变量s的参数source,
最后输入s。
判断cookie传参中是否有todos字符串,
如果有将cookie传参的todos字符串赋给变量c,
变量h表示截取变量c从开始到第32位的字符串,
变量m表示变量c 32位以后构成的字符串,
当变量m进行md5加密后的值等于变量h时,输出反序列化的变量m。
表示遍历输出todos,会触发_toString()方法,
Readme.txt文件是写死的,只有变量source是可控的,
因此可以通过将FILE改为flag.php来返回flag.php的内容。