面试php反序列化、java反序列化原理和常见函数

关于反序列化,我更多的只是针对php和Java,把原理看懂了点,后面还会对反序列化进行详细总结
1.什么是序列化和反序列化?
序列化即将对象转化为字节流,便于保存在文件,内存,数据库中;反序列化即将字节流转化为对象
也就是把数据转化为一种可逆的数据结构,再把这种可逆的数据结构转化回数据,这就是序列化与反序列化

用途:
  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
  2) 在网络上传送对象的字节序列。

php反序列化:

序列化的函数:string serialize ( mixed $value )
当调用serialize()函数序列化对象时,该函数会检查类中是否存在一个魔术方法__sleep()。
如果存在,该方法会先被调用,然后才执行序列化操作。可以通过重载这个方法,从而自定义序列化行为。
该方法原型如下:
public array __sleep ( void )
该方法返回一个包含对象中所有应被序列化的变量名称的数组
该方法未返回任何内容,则 NULL 被序列化,并产生一个E_NOTICE级别的错误
__sleep()不能返回父类的私有成员的名字。这样做会产生一个E_NOTICE级别的错误。这时只能用Serializable接口来替代。
常用于保存那些大对象时的清理工作,避免保存过多冗余数据

**反序列化的函数:mixed unserialize ( string KaTeX parse error: Expected group after '_' at position 179: …之后,PHP会自动地试图去调用_̲_wakeup()成员函数(如…this->username的值不为空
反序列化时,会尽量将变量值进行匹配并复制给序列化后的对象

php的魔法函数:
  _construct() 当一个对象被创建时调用
  _destruct() 当一个对象被销毁时调用
  _toString() 当一个对象被当作一个字符串使用
  _sleep() 在对象再别序列化之前运行
  _wakeup() 将在序列化之后调用

对象注入
当用户的请求在传给反序列化函数unserialize()之前没有被正确的过滤时就会产生漏洞。
因为PHP允许对象序列化,攻击者就可以提交特定的序列化的字符串给一个具有该漏洞的unserialize函数,最终导致一个在该应用范围内的任意PHP对象注入。
对象漏洞出现得满足两个前提:
一、unserialize的参数可控。
二、 代码里有定义一个含有魔术方法的类,并且该方法里出现一些使用类成员变量作为参数的存在安全问题的函数。
例子:

<?php class A{ var $test = "demo"; function __destruct(){ echo $this->test; } } $a = $_GET['test']; $a_unser = unserialize($a); ?>

比如这个列子,直接是用户生成的内容传递给unserialize()函数,那就可以构造这样的语句
?test=O:1:“A”:1:{s:4:“test”;s:5:“lemon”;}
在脚本运行结束后便会调用_destruct函数,同时会覆盖test变量输出lemon。

java反序列化
Java中的API实现:
  位置: Java.io.ObjectOutputStream   java.io.ObjectInputStream
  序列化:  ObjectOutputStream类 --> writeObject()

        注:该方法对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中
          按Java的标准约定是给文件一个.ser扩展名
  反序列化: ObjectInputStream类 --> readObject()   
        注:该方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

1****.漏洞触发场景****
在java编写的web应用与web服务器间java通常会发送大量的序列化对象例如以下场景:
  1)HTTP请求中的参数,cookies以及Parameters。
  2)RMI协议,被广泛使用的RMI协议完全基于序列化
  4)JMX 同样用于处理序列化对象
  5)自定义协议 用来接收与发送原始的java对象

  1. 漏洞挖掘
      (1)确定反序列化输入点
        首先应找出readObject方法调用,在找到之后进行下一步的注入操作。一般可以通过以下方法进行查找:
         1)源码审计:寻找可以利用的“靶点”,即确定调用反序列化函数readObject的调用地点。
       2)对该应用进行网络行为抓包,寻找序列化数据,如wireshark,tcpdump等
        注: java序列化的数据一般会以标记(ac ed 00 05)开头,base64编码后的特征为rO0AB。
      (2)再考察应用的Class Path中是否包含Apache Commons Collections库
      (3)生成反序列化的payload
      (4)提交我们的payload数据

如何发现java反序列化漏洞
通过检索源码中对反序列化函数的调用来静态寻找反序列化的输入点
可以搜索以下函数:
ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject

在实战过程中,我们可以通过抓包来检测请求中可能存在的序列化数据。
序列化数据通常以AC ED开始,之后的两个字节是版本号,版本号一般是00 05但在某些情况下可能是更高的数字。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值