序列化
首先說說什么是序列化
序列化是將某個(gè)對(duì)象轉(zhuǎn)換為以后可以恢復(fù)的數(shù)據(jù)格式的過程。 人們經(jīng)常序列化對(duì)象以將它們保存到存儲(chǔ)中,或作為通信的一部分發(fā)送。 反序列化與從某種格式獲取結(jié)構(gòu)化數(shù)據(jù)并將其重建為對(duì)象的過程相反。 今天,用于序列化數(shù)據(jù)的最流行的數(shù)據(jù)格式是JSON。在此之前,它是 XML。
a:4:{i:0;i:132;i:1;s:7:"Mallory";i:2;s:4:"用戶"; i:3;s:32:"b6a8b3bea87fe0e05022f8f3c88bc960";}
?
許多編程語言提供了用于序列化對(duì)象的本機(jī)功能。 這些原生格式通常提供比 JSON 或 XML 更多的功能,包括序列化過程的可定制性。 不幸的是,在對(duì)不受信任的數(shù)據(jù)進(jìn)行操作時(shí),這些原生反序列化機(jī)制的功能可能會(huì)被重新用于惡意影響。 已經(jīng)發(fā)現(xiàn)對(duì)解串器的攻擊允許拒絕服務(wù)、訪問控制和遠(yuǎn)程代碼執(zhí)行攻擊。
已知受影響的編程語言PHP、Python、Ruby、JAVA、C、C++
?
只有數(shù)據(jù)被序列化。 代碼本身沒有序列化。 反序列化創(chuàng)建一個(gè)新對(duì)象并從字節(jié)流中復(fù)制所有數(shù)據(jù),以獲得與序列化的對(duì)象相同的對(duì)象。
?
?
在PHP,通過反序列化在特定條件下可以重建php對(duì)象并執(zhí)行php對(duì)象中某些magic函數(shù)。
在PHP應(yīng)用中,序列化和反序列化一般用做緩存,比如session緩存,cookie等。
舉一個(gè)簡單的例子
<?php class people{ public $name; public $age; public $sex; function __construct($name,$age,$sex){ //_construct:創(chuàng)建對(duì)象時(shí)初始化 $this->name = $name; $this->age = $age; $this->sex = $sex; } } $people=new people("hhy",20,"boy"); echo serialize($people); ?>
輸出結(jié)果:O:6:"people":3:{s:4:"name";s:3:"hhy";s:3:"age";i:20;s:3:"sex";s:3:"boy";}
“O”表示對(duì)象,6表示對(duì)象名長度為6
“people”為對(duì)象名,3表示有3個(gè)參數(shù)
“s”表示string對(duì)象
“i”表示int對(duì)象
?
反序列化輸出
$unpeople='O:6:"people":3:{s:4:"name";s:3:"hhy";s:3:"age";i:20;s:3:"sex";s:3:"boy";}'; var_dump(unserialize($unpeople)); //輸出用var_dump函數(shù)
或者 $u=unserialize('O:6:"people":3:{s:4:"name";s:3:"hhy";s:3:"age";i:20;s:3:"sex";s:3:"boy";}'); echo $u->name,$u->age,$u->sex;
輸出結(jié)果:object(people)#2 (3) { ["name"]=> string(3) "hhy" ["age"]=> int(20) ["sex"]=> string(3) "boy" }
輸出結(jié)果:hhy20boy
?
在JAVA中由ObjectOutputStream類中的writeObject()函數(shù)和ObjectInputStream類中的readObject()函數(shù)實(shí)現(xiàn)
?
PHP反序列化漏洞
原理:未對(duì)用戶輸入的序列化字符串進(jìn)行檢測(cè),導(dǎo)致攻擊者可以控制反序列化過程,從而導(dǎo)致代碼?執(zhí)行,SQL 注入,目錄遍歷等不可控后果。在反序列化的過程中自動(dòng)觸發(fā)了某些魔術(shù)方法。當(dāng)進(jìn)行?反序列化的時(shí)候就有可能會(huì)觸發(fā)對(duì)象中的一些魔術(shù)方法
序列化和反序列化本身沒有問題,但是如果反序列化的內(nèi)容是用戶可以控制的,且后臺(tái)不正當(dāng)?shù)氖褂昧薖HP中的魔法函數(shù),就會(huì)導(dǎo)致安全問題?
- unserialize()函數(shù)的參數(shù)可控
- php中有可以利用的類并且類中有魔術(shù)方法
常見的魔術(shù)方法
__construct(): 在創(chuàng)建對(duì)象時(shí)候初始化對(duì)象,一般用于對(duì)變量賦初值。
__destruct(): 和構(gòu)造函數(shù)相反,當(dāng)對(duì)象所在函數(shù)調(diào)用完畢后執(zhí)行。
__toString():當(dāng)對(duì)象被當(dāng)做一個(gè)字符串使用時(shí)調(diào)用。
__sleep():序列化對(duì)象之前就調(diào)用此方法(其返回需要一個(gè)數(shù)組)
__wakeup():反序列化恢復(fù)對(duì)象之前調(diào)用該方法
__call():當(dāng)調(diào)用對(duì)象中不存在的方法會(huì)自動(dòng)調(diào)用該方法。
__get():在調(diào)用私有屬性的時(shí)候會(huì)自動(dòng)執(zhí)行
__isset()在不可訪問的屬性上調(diào)用isset()或empty()觸發(fā)
__unset()在不可訪問的屬性上使用unset()時(shí)觸發(fā)
<head> <meta charset="UTF-8"> </head> <?php class T{ public $test=1; function __construct(){ echo '調(diào)用了_construct<br>'; } function __destruct(){ echo '調(diào)用了_destruct<br>'; } //function __sleep(){ // echo '調(diào)用了_sleep<br>' //} function __wakeup(){ echo '調(diào)用了_wakeup<br>'; } } $t=new T(); echo $t->test; echo "<br/>"; $t1=serialize($t); echo $t1; echo "<br/>"; $t2=unserialize($t1); echo $t->test; echo "<br/>";
?
當(dāng)程序執(zhí)行前,serialize() 函數(shù)會(huì)首先檢查是否存在一個(gè)魔術(shù)方法__sleep.如果存在,__sleep()方法會(huì)先被調(diào)用,然后才執(zhí)行序列化操作。這個(gè)功能可以用于清理對(duì)象,并返回一個(gè)包含對(duì)象中所有變量名稱的數(shù)組。如果該方法不返回任何內(nèi)容,則NULL被序列化,導(dǎo)致一個(gè)E_NOTICE錯(cuò)誤。
unserialize()會(huì)檢查是否存在一個(gè)__wakeup方法。如果存在,則會(huì)先調(diào)用 __wakeup方法,預(yù)先準(zhǔn)備對(duì)象數(shù)據(jù)。
?
漏洞舉例? ? ? ?
class S{
var $test = "pikachu";
function __destruct(){
echo $this->test;
}
}
$s = $_GET['test'];
@$unser = unserialize($a);
payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
?
JAVA反序列化
WebGoat靶場(chǎng)
Releases · WebGoat/WebGoat (github.com)
分析一下源碼
?
?大概的內(nèi)容就是,用戶輸入了數(shù)據(jù),對(duì)數(shù)據(jù)進(jìn)行對(duì)象的還原,接著進(jìn)行命令執(zhí)行
?
防御
反序列化的問題是用戶參數(shù)的控制問題引起的,所以好的預(yù)防措施就是不要把用戶的輸入或者是用戶可控的參數(shù)直接放進(jìn)反序列化的操作中去。
?
?
本文摘自 :https://www.cnblogs.com/