Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Callbacks provide a means to register a method to be invoked (or called back  back)when an interesting event occurs. Java uses callbacks for applet and servlet life-cycle events, AWT and Swing event notifications such as button clicks, and asynchronously reading and writing data from storage asynchronous reads and writes to storage, and even in Runnable.run() wherein a new thread automatically executes the specified run() method.

...

Callback methods are often invoked with no without changes in privileges, which means that they may be executed in a context that has more privileges than the context in which they are declared. If these callback methods accept data from untrusted code, privilege escalation may occur.

...

Code Block
bgColor#ffcccc
langjava
public interface CallBack {
  void callMethod();
}
 
class UserLookupCallBack implements CallBack {
  private int uid;
  private String name;

  public UserLookupCallBack(int uid) {
    this.uid = uid;
  }

  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;
    }
  }
}

final class CallBackAction {
  private CallBack callback;

  public CallBackAction(CallBack callback) {
    this.callback = callback;
  }
 
  public void perform() {
    AccessController.doPrivileged(new PrivilegedAction<Void>() {
        public Void run() {
          callback.callMethod();
          return null;
        }
      });
  }
}

This code could be safely used by a client safely, as infollows:

Code Block
langjava
public static void main(String[] args) {
  int uid = Integer.parseInt(args[0]);

  CallBack callBack = new UserLookupCallBack(uid);
  CallBackAction action = new CallBackAction(callBack);

  // ...
  action.perform(); // Looks up user name
  System.out.println("User " + uid + " is named " + callBack.getName());
}

...

Code Block
bgColor#ccccff
langjava
public interface CallBack {
  void callMethod();
}
  
class UserLookupCallBack implements CallBack {
  private int uid;
  private String name;
 
  public UserLookupCallBack(int uid) {
    this.uid = uid;
  }
 
  public String getName() {
    return name;
  }
 
  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;
        }
      });
  }
}
 
final class CallBackAction {
  private CallBack callback;

  public CallBackAction(CallBack callback) {
    this.callback = callback;
  }
 
  public void perform() {
    callback.callMethod();
  }
}

This code functions behaves the same as before, but an attacker can no longer run malicious callback code with elevated privileges. Even though an attacker can pass a malicious callback instance using the constructor of class CallBackAction, the code is not executed with elevated privileges because the malicious instance must contain a doPrivileged block which that cannot have the same privileges as trusted code. Additionally, class CallBackAction cannot be subclassed to override the the perform() method as it is declared final.

...

This compliant solution declares the UserLookupCallBack class final to prevent overriding of callMethod().

Code Block
bgColor#ccccff
langjava
final class UserLookupCallBack implements CallBack {
  // ...    
}
 
// OtherRemaining code is sameunchanged

Applicability

Exposing sensitive methods through callbacks can result in misuse of privileges and arbitrary code execution.

Bibliography

[API 20112014]

AccessController.doPrivileged()

[SCG 2010]

Guideline 9-3: Safely invoke java.security.AccessController.doPrivileged
Guideline 9-2: Beware of callback methods

...