Alosh Bennett is a passionate programmer and has been working on various java technologies since 2002. He is an ardent believer and promoter of the FOSS cause and is interested in RESTful architectures, web development and scripting languages. He is currently employed with Oracle Corporation. Alosh is a DZone MVB and is not an employee of DZone and has posted 6 posts at DZone. You can read more from them at their website. View Full User Profile

Reflection and the Missing Security Manager

11.30.2010
| 4593 views |
  • submit to reddit

Here’s an interesting trick that’s been around for a long time: Consider the Person class here, with password as a private data member.

public class Person {

private String name;
private String password;

public String getName() {
return name;
}

public boolean login(String password) {
if(this.password(equals(password)) {
....
}
}
...
}

The Java scope rules do not allow me to access or modify the password field that’s declared private. All the same, I could do it using reflection as shown below:

   Person person = db.queryPerson("alosh");
//System.out.println("password: "+person.password); -- won't compile

Field field = person.getClass().getField("password");
field.setAccessible(true);
System.out.println("password: "+field.get(person));
field.set(person, "welcome");
person.login("welcome");
...

It all boils down to this line of code.

   field.setAccessible(true);

All reflection access to an object (methods, fields, constructors) is through the interface AccessibleObject which lets the reflected object suppress the normal access controls. By setting the access flag, the reflected object is now open.
But the access flags are not flipped before it checks with the security manager. Reflection and SecurityManager together provides the power to control access dynamically.

Our little trick could then be attributed to the SecurityManager. Or like in this case, the lack of a SecurityManager.

By default the JVM does not have a SecurityManager available. A security manager could be installed either by passing the following option to the jvm

-Djava.security.manager

or by setting one in the code

System.setSecurityManager(new SecurityManager());

(Now the snippet mentioned in the beginning will not work.)

* SecurityManager is not enabled by default in the JVM.
* Majority of the JEE servers out there don’t run a SecurityManager unless asked for.
* Many applications would not run with SecurityManager in place.

Isn’t it against Java’s principle of ‘Secure by Default’?

From http://www.aloshbennett.in/weblog/2010/java/reflection-and-the-missing-security-manager/

Published at DZone with permission of Alosh Bennett, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Balázs Bessenyei replied on Tue, 2010/11/30 - 5:40pm

Java applets by default have a SecurityManager installed so the above code will fail. 

In other cases, if the attacker managed to run code on your application server you already have more trouble than "enabled" reflections.

Also several frameworks are using reflections to get to non public data fields, like ORM mapping frameworks. Even spring with it @resource annotations. In case of no byte code engineering library is present. 

If such library present, then it is possible to dynamically generate new derived class, which will grant the code access to those fields without reflection, in a significantly more performant way.
You can protect yourself against this by making the class final, but a non standard classloader can ignore this restriction as well. Some of the mocking frameworks are employing such classloaders. Again, security manager can help here by preventing the load of such classloaders.

However coming up with security manager that allow only the necessary frameworks related code to use such advanced features is difficult at best.

So in short, don`t let untrusted code run on the app server and you shouldn`t have to worry about this. If such code can run a security manager won`t do you much good.

darryl west replied on Tue, 2010/11/30 - 11:52pm

Good points.  My suggestion would be to NEVER keep a password, especially as a string, in a data model object.  the only place passwords should exist are as transient variables that need to be sent from client to server.   And hopefully, any transfers would be hashed and base64 encoded at a minimum, and sent only over https.

 The use of passwords as Strings also has other potential security concerns.  That's why JPassword only returns a char[] rather than a string.  in any case, it's best to keep it well away from any type of POJO or value object.

Gervais Blaise replied on Wed, 2010/12/01 - 2:56am

Alosh Bennett replied on Wed, 2010/12/01 - 7:50am in response to: Gervais Blaise

I didn't. Repost came via MVB :-)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.