 
                            A callback passes executable code as an argument to a method that is required to call back and execute that code when an interesting event occurs. Callbacks are commonly used in object-oriented programming languages. Java uses callbacks for life cycle events of applets and servlets, AWT and Swing event notifications such as button clicks, asynchronously reading and writing data from storage and even in Runnable.run() wherein a new thread automatically executes the specified run() method.
In Java, callbacks are widely implemented using interfaces. The general structure of a callback is as follows.
public interface CallBack {
  void callMethod();
}
 
class CallBackImpl implements CallBack {
    public void callMethod() {
        System.out.println("Callback called");
    }
}
 
class Client {
    public void register(CallBack callback) {
        callback.callMethod();
    }
    public static void main(String[] args) {
        Client client = new Client();
        CallBack callBack = new CallBackImpl();
        client.register(callBack);
    }
} 
Frequently, callback methods are given full privileges which can make them lucrative targets. If these methods accept arguments from untrusted code, privilege escalation may occur.
According to Oracle's Secure Coding Guidelines [SCG 2010]:
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.
Noncompliant Code Example
This noncompliant code example uses a CallBackImpl class that implements the CallBack interface. The securityCritical() method accepts a privileged action that is used by its implementation as an argument to a doPrivileged block.
public interface CallBack {
  void securityCritical(PrivilegedAction<String> action);
}
 
class CallBackImpl implements CallBack {
  public void securityCritical(PrivilegedAction<String> action) {
    AccessController.doPrivileged(action);        
  }
}
 
class Client {
  public void register(CallBack callback) {
    callback.securityCritical(new MaliciousUserLookupAction(7));
  }
  public static void main(String[] args) {
    Client client = new Client();
    CallBack callBack = new CallBackImpl();
    client.register(callBack);
  }
} 
The class Client allows registering the callback so that an untrusted caller can specify the user id to look-up. An object of type UserLookupAction  is expected by the callback, however, an attacker may extend that class and replace it with a malicious implementation in the form of a MaliciousUserAction instance.
public class UserLookupAction implements PrivilegedAction<String> {
  private int userid;
 
  public UserLookupAction(int userid) {
    this.userid = userid;
  }
 
  public String run() {
    String name = null;
    try (InputStream fis = new FileInputStream("/etc/passwd")) {
      // Look up userid & assign to name
    } catch (IOException x) {
      name = null;
    }
    return name;
  }
}
 
class MaliciousUserLookupAction extends UserLookupAction {
  public MaliciousUserLookupAction(int userid) {
    super(userid);
  }
  public String run() {
    System.out.println("Executing untrusted code");
    return null;
  }
}
Consequently, the malicious code will execute with privileges of the class CallBackImpl that defines the callback in securityCritical() method.
Compliant Solution
According to Oracle's secure coding guidelines [SCG 2010]:
By convention, instances of
PrivilegedActionandPrivilegedExceptionActionmay be made available to untrusted code, butdoPrivilegedmust not be invoked with caller-provided actions.
This compliant solution amends the CallBack interface and instead of accepting the PrivilegedAction objects, the securityCritical() methods accepts the user id to be searched for. The code contained within the UserLookupAction class is moved to the securityCritical() method.
public interface CallBack {
  void securityCritical(int uid);
}
 
class CallBackImpl implements CallBack {
  public void securityCritical(int uid) {
    AccessController.doPrivileged(new PrivilegedAction<String>() {
      public String run() {
        String name;
        try (InputStream fis = new FileInputStream("/etc/passwd")) {
          // Look up userid & assign to name
        } catch (IOException x) {
          name = null;
        }
         return name;
      }
    });        
  }
}
 
class Client {
  public void register(CallBack callback) {
    callback.securityCritical(7);
  }
  public static void main(String[] args) {
    Client client = new Client();
    CallBack callBack = new CallBackImpl();
    client.register(callBack);
  }
} 
Class UserLookupAction is no longer required. This solution does not allow untrusted code to supply arbitrary statements for execution.
Applicability
Exposing sensitive methods through callbacks can result in misuse of privileges and arbitrary code execution.
Bibliography
| [API 2011] | Todo | 
| [SCG 2010] | Guideline 9-3: Safely invoke  |