惡意App利用華為Android手機觸屏事件統計日志還原用戶的觸屏輸入
譯者說明:由于該研究是在一年前完成的,所以截止本文發布時,華為不僅解決了本文提到的漏洞(CVE-2021-22337),而且現在已經將他們的許多設備從 Android 升級到了鴻蒙操作系統。因此,不要期望在你最新的華為設備上找到完全相同的漏洞利用細節。
在審核某個供應商的文件系統節點訪問權限時,我們發現了一個 SELinux 權限錯誤配置漏洞,起初看起來有些無害,因為所有不受信任的應用程序都可以訪問基于 sysfs 的觸屏事件統計日志文件。然而,在對這些日志的格式進行逆向工程并應用一些簡單的機器學習技巧之后,我們設法從不受信任的應用程序上下文中偷偷地提取了精確的觸屏事件模式。為此,我們創建了概念驗證,發現通過此漏洞,惡意應用程序可以通過在后臺持續偵聽觸屏事件并從觀察到的事件推斷用戶輸入來竊取敏感的用戶數據。調查表明,可以提取的信息量足以在很大程度上重構輸入密碼的鍵盤(pin-pad)甚至模擬屏幕鍵盤上的用戶輸入。
華為Android設備上的觸摸屏事件可以被記錄
華為智能手機的觸屏是通過 tpkit 模塊處理的,該模塊可以在已發布的內核源代碼中的drivers/devkit/tpkit/ 中找到。為不同的觸屏供應商實現了多個底層驅動程序,但:
Nova 5T(YAL)、Mate 30 Pro(LIO)和P40 Pro (ELS)上的高級驅動程序都使用了 hostprocessing/huawei_thp* 文件中定義的驅動程序.
這個huawei_thp驅動會在/sys/devices/platform/huawei_thp/路徑下創建一些虛擬控制文件。以下是包含詳細權限和 SELinux 部分標簽文件列表:

現在讓我們看一下 roi_data_internal 節點,它由 root 用戶擁有,但對其他用戶來說仍然是可讀的。正如我們所看到的,huawei_thp內核模塊的大多數其他節點對“other”角色沒有文件權限,所以不管SELinux是什么,自由訪問控制(傳統的Unix權限系統)都會阻止訪問。但是roi_data_internal是一個例外。我們有必要弄清它來自哪里。sysfs 文件權限以編程方式分配。下面是drivers/devkit/tpkit/hostprocessing/huawei_thp_attr.c文件的相關部分:

正如我們在上面看到的,roi_data_internal 設備屬性是用 S_IRUGO 定義的。這是漏洞利用的代碼行。
然而,如果不考慮強制訪問控制,這幅圖就是不完整的。由于華為智能手機使用 SELinux,因此檢查 SELinux 策略數據庫中的 sysfs_touchscreen 文件標簽很重要,該數據庫位于 /vendor/etc/selinux/precompiled_sepolicy。下載數據庫并查詢允許對 sysfs_touchscreen 目標上下文執行讀取操作的每個規則會產生超過一千條輸出行。在結果中,我們可以找到允許untrusted_app上下文規則。

這意味著任何應用程序都可以在沒有任何權限的情況下訪問roi_data_internal節點。該訪問適用于未經修改的、開箱即用的電話,無需任何類型的本地權限提升。雖然訪問控制繞過漏洞本身很明顯,但我們必須弄清楚從該節點提取觸屏使用信息的精確度,以確定此漏洞對安全性的影響。
roi_data_internal 矩陣的含義
該節點的內容由huawei_thp_core.c文件中的thp_roi_data_debug_show函數提供,其中ROI_DATA_LENGTH == 49。

thp_get_core_data()函數調用返回g_thp_core指針,在這個指針中,觸屏控制器以中斷驅動的方式更新底層數據。由于該節點對觸屏內核驅動程序使用的原始數據進行操作,因此只需在緊密循環中監視 roi_data_internal 并尋找變化,就可以實現非常高的計時精度。
下面是節點在簡單觸摸屏幕后的輸出示例,屏幕以原始文本格式和圖形形式表示。可以看出,最大值在矩陣([3,3])的中心,這是設計的,因為該點應該是估計的接觸點的中心。

指尖觸摸的 roi_data_internal 輸出示例
為了驗證這個7 × 7矩陣確實代表觸屏區域的周邊區域(而矩陣的中心代表觸屏的中心,但事實并非如此),我們制作了一個超級復雜的驗證工具:一個由鋁箔覆蓋的不對稱 L 形鋼回形針,鋁箔很重要,因為現代觸屏使用電容傳感,主要是檢測由導電觸摸事件引起的表面電子虧損。

L形回形針實驗
由于 roi_data_internal 的圖形明顯類似于回形針的 L 形,我們可以通過捕獲觸摸位置的大約 3 cm周邊區域得出結論,返回的矩陣與物理現實有緊密的聯系。
roi_data_internal 數據與tapping位置的關系
人們可能會假設,如果每個觸摸事件都具有完全相同的物理特性,那么就不可能從觸屏數據中推斷出位置。事實上,情況并非如此。當 ROI 矩陣超出屏幕的物理尺寸時,觸摸屏驅動程序將用常量零填充缺失的數據點。這使得僅根據ROI數據來區分觸屏特定邊緣的觸摸與其他位置的觸摸非常方便。
當然,人類的觸摸不會像理論上的高精度機器人手指那樣具有恒定的特性,它具有均勻的表面、固定的觸摸角度和力度,以及無論位置如何,每次觸摸之間的時間間隔都是恒定的。與單獨的內核驅動程序的“用零填充缺失數據”行為相比,有兩個主要因素可以促進更高精度的推斷。
首先是時機。由于各種原因,在許多場景中,觸摸之間的時間間隔將與實際的按鍵序列相關聯。我們注意到學術界在這個研究領域的現有技術。例如,在“沙盒JavaScript中的實際按鍵計時攻擊”中,Lipp等人認為,即使在瀏覽器內的沙盒JavaScript運行時限制更大的環境中,按鍵計時差異也可以用來恢復實際類型化的短語。在一個更接近我們的場景中,在“對PIN輸入設備的計時攻擊”中,Kune等人使用按鍵間隔計時(在他們的例子中,這是從音頻獲得的,不如我們在這里所依賴的時間戳精確)來更好地推斷PIN pad上的按鍵命中情況。最近,在“鍵盤記錄側通道”中,Monaco基于許多數據集構建了鍵間時間延遲的語言模型。有趣的是,他們發現單詞越長(就字符數而言),恢復的機會就越高,因為延遲模式變得非常獨特。
第二個因素是手指運動和定位的差異。我們在生活中可以觀察到,大多數人都是將自己的手機拿在手里,同時用拇指來訪問觸摸屏。這意味著手通常處于相對固定的位置,而只有拇指在屏幕上移動。拇指觸摸屏幕的部分在屏幕上有一個不對稱的印記,更重要的是,當我們旋轉、彎曲或伸展我們的拇指以到達屏幕的特定區域時,這個印記也會發生變化。這個簡單的觀察提供了一種直覺,即所記錄的矩陣數據值的差異實際上與所觸摸的位置相關。



不同位置的不同印記
我們做了一個非常簡單的實驗來還原了這個過程,在屏幕中間留下一個觸摸事件的指紋,在右下角留下一個,同時右手拿著手機,用 4 個手指支撐,用拇指觸碰。正如我們在可視化中看到的,有一個明顯的區別!出于隱私原因,屏幕上的指紋是模糊的,但為了更好的可見性而突出顯示。用于從數據集生成可視化的數學變換將在下一節中進行更詳細的描述。
觸摸事件目標:PIN 和按鍵
在嘗試創建基于統計或神經網絡的模型之前,我們首先必須為我們的推理實驗選擇目標。首先,我們研究了數字輸入的默認虛擬鍵盤和PIN pad。
屏幕上的鍵盤
Android上的虛擬屏幕鍵盤基本上是唯一的文本輸入法,所以它不可避免地會在系統范圍內使用。屏幕鍵盤的按鍵布局是固定的,這就有可能發生類似的攻擊。

SwiftKey輸入法,華為智能手機的默認屏幕鍵盤
很明顯,由于間隔和可能性的數量,僅從指紋數據對鍵盤進行精確推斷比對PIN pad更具挑戰性。雖然我們對此的研究結果是比較初步的,但它們仍顯示了該方法在基本層面上的可行性。
PIN Pad
華為智能手機中使用數字輸入法的例子有很多,例如解鎖屏幕或電話撥號器。正如下面的屏幕截圖所示,密碼鍵盤使用常見的 3×4 網格。可能是出于人體工程學和可用性的原因,這些網格是均勻分布的,幾乎跨越了整個手機的寬度,并占據了高度的很大一部分。

華為智能手機PIN pad示例
在所有測試設備(即YAL、LIO和ELS)上,1,4,7,3,6,9和0的數字都位于距離屏幕邊緣1.5厘米的位置。在前幾節中,我們根據經驗估計了LIO上ROI矩陣的邊長為3厘米。正如我們上面所提到的,當ROI矩陣超出屏幕的物理尺寸時,觸屏驅動程序將用常量零填充缺失的數據點。這使得僅基于ROI數據就可以非常方便地檢測邊緣周圍的觸摸。
最近智能手機的大屏幕尺寸確保了手指觸摸的遠距離差異,例如右手拿著電話時的數字 1 與 9(或類似的左手拿著電話時的數字 3 和 7)。這些距離需要大量的拇指移動、旋轉和拉伸,這將導致手指印記變形。
因此,從經驗上來說,我們可以合理地假設,這些差異會讓觸摸值變得可區分。接下來,我們將ROI數據分兩個階段進行數字識別分析。首先,我們使用統計分析。其次,我們使用神經網絡。
統計分析
我們有兩個主要目標:首先證明多次觸摸某個數字會導致相似的 ROI 數據,其次驗證不同數字的 ROI 數據收到不同的均值。
屏幕上的鍵盤
對于 Swiftkey 鍵盤,我們首先嘗試對邊緣的幾個鍵進行統計分析:左側的 A 和 Q 以及右側的 0 和 P。數據標準化與密碼鍵盤數據相同(見下文)。下圖顯示了數字平均值與全局平均值的差異。

SwiftKey 上選定鍵的全局平均值和 ROI 數據的差異
ROI 差異非常明顯,這意味著,通過進一步建模,觸屏鍵應該通過其相應的 ROI 數據即可復原。
PIN Pad
對于PIN Pad,首先我們收集了一個小數據集(每個數字100個觸摸事件),這些ROI數據由實際觸摸的數字標記。然后將原始樣本(ROI矩陣)按其能量(平方和的平方根)歸一化,并按標簽平均,以得到每個數字的平均基線。這些基線進一步平均,從而形成一個統一的全局基線。
為了驗證第一個目標,通過從歸一化數據集中隨機選擇不同數量的樣本并繪制與全局平均值的差異來證明每位數的 ROI 數據的收斂性。下圖顯示了列中的數字,向下有更多的樣本用于平均計算。它清楚地表明數據收斂到平均值。當前的方法是比較經驗的,但通過這種方式在視覺上更容易掌握聯系。這告訴我們觸摸數字會提供可重復的 ROI 數據。

歸一化樣本和基線與樣本大小的差異
要驗證第二個目標,就需要用數字標出平均值,并將它們相互比較。下個圖顯示了數字和全局基線的差異。很容易看出,數字之間的差異是非常明顯的。即使通過肉眼,也很容易看出 1-4-7、2-5-8、3-6-9 和 0 這四個數字組具有非常容易區分的模式。當然,數據處理可以更好地區分它們。為了使精度更加明顯,我們采用了神經網絡處理。

平均ROI數據和按數字分組的全局基線的差異
神經網絡模型
為了提供進一步的證明,我們還對非常簡單的神經網絡模型進行了實驗,結果很好,因此我們認為通過收集更多的數據和應用更先進的數據清理方法,神經網絡可以很好地實現 ROI 之間的映射函數數據和實際數字。
與統計分析一樣,整個神經網絡計算都是在 tensorflow 中實現的。
我們的神經網絡模型在輸入層接收ROI數據的49個像素點,最后有10個輸出節點。在兩個全連接層之間只使用了 512 個節點并使用 ReLU 激活函數。我們的 1000 個元素數據集在 ML 領域被認為很小,并且小的輸入案例往往會過度擬合,因此我們還包含了“dropout”層來抵消這種影響。對于我們模型的損失函數,我們選擇優化交叉熵,因為我們期望在輸出層上進行一次性編碼,即對于輸入 ROI,只有 10 個輸出神經元中的一個應該被觸發。在訓練期間,五分之一的輸入數據被保留用于驗證目的。以下是部分tensorflow 代碼:


令人驚訝的是,這樣一個簡單的模型已經表現得相當好:我們已經實現了大約 90% 的準確率,而無需微調網絡結構或輸入數據。另請注意,當前模型僅依賴于 ROI 數據,并未考慮時間信息。具有記憶功能的循環神經網絡也能夠計算觸摸間延遲,進一步提高準確度。

神經網絡訓練歷史
最后,構建一個預測器來對 PIN pad觸摸進行分類并在手機上實時播放會產生預期的積極結果:

神經網絡分類結果
總之,我們的經驗表明,ROI數據可以明確地映射到PIN pad數字上。
實驗結果的實踐應用
誠然,這些結果是實驗性的。但經過大量的改進,很快就能被用于實踐。從 roi_data_internal 獲取的側信道信息取決于用戶特征:ROI 數據會隨著手的大小、慣用手和手機使用習慣而變化。變化也可以基于地理或基于語言的特征。盡管開發適用于每個受害者的通用算法似乎很困難,但并非絕對有必要有效利用此漏洞。一個關鍵原因是攻擊者(惡意應用程序)還可以對其決策算法應用高精度的設備端訓練。這是因為應用程序可以很容易地設計為在使用應用程序本身時從用戶那里繪制觸摸事件,通過持續監控 ROI 數據,同時通過合法輸入字段了解真實情況,應用程序可以有效地“學習”其用戶的手勢。此外,這種行為很難被任何監控檢測到,因為讀取 roi_data_internal 不會生成任何內核日志消息。
可用于改進精度的另一個參數是時間,我們還沒有進一步試驗用于推斷鍵盤按鍵的時間信息,但除了指尖的印記之外,roi_data_internal 還提供了非常精確的時間信息。由于鍵盤的幾何形狀,當手指移動更遠的距離以到達更遠的按鍵時,計時信息也帶有信息值,這會轉化為按鍵之間的延遲增加。
參考及來源:
https://labs.taszk.io/articles/post/ouchscreen/