天天看点

《Java编码指南:编写安全可靠程序的75条建议》—— 指南21:不要让不可信代码误用回调方法的特权

本节书摘来异步社区《java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.21节,作者:【美】fred long(弗雷德•朗), dhruv mohindra(德鲁•莫欣达), robert c.seacord(罗伯特 c.西科德), dean f.sutherland(迪恩 f.萨瑟兰), david svoboda(大卫•斯沃博达),更多章节内容可以访问云栖社区“异步社区”公众号查看。

回调提供一种注册方法的手段,在其感兴趣的事件发生时将会被调用(或回调。java在很多地方都使用了回调, 如applet技术、响应servlet的生命周期事件、awt和swing框架中的事件通知(如按钮单击事件),以及异步的读写操作等。甚至在线程的运行机制runnable.run()中,新起一个线程时,自动执行对应的run()方法都使用到了回调技术。

在java中,回调函数通常是使用接口来实现。下面是回调的一般结构:

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() {

   public void run() {

    callback.callmethod();

    return null;

   }

  });

}<code>`</code>

这段代码可以被客户端安全地使用,如下所示:

class maliciouscallback implements callback {

  // code here gets executed with elevated privileges

// client code

public static void main(string[] args) {

 callback callback = new maliciouscallback();

 callbackaction action = new callbackaction(callback);

 action.perform(); // executes malicious code

合规解决方案(回调自己调用doprivileged块)

根据oracle公司的安全编码指南[scg 2010]:

按照惯例,privilegedaction的实例和privilegedexceptionaction的实例可以提供给不可信代码,但不能以调用者提供的动作调用doprivileged。

下面的合规解决方案将doprivileged()的调用从callbackaction代码中移到了它自己的回调里。

final class userlookupcallback implements callback {

 // ...

// remaining code is unchanged<code>`</code>

通过回调暴露敏感方法可能导致特权误用和任意代码执行。