深入剖析deserialization

发布时间:2023-05-20

在软件开发过程中,序列化和反序列化常常用于将对象转换为可在网络上传输或存储的格式。其中序列化是将对象转换为二进制数据,反序列化是将其还原为对象。这里我们将关注deserialization反序列化。

一、deserialization error

反序列化过程中可能会出现错误。例如发生对象转换错误或序列化格式错误(如尝试反序列化xml格式的数据),都会导致反序列化失败。这时我们便需要跟踪反序列化过程以寻找错误原因。一种查找方法是在程序中插入日志语句,另一种方法是借助现成的工具,如Wireshark和Fiddler等。

二、deserialization vulnerability

反序列化也可能存在安全漏洞。黑客很容易利用反序列化漏洞,从而实现远程代码执行和数据泄露这些攻击动作。一种常见的漏洞是应用程序接受并反序列化用户提交的数据,并将其传递到不受信任的代码中,这就可能导致远程代码执行攻击。另外,插入恶意对象也可能导致数据泄露漏洞。为了减少反序列化漏洞,建议在传输和存储敏感数据时要进行加密,并在反序列化过程中使用反序列化过滤器来限制类的反序列化。

import java.io.*;
import java.util.Base64;
public class SerializedObject {
  public byte[] toByteArray() {
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(this);
      return baos.toByteArray();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
  public static SerializedObject fromBase64String(String base64) {
    try {
      ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(base64)));
      return (SerializedObject) ois.readObject();
    } catch (ClassNotFoundException | IOException e) {
      throw new RuntimeException(e);
    }
  }
}

三、deserialization failed

如果反序列化失败,可能是因为缺少必需的类或包。这时我们需要检查是否已经正确配置类路径,或者手动添加需要的类和包。

import java.io.*;
public class SerializeDemo
{
   public static void main(String [] args)
   {
      Employee e = new Employee();
      e.name = "Jack";
      e.address = "Haidian, Beijing";
      e.SSN = 11122333;
      e.number = 101;
      try
      {
         FileOutputStream fileOut =
         new FileOutputStream("/tmp/employee.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in /tmp/employee.ser");
      }catch(IOException i)
      {
          i.printStackTrace();
      }
   }
}

四、deserialization error翻译

如果程序在反序列化过程中发生了错误,可以根据错误信息进行排查。在Java中,反序列化时可能会出现ClassNotFoundExceptionInvalidClassExceptionStreamCorruptedException等异常。我们可以捕获异常并输出对应的错误信息,以帮助我们找出问题所在。

五、deserialization error鹅鸭杀

针对反序列化过程中可能存在的安全漏洞,在Java中提供了一种叫“鹅鸭杀”的机制。当Java反序列化调用readObject()方法时,会首先判断待反序列化的类是否实现了Serializable接口。如果不是,则会抛出一个鹅鸭声音异常org.apache.commons.collections.functors.InvokerTransformer(反序列化机制中仅使用)。

import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class Deproxy {
        public static void main(String[] args) throws Exception {
                ObjectInputStream in = new ObjectInputStream(new FileInputStream(args[0]));
                in.readObject();
        }
}

六、serialization

与反序列化相关的还有序列化,序列化是将Java对象转化成字节流的过程,可以用于实现远程对象的传输和存储。以下示例中,我们定义了一个类并实现了序列化接口,将对象序列化并写入文件,然后再通过反序列化将其读取出来。

import java.io.*;
public class Employee implements java.io.Serializable
{
   public String name;
   public String address;
   public transient int SSN;
   public int number;
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + name + " " + address);
   }
}
import java.io.*;
public class DeserializeDemo
{
   public static void main(String [] args)
   {
      Employee e = null;
      try
      {
         FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
         ObjectInputStream in = new ObjectInputStream(fileIn);
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      }catch(IOException i)
      {
         i.printStackTrace();
         return;
      }catch(ClassNotFoundException c)
      {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + e.name);
      System.out.println("Address: " + e.address);
      System.out.println("SSN: " + e.SSN);
      System.out.println("Number: " + e.number);
    }
}

结论

综上所述,反序列化是一项重要的功能,但也存在着安全风险和错误风险。在开发中,我们需要加强对反序列化的认知并在程序设计中进行严格的防范措施以保障应用的安全性和稳定性。