攻擊者思維 - iOS 攝像頭指示燈不亮,就真的沒事了么?
原文來自 blog.secops.com
在這個(gè)博客系列中,我們將介紹移動(dòng)威脅參與者的想法,以及攻擊者使用哪些技術(shù)來克服安全保護(hù)以及我們的手機(jī)和平板電腦受到威脅的跡象。
在第一篇博客中,我們將展示最近添加的攝像頭和麥克風(fēng)綠色/橙色指示器如何不會(huì)對移動(dòng)威脅參與者構(gòu)成真正的安全挑戰(zhàn)。
從 iOS 14 開始,系統(tǒng)右上角新增了兩個(gè)點(diǎn):一個(gè)綠點(diǎn)和一個(gè)橙點(diǎn)。當(dāng)訪問攝像頭或麥克風(fēng)時(shí),這些指示燈會(huì)點(diǎn)亮發(fā)出信號。
當(dāng)沒有綠色/橙色圓點(diǎn)時(shí),我們就不那么擔(dān)心手機(jī)能聽到我們說話了。

我們知道像 NSO/Pegasus 這樣的惡意軟件能夠監(jiān)聽麥克風(fēng)。NSO Group 和數(shù)百名其他針對移動(dòng)設(shè)備的威脅軟件能否在攝像頭指示器關(guān)閉時(shí)拍攝我們的視頻呢?
讓我們來看看此功能是否對攻擊者構(gòu)成任何挑戰(zhàn)。
邏輯問題
我們先想一想。每次訪問攝像頭或麥克風(fēng)時(shí),指示燈是否真的亮起?我們很快就會(huì)想到 Siri。如果麥克風(fēng)指示燈沒有一直亮起,手機(jī)如何知道我們何時(shí)說“嘿 Siri”?手機(jī)一定在監(jiān)聽某種正確的聲音。
“嘿Siri”
/System/Library/PrivateFrameworks/CoreSpeech.framework/corespeechd?依賴?VoiceTrigger.framework?來持續(xù)監(jiān)聽用戶的聲音,然后在聽到關(guān)鍵字時(shí)激活 Siri。
輔助功能 -> 語音控制

語音控制允許您使用語音命令與設(shè)備交互。
/System/Library/PrivateFrameworks/SpeechRecognitionCore.framework/XPCServices/com.apple.SpeechRecognitionCore.brokerd.xpc/XPCServices/com.apple.SpeechRecognitionCore.speechrecognitiond.xpc/com.apple.SpeechRecognitionCore.speechrecognition
負(fù)責(zé)訪問麥克風(fēng)。
輔助功能 -> 切換控制

SwitchControl 功能的一部分是檢測用戶頭部的運(yùn)動(dòng)以與設(shè)備進(jìn)行交互。很酷的功能!由以下模塊處理:
/System/Library/PrivateFrameworks/AccessibilityUI.framework/XPCServices/com.apple.accessibility.AccessibilityUIServer.xpc/com.apple.accessibility.AccessibilityUIServer
和
/System/Library/CoreServices/AssistiveTouch.app/assistivetouchd
這些功能必須訪問麥克風(fēng)或攝像頭才能運(yùn)行。但是,這些功能不會(huì)觸發(fā)綠色/橙色視覺指示器。這意味著移動(dòng)惡意軟件也可以這樣做。
這意味著通過將惡意線程注入?com.apple.accessibility.AccessibilityUIServer / com.apple.SpeechRecognitionCore.speechrecognitiond?守護(hù)進(jìn)程,攻擊者可以啟用對麥克風(fēng)的靜默訪問。相機(jī)訪問需要額外的補(bǔ)丁,我們稍后會(huì)討論
繞過 TCC 提示
TCC 代表“透明度、同意和控制”。iOS 用戶經(jīng)常會(huì)遇到這樣的提示:

TCC 的核心是一個(gè)名為?tccd?的系統(tǒng)守護(hù)進(jìn)程,它管理對敏感數(shù)據(jù)庫的訪問以及從輸入設(shè)備(包括但不限于麥克風(fēng)和攝像頭)收集敏感數(shù)據(jù)的權(quán)限。
你可知道?TCC 提示僅適用于具有 UI 界面的應(yīng)用程序。在后臺運(yùn)行的任何東西都需要特殊的操作權(quán)限。權(quán)限如下圖所示。只需?kTCCServiceMicrophone?就足以訪問麥克風(fēng)。

相機(jī)訪問稍微復(fù)雜一些。除了?tccd?之外,還有另一個(gè)名為?mediaserverd?的系統(tǒng)守護(hù)進(jìn)程確保沒有后臺運(yùn)行狀態(tài)的進(jìn)程可以訪問攝像頭。

到目前為止,當(dāng)用戶與另一個(gè)前臺應(yīng)用程序交互時(shí),似乎需要一個(gè)額外的步驟(例如修補(bǔ) mediaserverd)來在后臺訪問相機(jī)。
禁用麥克風(fēng)、攝像頭訪問的可視指示器
第一種方法比較粗糙,使用 Cycript 向 SpringBoard 注入代碼,導(dǎo)致指標(biāo)突然消失。

受?com.apple.SpeechRecognitionCore.speechrecognitiond?和?com.apple.accessibility.AccessibilityUIServer?的啟發(fā),這是一種非常適合我們目的的私有權(quán)限 (com.apple.private.mediaexperience.suppressrecordingstatetosystemstatus)!不幸的是,此方法不適用于相機(jī)訪問。

通過修補(bǔ)“mediaserverd”在后臺訪問相機(jī)
mediaserverd?是一個(gè)監(jiān)控媒體捕獲會(huì)話的守護(hù)進(jìn)程。想要訪問攝像頭的進(jìn)程必須得到?tccd?和?mediaserverd?的批準(zhǔn)。它是 tccd 之后的額外安全層。當(dāng)它檢測到應(yīng)用程序不再在前臺運(yùn)行時(shí),它還會(huì)終止相機(jī)訪問。
值得注意的是,mediaserverd?配備了一個(gè)特殊的權(quán)限(get-task-allow)來防止代碼注入。

作為“get-task-allow”權(quán)限的結(jié)果,動(dòng)態(tài)調(diào)試器依賴于獲取任務(wù)端口,如 cycript,frida 在 mediaserverd 守護(hù)進(jìn)程上不起作用。當(dāng)?mediaserverd?沒有響應(yīng)時(shí),它也會(huì)經(jīng)常被系統(tǒng)殺死,即使是很短的時(shí)間。這并不常見:這些跡象告訴我們?mediaserverd?負(fù)責(zé)一些重要的事情。
當(dāng)進(jìn)程切換到后臺時(shí),mediaserverd?將收到通知并撤銷對該特定進(jìn)程的相機(jī)訪問權(quán)限。我們需要想辦法讓mediaserverd在檢測到進(jìn)程在后臺運(yùn)行時(shí)什么都不做。
經(jīng)過簡短的研究,我們發(fā)現(xiàn)可以通過 hook 到 Objective-C 方法?-[FigCaptureClientSessionMonitor _updateClientStateCondition:newValue:]?來防止?mediaserverd?撤銷相機(jī)訪問權(quán)限,因此不需要代碼覆蓋。
為了注入?mediaserverd,我們使用了?lldb。?lldb?不依賴于任務(wù)端口,而是調(diào)用內(nèi)核進(jìn)行代碼注入。實(shí)際上,已經(jīng)具有內(nèi)核代碼執(zhí)行能力的操控者可以替代?mediaserverd?的“權(quán)限”來執(zhí)行此類注入。
POC 源代碼可在此處獲得 https://github.com/ZecOps/public/tree/master/hidden_cam_mic_demo。
在 Mac 上呢?
根據(jù) 2015 年之前的實(shí)驗(yàn),Mac 上前置攝像頭旁邊的綠燈不能僅使用軟件關(guān)閉。修改?AppleCameraInterface?驅(qū)動(dòng)程序并上傳自定義網(wǎng)絡(luò)攝像頭固件沒有解決問題。綠燈無法關(guān)閉,因?yàn)樗谙鄼C(jī)開機(jī)時(shí)亮起。只要有電,燈就會(huì)一直亮著。從隱私角度來看,基于硬件的指標(biāo)是理想的選擇。我們尚未在最近的 Mac 版本/硬件上對此進(jìn)行驗(yàn)證。
演示
我們做了一個(gè)演示,從后臺進(jìn)程訪問攝像頭/麥克風(fēng),使用RTMP協(xié)議流式傳輸視頻/音頻,步驟:
設(shè)置RTMP服務(wù)器
編譯?
mediaserver_patch,將代碼注入?mediaserverd編譯?
ios_streaming_cam,使用以下權(quán)限重新簽署二進(jìn)制文件并在后臺運(yùn)行
<plist version="1.0">
<dict>
<key>com.apple.private.security.container-requiredkey>
<false/>
<key>platform-applicationkey>
<true/>
<key>com.apple.private.tcc.allowkey>
<array>
<string>kTCCServiceMicrophonestring>
<string>kTCCServiceCamerastring>
array>
<key>com.apple.security.iokit-user-client-classkey>
<array>
<string>IOSurfaceRootUserClientstring>
<string>AGXDeviceUserClientstring>
array>
<key>com.apple.private.mediaexperience.suppressrecordingstatetosystemstatuskey>
<true/>
<key>com.apple.private.mediaexperience.startrecordinginthebackground.allowkey>
<true/>
<key>com.apple.private.avfoundation.capture.nonstandard-client.allowkey>
<true/>
dict>
plist>
