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.17.2010
| 4254 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.)

Comments

Gervais Blaise replied on Wed, 2010/11/17 - 2:47am

Yes, of course it is a security hole. But to secure your app, you have to encrypt/hash the user password, so the "password" filed will contains the encrypted/hashed string, not the clear password. Also if you think that someone can magically intersect to your app to spoof the password, you can use a code obfuscator who will the replace the "password" field name with a strange name. So "getFiled("password")" will trhow an exception.

Roberto Lo Giacco replied on Wed, 2010/11/17 - 7:24am in response to: Gervais Blaise

I think you completely missed the point: the scurity hole is not about the password field value itself, call it firstname and the security hole is still there!
The problem depicted by the article is about the possibility to access a private field through reflection calls.

public class Something {
  private String somethingElse;
 
  public String getSomethingElse() {
    return somethingElse;
  }
}

In the previous code there is only a getter method so, unless there's some missing code and this is not the case, whenever you call the getSomethingElse() method you would expect to get a null value. If in some other class you issue the statements providen in the article (adapted to the new Something class) you could get a non null value.
The security hole is: with reflection you can manage private field values from outside a class.

Roberto Lo Giacco replied on Wed, 2010/11/17 - 7:28am

I think a SecurityManager should be in place by default, both in an enterprise and in a desktop environment, allowing eventually other tools/libraries to replace it when needed, like for Hibernate which by default uses direct field access to read/write values into your POJOs. Agreed, it's a security hole.

Robert Saulnier replied on Wed, 2010/11/17 - 9:22am in response to: Roberto Lo Giacco

The problem with having a SecurityManager by default means you'll need to supply a policy file for even trivial Java apps, like an app that reads a file. Default SecurityManagers make sense in remote apps like applets or JNLP apps. Also, once a SecurityManager is set, it cannot be replaced.

David Shah replied on Sat, 2010/11/20 - 7:51am

I got a little curious about the above code snippet and decided to give it a whirl - When attempting to access a private member variable with the getField() method, I received a "NoSuchFieldException".

Replacing getField() with getDeclaredField() will do the trick though. I just thouht I'd pass this along in case anyone wanted to experiment with the above.

Alosh Bennett replied on Mon, 2010/11/22 - 2:16am in response to: David Shah

Thanks David for pointing that out.

Comment viewing options

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