Closed dinosn closed 1 year ago
Hi Nicolas,
again, thanks for reporting :+1:
Lets start with the second output you reported as this one is easier to resolve. The recent versions of beanshooter do not look for a specific boundname like jmxrmi
within the RMI registry, but take the first javax.management.remote.rmi.RMIServerImpl_Stub
they find. In your case, this is probably some of your self created objects. Since these target a custom address (e.g. 127.0.0.1:4444
) beanshooter attempts to connect to there. However, as the corresponding port is probably not opened, a ConnectionException
is raised. This is expected behavior. To fix this, you need to target another bound name manually e.g. by specifying --bound-name jmxrmi
The other output is more confusing to me. Seems to be an odd glassfish behavior. If I understand the exception message correctly, you are running beanshooter also from the glassfish system? Have you also tried running it from another machine against the glassfish system? It would be interesting to see whether the issue occurs only on the client side, or also when communicating with a glassfish system in general :thinking:
Hi!
Thank you for the response. All clear for the first item, the --bound-name can be used to proceed further.
For the second case, I'm running from a remote system, there is no access to the glassfish system. I have 2 similar setup of glassfish on the other end, on different ip and both of them respond the same. I will proceed with some tests using --bound-name to bind it on the correct address and revert back.
Regards, Nicolas
Quick update on this, using --bound-name jmxrmi
will cause a crash to the second system with multiple bound-names as it will also produce a crash on the case of one bound-name,
root@system:~/tools/rmi/beanshooter# java -jar beanshooter-3.0.0-jar-with-dependencies.jar enum IP 8686 --ssl --bound-name jmxrmi
[+] Checking for unauthorized access:
[+]
[-] Caught java.io.NotSerializableException while invoking the newClient method.
[-] The exception occured unexpected and was not caught by beanshooter.
[-] Please report the exception to help improving the exception handling :)
[-] StackTrace:
java.rmi.UnmarshalException: Error unmarshaling return; nested exception is:
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.sun.enterprise.admin.util.AdminLoginModule$PrincipalCallback
at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:273)
at java.rmi/sun.rmi.server.UnicastRef.invoke(UnicastRef.java:164)
at java.management.rmi/javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
at java.management.rmi/javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2105)
at java.management.rmi/javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:321)
at java.management.rmi/javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:265)
at de.qtc.beanshooter.plugin.providers.RMIProvider.getMBeanServerConnection(RMIProvider.java:68)
at de.qtc.beanshooter.plugin.PluginSystem.getMBeanServerConnectionUmanaged(PluginSystem.java:211)
at de.qtc.beanshooter.operation.EnumHelper.enumAccess(EnumHelper.java:154)
at de.qtc.beanshooter.operation.Dispatcher.enumerate(Dispatcher.java:147)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at de.qtc.beanshooter.operation.BeanshooterOperation.invoke(BeanshooterOperation.java:348)
at de.qtc.beanshooter.Starter.main(Starter.java:22)
Caused by: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.sun.enterprise.admin.util.AdminLoginModule$PrincipalCallback
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1694)
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2496)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2390)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2496)
at java.base/java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:625)
at java.base/java.lang.Throwable.readObject(Throwable.java:896)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1046)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2496)
at java.base/java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:625)
at java.base/java.lang.Throwable.readObject(Throwable.java:896)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1046)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:270)
... 15 more
Caused by: java.io.NotSerializableException: com.sun.enterprise.admin.util.AdminLoginModule$PrincipalCallback
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at java.lang.Throwable.writeObject(Throwable.java:985)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1140)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at java.lang.Throwable.writeObject(Throwable.java:985)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1140)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:396)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
[-] Cannot continue from here.
PS. rmg is working on the target by using AnTrihn gadget very well, but beanshooter has become my favorite for some time now for jmxrmi cases.
Thanks for the additional input. I will dig in the glassfish implementation of JMX to identify what is going wrong there. Probably takes some time, but I will come back to you :)
Hi @dinosn,
I finally found time to look at this issue again. As it turned out, it is a glassfish bug. I opened an issue in their repository. Here is a short summary:
GlassFish seems to use different LoginModules for login attempts with and without credentials. The LoginModule used for logins without credentials is the AdminLoginModule
. This class also contains a corresponding description:
Handles the non-username/password ways an admin user can authenticate.
Within the AdminLoginModule
, a custom callback is defined (PrincipalCallback
). In contrast to all the default callbacks that ship with Java, this custom callback is not defined serializable. Finding this information was the easy part :D The difficult was to find out where the callback is serialized, because why should the server serialize a callback? After tracing the calls in the GlassFish source for a while, I found the following definition for a CallbackHandler:
private static class AuthenticationCallbackHandler implements CallbackHandler {
private final String user;
private final char[] pass;
public AuthenticationCallbackHandler(String username, char[] password) {
user = username;
pass = password;
}
protected String getUsername() { return user; }
protected char[] getPassword() { return pass; }
@Override
public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
for (Callback callback : callbacks) {
if (callback instanceof NameCallback) {
((NameCallback) callback).setName(user);
} else if (callback instanceof PasswordCallback) {
((PasswordCallback) callback).setPassword(pass);
} else {
// TODO - Have configuration setting for throwing exception
throw new UnsupportedCallbackException(callback,
"AuthenticationCallbackHandler: Unrecognized Callback "
+ callback.getClass().getName());
}
}
}
}
As one can see, this callback handler only handles NameCallback
and PasswordCallback
. All other callbacks (including the PrincipalCallback
) cause an UnsupportedCallbackException
that contains the unsupported callback as a property. When an exception is thrown during an RMI call, the exception is usually propagated back to the caller. Since RMI communication uses serialized objects, the exception needs to get serialized for this purpose. During this serialization process PrincipalCallback
is attempted to be serialized too, which causes the exception.
I'm not totally sure whether GlassFish is going to fix that. This issue only occurs because we access the server in an incorrect way. Accessing the server with credentials works fine. Moreover, we all know that outdated RMI servers are a must have in each internal network. For this reason I will implement a workaround for the NotSerializableException
. Might also be a good opportunity to catch the UnsupportedCallbackException
, which is currently also not done :sweat_smile:
New release is coming soon :+1:
Hi,
Thank you again for the awesome toolset both beanshooter and rmg are excellent tools.
I would like to write a question regarding an issue that I'm facing over a target, the setup is an old glassfish system.
From RMG:
From Beanshooter
On a similar setup if a prior bind is issued from RMG on the service e.g.:
java -jar rmg-4.3.1-jar-with-dependencies.jar bind ip 8686 127.0.0.1:4499 my-object3 --localhost-bypass --ssl
Beanshooter will report:
Regards, Nicolas