[ https://issues.apache.org/jira/browse/COLLECTIONS-580?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15003912#comment-15003912 ]
Karsten Klein edited comment on COLLECTIONS-580 at 11/13/15 12:16 PM: ---------------------------------------------------------------------- We (not having seen the attached patch before) have come up with the following solution: {code} /** * Transforms the input to result by invoking a method on the input. * * @param input the input object to transform * @return the transformed result, null if null input */ public Object transform(Object input) { if (input == null) { return null; } if (deserialized) { throw new IllegalStateException("Transformation on deserialized object not supported. " + "Using this function may indicate an attempted SECURITY BREACH."); } try { Class cls = input.getClass(); Method method = cls.getMethod(iMethodName, iParamTypes); return method.invoke(input, iArgs); } catch (NoSuchMethodException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist"); } catch (IllegalAccessException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); } catch (InvocationTargetException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex); } } private transient boolean deserialized = false; private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); deserialized = true; } {code} This approach is the most non-invasive and 'compatible' approach. It will only fail if transform is invoked on a deserialized object. In particular it does not fail at deserialization time. Only when the transform method is invoked. This may reduce the effects of the change. was (Author: karsten.kl...@gmail.com): We (not having seen the attached patch before) have come up with the following solution: {code} /** * Transforms the input to result by invoking a method on the input. * * @param input the input object to transform * @return the transformed result, null if null input */ public Object transform(Object input) { if (input == null) { return null; } if (deserialized) { throw new IllegalStateException("Transformation on deserialized object not supported. " + "Using this function may indicate an attempted SECURITY BREACH."); } try { Class cls = input.getClass(); Method method = cls.getMethod(iMethodName, iParamTypes); return method.invoke(input, iArgs); } catch (NoSuchMethodException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist"); } catch (IllegalAccessException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); } catch (InvocationTargetException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex); } } private transient boolean deserialized = false; private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); deserialized = true; } {code} This approach is the most non-invasive and 'compatible' approach. It will only fail if transform is invoked on a deserialized object. > Arbitrary remote code execution with InvokerTransformer > ------------------------------------------------------- > > Key: COLLECTIONS-580 > URL: https://issues.apache.org/jira/browse/COLLECTIONS-580 > Project: Commons Collections > Issue Type: Bug > Affects Versions: 3.0, 4.0 > Reporter: Philippe Marschall > Attachments: COLLECTIONS-580.patch > > > With {{InvokerTransformer}} serializable collections can be build that > execute arbitrary Java code. > {{sun.reflect.annotation.AnnotationInvocationHandler#readObject}} invokes > {{#entrySet}} and {{#get}} on a deserialized collection. If you have an > endpoint that accepts serialized Java objects (JMX, RMI, remote EJB, ...) you > can combine the two to create arbitrary remote code execution vulnerability. > I don't know of a good fix short of removing {{InvokerTransformer}} or making > it not Serializable. Both probably break existing applications. > This is not my research, but has been discovered by other people. > https://github.com/frohoff/ysoserial > http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/ -- This message was sent by Atlassian JIRA (v6.3.4#6332)