天天看點

《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>

通過回調暴露敏感方法可能導緻特權誤用和任意代碼執行。