0%

Java反序列化(1)

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
/*
* @Author: harry
* @Date: 2021-11-04 19:09:14
* @LastEditTime: 2021-11-04 19:22:01
* @LastEditors: harry
* @Description: edited by harry
* @FilePath: /java_tmp/un_serializaable.java
* @E-mail: lycshub@gmail.com
*/
import java.io.*;

//定义一个可序列化的类,该类必须实现 java.io.Serializable 接口
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);
}

// 自定义 readObject 方法
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
// 执行默认的readObject()方法
in.defaultReadObject();

// 执行命令,windows弹计算机我就弹个spotify吧
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);
}
}

反序列化必须有两个条件:

  1. 该类必须实现 java.io.Serializable 接口
  2. 该类的所有属性必须是可序列化的

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;
//RMI服务端,用于把本机信息绑定到服务端并且注册服务
public class RMIServer {
public static void main(String[] args) throws Exception {
String name = "hello";
Hello hello = new HelloImpl();

// 生成存根(Stub)
UnicastRemoteObject.exportObject(hello, 1099);

// 创建本机 1099 端口上的 RMI registry
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;
}
// sc.close();
}
}
}

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;
//实现hello类的接口
public class HelloImpl implements Hello {
@Override
public String echo(String message) throws RemoteException {
//如果用户输入quit就关闭服务器RMIServer
if("quit".equalsIgnoreCase(message.toString())){
System.out.println("Server will be shutdown!");
System.exit(0);
}
//非quit的字符直接打印在终端
System.out.println("Message from client: " + message);
return "Server response:" + message;
}
}

RMIClient命令行输入字符

RMIServer收到消息

demo结束

和反序列化有什么关系?

因为RMI 在传输数据的时候,会将数据序列化,在传输完成后再进行反序列化。客户端提供构造好的恶意数据,服务器端接收后进行反序列化触发代码执行。

  • 能够进行 RMI 通信
  • 服务器引用第三方存在反序列化漏洞的包

挖个坑,之后研究下RMI的反序列化

参考师傅的文章Jckling’s Blog