Java Reflection 3 – Avoiding access to the Private methods and fields with SecurityManager

SecurityManager is an object that defines the security policy for an application. These SecurityPolicies defines the actions that are unsafe or sensitive and any action that is not allowed by this, causes a SecurityException to be thrown.
Normally, web applets like limited applications are running with a security manager. But other applications are normally running without SecurityManager unless the applications defines one by itself.

This can be widely used in many areas like Files and System Properties, Thread control, Networking, Object serialization and many applications like restricting access to specific functions like reading/writing.

SecurityManager can be integrated in two main ways
1. By having a reference of your own SecurityMenager file.
2. Through a .policy file referenced by the VM arguments

Once the application has a reference to the SecurityManager, it can request permission to do specific things. Many classes in the standard libraries uses this. (Eg : System.exit invokes SecurityManager.checkExit to ensure that the current thread has permission to shut down the application.).

1. By having a reference of your own SecurityManager file.

In SecurityManager, each operation / group of operations has its own chckXXX() method as follows. But application doesn’t have to directly invoke any checkXXX() method and also the application will consult it iff the code said so and it won’t call it in each operation once it is intergrated.

Example :

Tester.java


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Tester {

public static void main(String[] args) throws Exception {
 Tester tester = new Tester();
 tester.reflect();
 }

public void reflect() throws Exception{
 Class testeeCls = Class.forName("security.mySecurityManager.anotherPackage.Testee");
 Constructor testeeConstructor = testeeCls.getConstructor(null);
 GeneralTestee generalTestee = (GeneralTestee) testeeConstructor.newInstance(null);
 System.out.println("reflect().generalTestee : " + generalTestee);

Field[] testeeFields = testeeCls.getDeclaredFields();

 for (int i = 0; i < testeeFields.length; i++) {
 Field testeeField = testeeFields[i];
 testeeField.setAccessible(true);
 System.out.println(testeeField.getName() + " : " + testeeField.get(generalTestee));
 }

}
}

Testee.java


import security.mySecurityManager.GeneralTestee;
import security.mySecurityManager.NewSecurityManager;

public class Testee extends GeneralTestee{

 static{
 try {
 System.setSecurityManager(new NewSecurityManager("1"));
 } catch (SecurityException se) {
 System.out.println("SecurityManager already set!");
 }
 }

 public String a = "pu_blic";
 protected String b = "pro_tected";
 String c = "de_fault";
 private String d = "pri_vate";

}

GeneralTestee.java


public class GeneralTestee {}

NewSecurityManager.java


import java.io.DataInputStream;
import java.io.IOException;
import java.security.Permission;

public class NewSecurityManager extends SecurityManager{

public NewSecurityManager(String password) {
 this.password = password;
 }

public void checkPermission(Permission perm) {
 if(perm.getName().equals("suppressAccessChecks")){
 if(!accessOK()) throw new SecurityException("You are drunk. Please go home!");
 }
 }

private boolean accessOK() {
 DataInputStream dis = new DataInputStream(System.in);
 String response;
 System.out.println("Pasword please : ");

 try {
 response = dis.readLine();
 if (response.equals(password)) return true;
 else return false;
 } catch (IOException e) {
 return false;
 }
 }

String password = null;

}

2. Through a .policy file referenced by the VM arguments

1. Create a policy file (security.policy) and grant the permission for the desired areas.

java.awt.AWTPermission
java.io.FilePermission
java.net.NetPermission
java.util.PropertyPermission
java.lang.reflect.ReflectPermission
java.lang.RuntimePermission
java.security.SecurityPermission
java.io.SerializablePermission
java.net.SocketPermission

2. Execute the file providing the following VM arguments with the .policy file path.

-Djava.security.manager -Djava.security.policy=security.policy

Example :

Tester.java


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Tester {

public static void main(String[] args) throws Exception {
 Tester tester = new Tester();
 tester.reflect();
 }

public void reflect() throws Exception{
 Class testeeCls = Class.forName("security.policyFile.anotherPackage.Testee");
 Constructor testeeConstructor = testeeCls.getConstructor(null);
 GeneralTestee generalTestee = (GeneralTestee) testeeConstructor.newInstance(null);
 System.out.println("reflect().generalTestee : " + generalTestee);

Field[] testeeFields = testeeCls.getDeclaredFields();

 for (int i = 0; i < testeeFields.length; i++) {
 Field testeeField = testeeFields[i];
 testeeField.setAccessible(true);
 System.out.println(testeeField.getName() + " : " + testeeField.get(generalTestee));
 }

}
}

Testee.java


import security.policyFile.GeneralTestee;

public class Testee extends GeneralTestee{

 public String a = "pu_blic";
 protected String b = "pro_tected";
 String c = "de_fault";
 private String d = "pri_vate";

}

GeneralTestee.java


public class GeneralTestee {}

security.policy


grant {
 permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};

Leave a comment