风炫安全Web安全学习第三十九节课 反序列化漏洞基础知识

风炫安全Web安全学习第三十九节课 反序列化漏洞基础知识

反序列化漏洞

0x01 序列化相关基础知识

0x01 01 序列化演示

序列化就是把本来不能直接存储的数据转换成可存储的数据,并且不会丢掉数据格式

序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。 在序列化期间,对象将其当前状态写入到临时或持久性存储区。 以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。 序列化使其他代码可以查看或修改,那些不序列化便无法访问的对象实例数据。

flag = $flag;
    }   

    public function get_flag($flag){
        return $this->flag;
    }

}

$object = new test();
$object->set_flag('Active');
$data = serialize($object);
echo $data;
?>

那么这种将原本的数据通过某种手段进行“压缩”,并且按照一定的格式存储的过程就可以称之为"序列化"

O:4:"test":3:{s:10:"testflag";s:6:"Active";s:7:"*test";s:4:"test";s:5:"test1";s:5:"test1";}
对象类型:长度:"类名":类中变量的个数:{类型:长度:"值";类型:长度:"值";......}

此处输入图片的描述

a - array                  b - boolean  
d - double                 i - integer
o - common object          r - reference
s - string                 C - custom object
O - class                  N - null
R - pointer reference      U - unicode string

0x01 02 php魔法方法

PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法

这里就不得不介绍几个我们必须知道的魔法方法了

__construct   当一个对象创建时被调用,
__destruct   当一个对象销毁时被调用,
__toString   当一个对象被当作一个字符串被调用。
__wakeup()   使用unserialize时触发
__sleep()    使用serialize时触发
__call()    在对象上下文中调用不可访问的方法时触发
__callStatic()    在静态上下文中调用不可访问的方法时触发
__get()    用于从不可访问的属性读取数据
__set()    用于将数据写入不可访问的属性
__isset()    在不可访问的属性上调用isset()或empty()触发
__unset()     在不可访问的属性上使用unset()时触发
__invoke()   当脚本尝试将对象调用为函数时触发

其中我想特别说明一下第四点:

这个 __toString 触发的条件比较多,也因为这个原因容易被忽略,常见的触发条件有下面几种

(1)echo ($obj) / print($obj) 打印时会触发

(2)反序列化对象与字符串连接时

(3)反序列化对象参与格式化字符串时

(4)反序列化对象与字符串进行==比较时(PHP进行==比较的时候会转换参数类型)

(5)反序列化对象参与格式化SQL语句,绑定参数时

(6)反序列化对象在经过php字符串函数,如 strlen()、addslashes()时

(7)在in_array()方法中,第一个参数是反序列化对象,第二个参数的数组中有toString返回的字符串的时候toString会被调用

varr1."
"; } public function __construct(){ echo "__construct
"; } public function __destruct(){ echo "__destruct
"; } public function __toString(){ return "__toString
"; } public function __sleep(){ echo "__sleep
"; return array('varr1','varr2'); } public function __wakeup(){ echo "__wakeup
"; } } $obj = new test(); //实例化对象,调用__construct()方法,输出__construct // $obj->echoP(); //调用echoP()方法,输出"abc" // echo $obj; //obj对象被当做字符串输出,调用__toString()方法,输出__toString $s =serialize($obj); //obj对象被序列化,调用__sleep()方法,输出__sleep echo unserialize($s); //$s首先会被反序列化,会调用__wake()方法,被反序列化出来的对象又被当做字符串,就会调用_toString()方法。 // 脚本结束又会调用__destruct()方法,输出__destruct ?>

参考:
http://blog.evalshell.com/2020/12/26/风炫安全web安全学习第三十九节课-反序列化漏洞基/

你可能感兴趣的:(风炫安全Web安全学习第三十九节课 反序列化漏洞基础知识)