Use the java.lang.reflect package to access and modify any field in Java objects, even when declared "private static final"
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 :
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 :
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 :
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.
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.
Thats all!