當(dāng)前位置:首頁 > IT技術(shù) > Web編程 > 正文

WEB漏洞——PHP反序列化
2021-09-13 11:30:06

序列化

首先說說什么是序列化

序列化是將某個對象轉(zhuǎn)換為以后可以恢復(fù)的數(shù)據(jù)格式的過程。 人們經(jīng)常序列化對象以將它們保存到存儲中,或作為通信的一部分發(fā)送。 反序列化與從某種格式獲取結(jié)構(gòu)化數(shù)據(jù)并將其重建為對象的過程相反。 今天,用于序列化數(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";}

?

許多編程語言提供了用于序列化對象的本機(jī)功能。 這些原生格式通常提供比 JSON 或 XML 更多的功能,包括序列化過程的可定制性。 不幸的是,在對不受信任的數(shù)據(jù)進(jìn)行操作時,這些原生反序列化機(jī)制的功能可能會被重新用于惡意影響。 已經(jīng)發(fā)現(xiàn)對解串器的攻擊允許拒絕服務(wù)、訪問控制和遠(yuǎn)程代碼執(zhí)行攻擊。
已知受影響的編程語言PHP、Python、Ruby、JAVA、C、C++

?

只有數(shù)據(jù)被序列化。 代碼本身沒有序列化。 反序列化創(chuàng)建一個新對象并從字節(jié)流中復(fù)制所有數(shù)據(jù),以獲得與序列化的對象相同的對象。

?

?

在PHP,通過反序列化在特定條件下可以重建php對象并執(zhí)行php對象中某些magic函數(shù)。

在PHP應(yīng)用中,序列化和反序列化一般用做緩存,比如session緩存,cookie等。

舉一個簡單的例子

<?php
class people{
 public $name;
 public $age;
 public $sex;
 
 function __construct($name,$age,$sex){   //_construct:創(chuàng)建對象時初始化
  $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”表示對象,6表示對象名長度為6

“people”為對象名,3表示有3個參數(shù)

“s”表示string對象

“i”表示int對象

?

反序列化輸出

$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ù)實現(xiàn)

?

PHP反序列化漏洞

原理:未對用戶輸入的序列化字符串進(jìn)行檢測,導(dǎo)致攻擊者可以控制反序列化過程,從而導(dǎo)致代碼?執(zhí)行,SQL 注入,目錄遍歷等不可控后果。在反序列化的過程中自動觸發(fā)了某些魔術(shù)方法。當(dāng)進(jìn)行?反序列化的時候就有可能會觸發(fā)對象中的一些魔術(shù)方法

序列化和反序列化本身沒有問題,但是如果反序列化的內(nèi)容是用戶可以控制的,且后臺不正當(dāng)?shù)氖褂昧薖HP中的魔法函數(shù),就會導(dǎo)致安全問題?

  1. unserialize()函數(shù)的參數(shù)可控
  2. php中有可以利用的類并且類中有魔術(shù)方法

常見的魔術(shù)方法

__construct(): 在創(chuàng)建對象時候初始化對象,一般用于對變量賦初值。

__destruct(): 和構(gòu)造函數(shù)相反,當(dāng)對象所在函數(shù)調(diào)用完畢后執(zhí)行。

__toString():當(dāng)對象被當(dāng)做一個字符串使用時調(diào)用。

__sleep():序列化對象之前就調(diào)用此方法(其返回需要一個數(shù)組)

__wakeup():反序列化恢復(fù)對象之前調(diào)用該方法

__call():當(dāng)調(diào)用對象中不存在的方法會自動調(diào)用該方法。

__get():在調(diào)用私有屬性的時候會自動執(zhí)行

__isset()在不可訪問的屬性上調(diào)用isset()或empty()觸發(fā)

__unset()在不可訪問的屬性上使用unset()時觸發(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ù)會首先檢查是否存在一個魔術(shù)方法__sleep.如果存在,__sleep()方法會先被調(diào)用,然后才執(zhí)行序列化操作。這個功能可以用于清理對象,并返回一個包含對象中所有變量名稱的數(shù)組。如果該方法不返回任何內(nèi)容,則NULL被序列化,導(dǎo)致一個E_NOTICE錯誤。

unserialize()會檢查是否存在一個__wakeup方法。如果存在,則會先調(diào)用 __wakeup方法,預(yù)先準(zhǔn)備對象數(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靶場

Releases · WebGoat/WebGoat (github.com)

分析一下源碼

?

?大概的內(nèi)容就是,用戶輸入了數(shù)據(jù),對數(shù)據(jù)進(jìn)行對象的還原,接著進(jìn)行命令執(zhí)行

?

防御

反序列化的問題是用戶參數(shù)的控制問題引起的,所以好的預(yù)防措施就是不要把用戶的輸入或者是用戶可控的參數(shù)直接放進(jìn)反序列化的操作中去。

?

?

本文摘自 :https://www.cnblogs.com/

開通會員,享受整站包年服務(wù)立即開通 >