1、演示 PHP 反序列化漏洞的成因
解释
该类实现了一个魔术方法 __sleep()。在 __sleep() 方法中,我们检查是否接收到名为 "cmd" 的 GET 参数,并且参数值为 "xiu"。如果满足条件,则执行系统命令 system('calc'),即运行Windows 计算器。
这段代码在 __sleep() 方法中直接执行用户传入的命令,存在非常严重的安全风险。因为它允许任意执行系统命令,可能导致恶意代码注入和远程命令执行等安全问题。
2、演示 java 类继承
public class Student extends Person{
public int score;
@Override
public void talk(){
System.out.println("Student 说话了");
}
}
解释
通过继承 Person 类,Student 类继承了 Person 类中的属性和方法,同时可以添加自己的新属性和方法,以满足特定的需求
结果
3、演示 java 方法的重写
Persion(父类)
public class Person {
public int age;
public String name;
public void talk(){
System.out.println("Person 说话了");
}
}
Student(子类)
public class Student extends Person{
public int score;
@Override
public void talk(){
System.out.println("Student 说话了");
}
Test(测试类)
public class Test {
public static void main(String[] args) {
Student stu1 = new Student();
stu1.talk();
Person p1 =new Person();
p1.talk();
}
}
输出
解释
在上述代码中,Person 是父类,Student 是子类。在子类Student 中,@Override 注解来显式地表示这是对父类中talk() 方法的重写。在 Test 类中,我们分别创建了 Student和 Person 的实例,并分别调用它们的 talk() 方法。
运行程序后,输出结果将分别是 "Student 说话了" 和"Person 说话了",说明子类中重写的方法覆盖了父类中的同名方法,实现了多态性。
4、编写 JAVA 反序列化的代码实现序列化与反序列化
Person
import java.io.ObjectInputStream;
import java.io.Serializable;
public class Person implements Serializable {
public int age;
public String name;
private void readObject(ObjectInputStream in) throws
IOException,ClassNotFoundException{
//默认的反序列化操作
in.defaultReadObject();
}
}
解释
Person 类定义了一个私有方法 readObject()。这是一个特殊的方法,在对象反序列化时会被自动调用。在该方法内部,通过调用 in.defaultReadObject() 来执行默认的反序列化操作,将对
象的状态从输入流中恢复。
Test
public class Test {
public static void main(String[] args) throws
IOException,ClassNotFoundException {
Person p = new Person();
p.age=18;
p.name="xiu";
serialize(p,"xiu.bin");
System.out.println("反序列化结果:"+deserialize("xiu.bin"));
}
解释
上述代码调用了 serialize 方法将 p 对象序列化到名为"xiu.bin" 的文件中然后,你调用了 deserialize 方法对"xiu.bin" 文件进行反序列化操作,并将结果打印出来。
5、重写 readObject 方法调用计算器,实现反序列化漏洞原理
Person
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class Person implements Serializable {
public int age;
public String name;
private void readObject(ObjectInputStream in) throws
IOException,ClassNotFoundException{
Runtime.getRuntime().exec("calc");
//默认的反序列化操作
in.defaultReadObject();
}
解释
Test
在上述代码中,定义了一个 Person 类,并让它实现了Serializable 接口。这意味着该类的对象可以被序列化和反序列化。
然而,在 Person 类中,重写了 readObject 方法,并在其中执行了 Runtime.getRuntime().exec("calc") 语句。这个语句会调用系统的计算器程序(Windows 操作系统中的 "计算器" 应用程序)。这样的操作是危险的,因为它可以让恶意代码在反序列化时在受害者的系统上执行任意命令。
import java.io.*;
public class Test {
public static void main(String[] args) throws
IOException,ClassNotFoundException {
Person p = new Person();
p.age=18;
p.name="xiu";
serialize(p,"xiu.bin");
System.out.println("反序列化结果:"+deserialize("xiu.bin"));
}
public static void serialize(Object obj, String filePath) throws
IOException {
try (FileOutputStream fileOut = new FileOutputStream(filePath);
ObjectOutputStream objectOut = new
ObjectOutputStream(fileOut)) {
objectOut.writeObject(obj);
}
}
public static Object deserialize(String filePath) throws IOException,
ClassNotFoundException {
try (FileInputStream fileIn = new FileInputStream(filePath);
ObjectInputStream objectIn = new ObjectInputStream(fileIn))
{
return objectIn.readObject();
}
}
}
解释
在 Test 类中,创建了一个 Person 对象,并设置其属性。然后调用serialize 方法将该对象序列化并保存到文件 "xiu.bin" 中。接着,通过调用 deserialize 方法从文件中读取并反序列化对象。最后,将
反序列化结果打印输出。
在 serialize 方法中,使用 FileOutputStream()函数和ObjectOutputStream 函数()将对象写入文件。在 deserialize 方法中,使用 FileInputStream 函数() 和 ObjectInputStream 函数()从文件中读取并反序列化对象。
结果
6、尝试使用代码解释什么是序列化漏洞
假设有以下的 Java 类 ExploitMe,ExploitMe 类实现了Serializable 接 口 , 表 示 它 可 以 被 序 列 化 和 反 序 列 化 。readObject 方法在反序列化该对象时会被自动调用,该方法中的Runtime.getRuntime().exec(data)将执行 data 变量中存储的命令,此处存在漏洞。攻击者可以构造一个恶意的字节 序列,将其反序列化为ExploitMe 对象,并执行恶意命令。以下是攻击者可以使用的代码:
Persion:
import java.io.Serializable;
public class ExploitMe implements Serializable {
private String data;
public ExploitMe(String data) {
this.data = data;
}
public String getData() {
return data;
}
// 当反序列化该对象时,将自动调用该方法
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
System.out.println("Executing command: " + data);
Runtime.getRuntime().exec(data);
}
}
Test:
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.ByteArrayInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Exploit {
public static void main(String[] args) throws Exception {
// 创建一个 ExploitMe 对象,其中包含恶意命令
ExploitMe maliciousObject = new ExploitMe("calc.exe");
// 将恶意对象序列化为字节序列
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new
ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(maliciousObject);
objectOutputStream.close();
byte[] serializedData = byteArrayOutputStream.toByteArray();
// 将字节序列存储到文件中,以便将其发送到目标系统
Files.write(Paths.get("malicious_data.bin"), serializedData);
// 在目标系统上反序列化恶意对象,触发恶意命令的执行
byte[] receivedData = Files.readAllBytes(Paths.get("malicious_data.bin"));
ByteArrayInputStream byteArrayInputStream = new
ByteArrayInputStream(receivedData);
ObjectInputStream objectInputStream = new
ObjectInputStream(byteArrayInputStream);
ExploitMe deserializedObject = (ExploitMe) objectInputStream.readObject();
}
}
攻击者通过序列化一个包含恶意命令的 ExploitMe 对象,并将其存储到文件中。当目标系统不安全地反序列化该文件时,恶意命令将被执行。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)