...
Callback methods are generally invoked from the system with full permissions. It seems reasonable to expect that malicious code needs to be on the stack in order to perform an operation, but that is not the case. Malicious code may set up objects that bridge the callback to a security checked operation. For instance, a file chooser dialog box that can manipulate the filesystem from user actions, may have events posted from malicious code. Alternatively, malicious code can disguise a file chooser as something benign while redirecting user events.
This rule guideline is an instance of 18. SEC51-JG. Minimize privileged code.
...
Code Block | ||||
---|---|---|---|---|
| ||||
public interface CallBack { void callMethod(); } class UserLookupCallBack implements CallBack { private int uid; private String name; public public UserLookupCallBack(int uid) { this.uid = uid; } private String name; public String getName() { return name; } public void callMethod() { try (InputStream fis = new FileInputStream("/etc/passwd")) { // Look up uid & assign to name } catch (IOException x) { name = null; } } } class Client { CallBack callback; public void registerCallBack(CallBack callback) { this.callback = callback; } public void doSomething() { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { callback.callMethod(); return null; } }); } public static void main(String[] args) { int uid = Integer.parseInt( args[0]); Client client = new Client(); UserLookupCallBackCallBack callBack = new UserLookupCallBack(uid); client.registerCallBack(callBack); // ... client.doSomething(); // looks up user name System.out.println("User " + uid + " is named " + callBack.getName()); } } |
Whie this code works as expected, an attacker can use it to run execute malicious code with elevated privileges using code like the following:by registering a MaliciousCallBack
instance.
Code Block |
---|
class MaliciousCallBack implements CallBack { public void callMethod() { // Code here gets executed with elevated privileges } } // ... Client client = new Client(); client.registerCallBack(new MaliciousCallBack()); client.doSomething(); // performsexecutes malicious code |
Compliant Solution
...
Code Block | ||||
---|---|---|---|---|
| ||||
class UserLookupCallBack implements CallBack { // uid and name publicfields, other code public void callMethod() { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { try (InputStream fis = new FileInputStream("/etc/passwd")) { // Look up userid & assign to UserLookupCallBack.this.name } catch (IOException x) { UserLookupCallBack.this.name = null; } return null; } }); } // ... rest of UserLookupCallBack unchanged } class Client { public void doSomething() { callback.callMethod(); } // ...rest of Client unchanged } |
...