java反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
import java.io.*;
class CanSerializable implements java.io.Serializable { public String first_name; public String last_name;
public void sayhello() { System.out.println(this.first_name + " " + this.last_name); }
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject();
Runtime.getRuntime().exec("spotify"); } }
public class un_serializaable { public static void main(String[] args) throws IOException, ClassNotFoundException { CanSerializable testClass = new CanSerializable(); testClass.first_name = "harry"; testClass.last_name = "smith";
FileOutputStream fos = new FileOutputStream("test.ser"); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(testClass); os.close(); fos.close();
CanSerializable obj = null; FileInputStream fis = new FileInputStream("test.ser"); ObjectInputStream ois = new ObjectInputStream(fis); obj = (CanSerializable) ois.readObject(); ois.close(); fis.close();
System.out.println(obj.first_name); System.out.println(obj.last_name); } }
|
反序列化必须有两个条件:
- 该类必须实现 java.io.Serializable 接口
- 该类的所有属性必须是可序列化的
windows弹个计算器,我就弹个spotify吧
Java RMI调用及其漏洞
RMI就是远程调用,RMI(Remote Method Invocation):一种用于实现远程过程调用的应用程序编程接口,常见的两种接口实现为 JRMP(Java Remote Message Protocol ,Java 远程消息交换协议)以及 CORBA。
实现的具体方式就是通过服务端注册Server然后由客户端调用,demo实现如下
目录结构
RMIServer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package server;
import service.Hello; import service.impl.HelloImpl; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject;
public class RMIServer { public static void main(String[] args) throws Exception { String name = "hello"; Hello hello = new HelloImpl();
UnicastRemoteObject.exportObject(hello, 1099);
Registry registry = LocateRegistry.createRegistry(1099);
registry.rebind(name, hello); } }
|
RMIClient.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package client;
import service.Hello; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.Scanner;
public class RMIClient { public static void main(String[] args) throws Exception { Registry registry = LocateRegistry.getRegistry("localhost", 1099); String name = "hello";
Hello hello = (Hello) registry.lookup(name); while (true) { Scanner sc = new Scanner(System.in); String message = sc.next();
hello.echo(message); if (message.equals("quit")) { break; } } } }
|
Hello.java
1 2 3 4 5 6 7 8 9
| package service;
import java.rmi.Remote; import java.rmi.RemoteException;
public interface Hello extends Remote { public String echo(String message) throws RemoteException; }
|
helloImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package service.impl; import service.Hello; import java.rmi.RemoteException;
public class HelloImpl implements Hello { @Override public String echo(String message) throws RemoteException { if("quit".equalsIgnoreCase(message.toString())){ System.out.println("Server will be shutdown!"); System.exit(0); } System.out.println("Message from client: " + message); return "Server response:" + message; } }
|
往RMIClient
命令行输入字符
RMIServer收到消息
demo结束
和反序列化有什么关系?
因为RMI 在传输数据的时候,会将数据序列化,在传输完成后再进行反序列化。客户端提供构造好的恶意数据,服务器端接收后进行反序列化触发代码执行。
- 能够进行 RMI 通信
- 服务器引用第三方存在反序列化漏洞的包
挖个坑,之后研究下RMI的反序列化
参考师傅的文章Jckling’s Blog