攻防世界-unserialize3

  • 序列化与反序列化
    序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。
    简单的说,序列化是将变量转换为可保存或可传输的字符串的过程。而反序列化是在适当的时候吧这个字符串再转化成原来的变量使用。
  • 序列化后格式

布尔型
b:value
b:0 //false
b:1 //true

整数型
i:value
i:1
i:-1

字符型
s:length:"value";
s:4:"aaaa";

NULL型
N;

数组
a::{key, value pairs};
a:1:{i:1;s:1:"a";}

对象
O:<class_name_length>:"<class_name>":<number_of_properties>:{};
O:6:"person":3:{s:4:"name";N;s:3:"age";i:19;s:3:"sex";N;}

  • php的序列化
    php的序列化和反序列化由serialize()和unserialize()这两个函数来完成
    serialize()完成序列化的操作,将传入的值转换为序列化后的字符串。字符串包括属性名、属性值、属性类型和该对象对应的类名。
    serialize()函数将一个对象转换成字符串时,其返回的字符串有一定规则:
    比如:
    例:O:7:"chybeta":1:{s:4:"test";s:3:"123";}
    O代表存储的是对象(object),假如你给serialize()传入的是一个数组,那它会变成字母a。7表示对象的名称有7个字符。"chybeta"表示对象的名称(类的名称)。1表示有一个属性。{s:4:"test";s:3:"123";}中,s表示字符串,4表示该字符串的长度,"test"为字符串的名称,之后的类似
    例:O:4:"xctf":1:{s:4:"flag";s:3:"111";}
    表示序列化的是一个对象。对象所在类名是"xctf"、类名的长度为4,该对象有一个属性。花括号内就是属性的具体内容。属性名为一个长度为4的字符串"flag"、该属性值为一个长度为3的字符串"111"
    注意:
    ① 当属性为private属性时,它会在两侧加入空字节,导致其长度会增加2
    ② 序列化对象时只会序列化对象中的属性值,不会序列化其中的函数
    ③Public属性序列化后格式:成员名
    ④Privatea属性序列化后格式:%00类名%00成员名
    ⑤Protect属性序列化后的格式:%00*%00成员名
    (%00代表终止符)

  • Magic function
    php中有一类特殊的方法叫“Magic function”, 这里我们着重关注一下几个:

    构造函数__construct():当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的。
    析构函数__destruct():当对象被销毁时会自动调用。
    __wakeup() :如前所提,unserialize()时会自动调用。

  • php的反序列化
    与 serialize() 对应的,unserialize()而unserialize()完成反序列化的操作,将字符串转换成原来的变量。
    当使用 unserialize() 恢复对象时, 将调用 __wakeup() 成员函数。

  • PHP反序列化漏洞
    php反序列化漏洞又称对象注入,可能会导致注入,远程代码执行等安全问题的发生
    php反序列化漏洞如何产生:
    如果一个php代码中使用了unserialize函数去调用某一类,该类中会自动执行一些自定义的魔法方法,这些魔法方法中如果包含了某一些危险的操作,或者这些魔法方法回去调用类中带有危险操作的函数,如果这些危险操作时我们可控的,那么就可以进行一些不可描述的操作了

    打开靶机,发现一段代码,__wakeup()会直接退出然后返回bad request,下面?code=提示我们可以用url绕过__wakeup()
    查资料知:当序列化字符串当中属性个数值大于实际的属性个数时,就会导致反序列化异常,从而跳过__wakeup函数
    这里我们写一段php代码,先将原来代码序列化

<?php
class xctf
{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$a = new xctf();
$b = serialize($a);
echo $b;
?>

得到
O:4:"xctf":1:{s:4:"flag";s:3:"111";}
将1改成大于一个任意数字

得到flag

posted @ 2022-04-28 16:25  -ro0t  阅读(337)  评论(0)    收藏  举报