加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 运营中心 > 建站资源 > 策划 > 正文

PHP反序列化漏洞简介及相关技巧小结

发布时间:2019-08-12 15:30:31 所属栏目:策划 来源:xiaopan233
导读:要学习PHP反序列漏洞,先了解下PHP序列化和反序列化是什么东西。 php程序为了保存和转储对象,提供了序列化的方法,php序列化是为了在程序运行的过程中对对象进行转储而产生的。序列化可以将对象转换成字符串,但仅保留对象里的成员变量,不保留函数方法。
副标题[/!--empirenews.page--]

要学习PHP反序列漏洞,先了解下PHP序列化和反序列化是什么东西。

php程序为了保存和转储对象,提供了序列化的方法,php序列化是为了在程序运行的过程中对对象进行转储而产生的。序列化可以将对象转换成字符串,但仅保留对象里的成员变量,不保留函数方法。

php序列化的函数为serialize。反序列化的函数为unserialize。

序列化

举个栗子:

  1. <?php  
  2. class Test{  
  3.          public$a = 'ThisA';  
  4.          protected$b = 'ThisB';  
  5.          private$c = 'ThisC';  
  6.          publicfunction test1(){  
  7.                   return'this is test1 ';  
  8.          }  
  9. }  
  10. $test = new Test();  
  11. var_dump(serialize($test));  
  12. ?> 

输出:

PHP反序列化漏洞简介及相关技巧小结

解释一下:

O代表是对象;:4表示改对象名称有4个字符;:”Test”表示改对象的名称;:3表示改对象里有3个成员。

接着是括号里面的。我们这个类的三个成员变量由于变量前的修饰不同,在序列化出来后显示的也不同。

第一个变量a序列化后为 s:1:”a”;s:5:”ThisA”;

由于变量是有变量名和值的。所以序列化需要把这两个都进行转换。序列化后的字符串以分号分割每一个变量的特性。

这个要根据分号来分开看,分号左边的是变量名,分号右边的是变量的值。

先看左边的。其实都是同理的。s表示是字符串,1表示该字符串中只有一个字符,”a”表示该字符串为a。右边的同理可得。

第二个变量和第一个变量有所不同,多了个乱码和 * 号。这是因为第一个变量a是public属性,而第二个变量b是protected属性,php为了区别这些属性所以进行了一些修饰。这个乱码查了下资料,其实是 %00(url编码,hex也就是0×00)。表示的是NULL。所以protected属性的表示方式是在变量名前加个%00*%00

第三个变量的属性是private。表示方式是在变量名前加上%00类名%00

可以看到虽然Test类中有test1这个方法,但是序列化后的字符串中并没有包含这个方法的信息。所以序列化不保存方法。

反序列化

  1. <?php 
  2.  
  3. class Test{ 
  4.  
  5.          public$a = 'ThisA'; 
  6.  
  7.          protected$b = 'ThisB'; 
  8.  
  9.          private$c = 'ThisC'; 
  10.  
  11.          publicfunction test1(){ 
  12.  
  13.                   return'this is test1 '; 
  14.  
  15.          } 
  16.  
  17.  
  18. $test = new Test(); 
  19.  
  20. $sTest = serialize($test); 
  21.  
  22. $usTest = unserialize($sTest); 
  23.  
  24. var_dump($usTest); 
  25.  
  26. ?> 

输出:

image.png

可以看到类的成员变量被还原了,但是类方法没有被还原,因为序列化的时候就没保存方法。

魔术方法

大概了解了php序列化和序列化的过程,那么就来介绍一下相关的魔术方法。

  • construct 当一个对象创建时被调用
  • destruct 当一个对象销毁时被调用
  • toString 当一个对象被当作一个字符串使用
  • sleep 在对象被序列化之前运行
  • wakeup 在对象被反序列化之后被调用

直接举栗子吧:

  1. <?php 
  2. classTest{ 
  3.          public function __construct(){ 
  4.                   echo 'construct run'; 
  5.          } 
  6.          public function __destruct(){ 
  7.                   echo 'destruct run'; 
  8.          } 
  9.          public function __toString(){ 
  10.                   echo 'toString run'; 
  11.          } 
  12.          public function __sleep(){ 
  13.                   echo 'sleep run'; 
  14.          } 
  15.          public function __wakeup(){ 
  16.                   echo 'wakeup run'; 
  17.          } 
  18. /**/ 
  19. echo'new了一个对象,对象被创建,执行__construct</br>'; 
  20. $test= new Test(); 
  21. /**/ 
  22. echo'</br>serialize了一个对象,对象被序列化,先执行__sleep,再序列化</br>'; 
  23. $sTest= serialize($test); 
  24. /**/ 
  25. echo'</br>unserialize了一个序列化字符串,对象被反序列化,先反序列化,再执行__wakeup</br>'; 
  26. $usTest= unserialize($sTest); 
  27. /**/ 
  28. echo'</br>把Test这个对象当做字符串使用了,执行__toString</br>'; 
  29. $string= 'hello class ' . $test; 
  30. /**/ 
  31. echo'</br>程序运行完毕,对象自动销毁,执行__destruct</br>'; 
  32. ?> 

输出:

image.png

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读