jeudi 21 juillet 2016

Completely compromise restricted access to methods in plain java using reflection - why is that possible?

I'm totally puzzled - I wrote a class in Java8 SE (less than 10 lines of code) which completely compromises restricted (private) methods using reflection. I find this is very dangerous and question the sense of reflection allowing this.

package reflection;

import java.lang.reflect.Method;
import java.util.Arrays;

public class Reflection {

    //  Throw 'Throwable' because this method must be totally transparent, doing exactly what the actually called method does:
    static public Object call(Object target, String methodName, Object... args) throws Throwable {

        // Get the arguments' classes:
        Class<?>[] argumentClasses =
                Arrays.asList(args)
                    .stream()
                    .map(object -> object.getClass())
                    .toArray(Class[]::new);

        Method method = target.getClass().getDeclaredMethod(methodName, argumentClasses);
        method.setAccessible(true);
        return method.invoke(target, args);
    }

}

You can run this tests, which calls private methods - both static and non-static - of another class, Action:

package reflection;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class ReflectionUnitTest {

    @Test
    public void testCall() throws Throwable {

        Action target = new Action();

        assertEquals("Something static done!", Reflection.call(target, "doSomethingStatic"));
        assertEquals("Something static done with something else!", Reflection.call(target, "doSomethingStatic", "something else"));
        assertEquals("Something static done 3 times with something else!", Reflection.call(target, "doSomethingStatic", 3, "something else"));
        assertEquals("Something static done 5 times with something else!", Reflection.call(target, "doSomethingStatic", "something else", 5));

        assertEquals("Something done!", Reflection.call(target, "doSomething"));
        assertEquals("Something done with something else!", Reflection.call(target, "doSomething", "something else"));
        assertEquals("Something done 3 times with something else!", Reflection.call(target, "doSomething", 3, "something else"));
        assertEquals("Something done 5 times with something else!", Reflection.call(target, "doSomething", "something else", 5));
    }

}


package reflection;

public class Action {

    static private String doSomethingStatic(){

        return "Something static done!";
    }

    private String doSomethingStatic(String argument) {

        return "Something static done with " + argument + "!";
    }

    private String doSomethingStatic(Integer count, String argument) {

        return "Something static done " + count + " times with " + argument + "!";
    }

    private String doSomethingStatic(String argument, Integer count) {

        return "Something static done " + count + " times with " + argument + "!";
    }


    private String doSomething() {

        return "Something done!";
    }

    private String doSomething(String argument) {

        return "Something done with " + argument + "!";
    }

    private String doSomething(Integer count, String argument) {

        return "Something done " + count + " times with " + argument + "!";
    }

    private String doSomething(String argument, Integer count) {

        return "Something done " + count + " times with " + argument + "!";
    }

}

My issues:

  1. To share this knowledge with you
  2. To ask if anybody can explain why this is possible




Aucun commentaire:

Enregistrer un commentaire