Modify any Java class field using reflection.
13 January 2011 20:46 5 messages
License : Copyright Emeric Nasi, some rights reserved
This work is licensed under a Creative Commons Attribution 4.0 International License.
I. Reflection and Java security
For most Java developers, Java security comes from the use of keywords such as "private, protected, or final".
For example a field declared : private static String state;
The field called "state" is a class variable, with the given keywords, it should only be accessible by other instance objects of the same class.
Another example : private final String name="MyClass";
In this example the field "name" can only be accessed by another code in the same object, and it has the "final" keyword so it cannot be modified once it is set (a real Java constant has both the keywords "static" and "final").
These examples shows that Java data access security is guaranteed by the language keywords, however this statement is not true because of Java "reflection".
Reflection is a Java feature that allows a code to examine itself dynamically and modify its references and properties at runtime.
Reflection is a direct part of the Java language. The reflection package is java.lang.reflect. This package provides objects that can be used to list any fields inside a class, invoke any class methods or access and modify any fields, and when I say any I mean all of them, even private ones.
II. Use reflection to modify any class/object field.
II.1 Our scope
The java.lang.reflect classes allows you do do a lot more things than just access to class fields. This is just a little part of the enormous possibilities of reflection, the goal here is to show that reflection can "break" classic keyword security.
The only include that is needed for this article codes is :
import java.lang.reflect.Field;
II.2 Access and modify any class variables
A class variable is a variable that is common to all instances of this class, it is defined with the "static" keyword.
The code below can be used to access any class variable :
/** * Returns an object containing the value of any static field (even private). * @param className The complete name of the class (ex. java.lang.String) * @param fieldName The name of a static field in the class * @return An Object containing the static field value. * @throws SecurityException . * @throws NoSuchFieldException . * @throws ClassNotFoundException . * @throws IllegalArgumentException . * @throws IllegalAccessException . */ public static Object getStaticValue(final String className, final String fieldName) throws SecurityException, NoSuchFieldException, ClassNotFoundException, // Get the private field // Allow modification on the field field.setAccessible(true); // Return the Obect corresponding to the field return field.get(Class.forName(className)); }
In this code, the essential line is "field.setAccessible(true);". The setAccessible() method disables usual languages security checks and allows the field to be accessed from any other class.
Note also the getDeclaredField() method that is really useful and allows you to access via reflection to a Field object representing any field that is declared inside a Class.
We saw we could grab any field value, but can we also modify them? the answer is yes. For that you can use the next code :
/** * Use reflection to change value of any static field. * @param className The complete name of the class (ex. java.lang.String) * @param fieldName The name of a static field in the class * @param newValue The value you want the field to be set to. * @throws SecurityException . * @throws NoSuchFieldException . * @throws ClassNotFoundException . * @throws IllegalArgumentException . * @throws IllegalAccessException . */ public static void setStaticValue(final String className, final String fieldName, final Object newValue) throws SecurityException, NoSuchFieldException, // Get the private String field // Allow modification on the field field.setAccessible(true); // Get // Sets the field to the new value field.set(oldValue, newValue); }
Here, the Field.get() method is used to grab the object contained in the field. The set() method overrides this object with another Object (newValue) we passed in parameters.
II.3 Access and modify any instance variables
In the previous section we saw that we could access and modify any static field. We can do the same thing for non-static fields that is, instance variables. The example codes works basically like the previous ones except that instead of manipulating a Class, we are going to manipulate an Object, instance of the Class.
/** * Returns an object containing the value of any field of an object instance (even private). * @param classInstance An Object instance. * @param fieldName The name of a field in the class instantiated by classInstance * @return An Object containing the field value. * @throws SecurityException . * @throws NoSuchFieldException . * @throws ClassNotFoundException . * @throws IllegalArgumentException . * @throws IllegalAccessException . */ public static Object getInstanceValue(final Object classInstance, final String fieldName) throws SecurityException, NoSuchFieldException, // Get the private field // Allow modification on the field field.setAccessible(true); // Return the Obect corresponding to the field return field.get(classInstance); }
/** * Use reflection to change value of any instance field. * @param classInstance An Object instance. * @param fieldName The name of a field in the class instantiated by classInstancee * @param newValue The value you want the field to be set to. * @throws SecurityException . * @throws NoSuchFieldException . * @throws ClassNotFoundException . * @throws IllegalArgumentException . * @throws IllegalAccessException . */ public static void setInstanceValue(final Object classInstance, final String fieldName, final Object newValue) throws SecurityException, // Get the private field // Allow modification on the field field.setAccessible(true); // Sets the field to the new value for this instance field.set(classInstance, newValue); }
III. Prevent reflection
Reflection is a very powerful feature and a lot of Java frameworks use it. However, an "evil" code can also use it to break the security of your application and access and modify any field and a lot more things (invoke any methods, list all class content, etc).
The only way to prevent reflection is to use a securitymanager. By default code using reflection needs particular security permissions.
In our example, both the getDeclaredField() method and the setAccessible() method contain an inner security check that will throw a SecurityException if called by a code that is not authorized by the securitymanager.
If you want to look at some example of securitymanager that authorizes reflection for particular jars you should read the article : Spring and Hibernate Tomcat security manager.
IV. Example : Disable Java security
The best example to show that reflection is a dangerous feature is to show that all the security mechanisms of Java, relying on the security manager, can be disabled using a single call to the setStaticValue() method previously described in this article.
The entire language security of Java relies on security checks using a static value inside the java.lang.System class.
The usual security checks maid by sensible functions are :
- Test if a call to System.getSecurityManager() returns null.
- If returned value is null, the function considers security is deactivated.
- If the return value is not null, the SecurityManager element returned by the function is used to know what is authorized and what is not.
The System.getSecurityManager() method simply returns the value of a static private variable of the System class, security.
So, that means, disabling Java language security is as simple as setting the security variable to null.
setStaticValue("java.lang.System", "security", null);
Thats all!
Also in this section
8 January 2011 – Enable securitymanager for Spring and Hibernate
10 November 2010 – Implement hash service using JCE
4 Forum posts
good tool..... for changing private values:-)
Very good article..B-)
How can you possibly disable all security by calling
setStaticValue("java.lang.System", "security", null);
when this method itself uses calls to the reflection api which will be prevented by the SecurityManager (== throw SecurityException) before you manage to set it to null?
1. Modify any Java class field using reflection., 3 November 2013, 13:33, by Emeric Nasi
“show that reflection is a dangerous feature” The point was to explain that if reflection API is enabled, the security of Java can be disabled.
That is why when enabling Java security you must ensure that you do not allow reflection, especially on modules your are not sure you can trust.
how to change the order of the private data variable?