0x01 基礎(chǔ)概述
許多應(yīng)用程序要求用戶在訪問任何內(nèi)容之前先在應(yīng)用程序內(nèi)部進(jìn)行身份驗證。根據(jù)其中包含的信息的敏感性,應(yīng)用程序通常有兩種方法:
· 用戶進(jìn)行一次身份驗證,然后保持身份驗證,直到他們手動注銷為止;
· 用戶保持登錄狀態(tài)的時間不會太長,并且在一段時間不活動后必須重新進(jìn)行身份驗證。
第一種策略雖然對用戶非常方便,但顯然不是很安全。第二種方法相當(dāng)安全,但是對用戶來說卻是一個負(fù)擔(dān),因為他們每次都必須輸入其憑據(jù)。實施生物特征認(rèn)證可以減輕這種負(fù)擔(dān),因為認(rèn)證方法對用戶而言變得相當(dāng)容易和快速。
開發(fā)人員通常不會從頭開始編寫與操作系統(tǒng)的集成,而通常會使用框架或第三方提供的庫。當(dāng)使用跨平臺的移動應(yīng)用程序框架(例如Flutter,Xamarin或React Native)時,尤其如此,其中需要在特定于平臺的代碼中實現(xiàn)此類集成。由于身份驗證是一項對安全性至關(guān)重要的功能,因此重要的是驗證這些第三方庫是否已安全地實現(xiàn)了所需的功能。
在此博客文章中,我們將首先看一下生物特征認(rèn)證的基本概念,以便我們隨后可以研究提供生物特征認(rèn)證支持的多個React Native庫的安全性。
我們分析了五個提供生物特征認(rèn)證的React Native庫。對于這些庫中的每一個,我們分析了生物識別認(rèn)證的實現(xiàn)方式以及它是否正確使用操作系統(tǒng)提供的加密原語來保護(hù)敏感數(shù)據(jù)。
我們的分析表明,五個分析的庫中只有一個提供了基于結(jié)果的安全生物特征認(rèn)證。其他庫僅提供基于事件的身份驗證,這是不安全的,因為僅對生物特征認(rèn)證進(jìn)行驗證,而實際上并未以密碼方式保護(hù)任何數(shù)據(jù)。
0x02 生物特征識別
生物特征認(rèn)證允許用戶使用其生物特征數(shù)據(jù)(指紋或面部識別)對應(yīng)用進(jìn)行認(rèn)證。通常,可以通過兩種不同的方式來實現(xiàn)生物特征認(rèn)證:
· 基于事件:生物統(tǒng)計API僅將身份驗證嘗試的結(jié)果返回給應(yīng)用程序(“成功”或“失敗”),這種方法被認(rèn)為是不安全的;
· 基于結(jié)果:身份驗證成功后,生物統(tǒng)計API會檢索一些加密對象(例如解密密鑰)并將其返回給應(yīng)用程序。失敗時,不會返回任何加密對象。
基于事件的身份驗證是不安全的,因為它僅包含返回的布爾值(或類似值)。因此,可以使用代碼工具(例如Frida)通過修改返回值或手動觸發(fā)成功流程來繞過它。如果實現(xiàn)是基于事件的,則還意味著敏感信息以不安全的方式存儲在某處:在應(yīng)用程序從生物識別API接收到“成功”之后,它仍將需要使用一些身份驗證向后端進(jìn)行用戶身份驗證。一種憑證,將從本地存儲中檢索,無需解密密鑰即可完成此操作,否則,實現(xiàn)將不是基于事件的,這意味著憑據(jù)無需適當(dāng)加密即可存儲在本地存儲中的某個位置。
另一方面,良好的基于結(jié)果的生物特征認(rèn)證將無法通過Frida之類的工具來繞過。要實現(xiàn)基于結(jié)果的安全生物特征認(rèn)證,應(yīng)用程序必須使用硬件支持的生物特征API。
存儲憑證
盡管我們在此文章中使用“憑證”一詞,但我們并不主張存儲用戶的憑證(即用戶名和密碼)。無論用戶的憑據(jù)存儲方式如何,將其存儲在設(shè)備上對于高安全性應(yīng)用程序從來都不是一個好主意。相反,上述“憑證”應(yīng)該是專用于生物認(rèn)證的憑證(例如高熵字符串),這些憑證是在生物認(rèn)證的激活期間生成的。
要在Android上實施基于結(jié)果的安全生物身份驗證,必須生成需要用戶身份驗證的加密密鑰。這可以通過使用setUserAuthenticationRequired生成密鑰時的方法來實現(xiàn)。每當(dāng)應(yīng)用程序嘗試訪問密鑰時,Android將確保提供有效的生物識別信息。然后必須使用密鑰來執(zhí)行加密操作,從而解鎖憑據(jù),然后可以將憑據(jù)發(fā)送到后端。這是通過向CryptoObject生物識別API提供以上一個密鑰開頭的來完成的。例如,BiometricPrompt類提供了一個authenticate方法,該方法采用CryptoObject作為一個論點。然后,可以通過result參數(shù)在成功回調(diào)方法中獲得對該鍵的引用??梢栽趂-secure的這篇非常不錯的博客文章中找到有關(guān)在Android上實現(xiàn)安全生物特征認(rèn)證的更多信息。
在iOS上,必須生成一個加密密鑰并將其存儲在key串中。key串中的條目必須設(shè)置有訪問控制標(biāo)志biometryAny。然后必須使用密鑰執(zhí)行加密操作,以解鎖可發(fā)送到后端的憑據(jù)。通過向key串查詢受密鑰保護(hù)的biometryAnyiOS,iOS將確保用戶使用其生物識別數(shù)據(jù)解鎖所需的key?;蛘撸覀兛梢詫{據(jù)本身直接存儲在biometryAny保護(hù)下,而不是將密碼密鑰存儲在“key串”中。
指紋認(rèn)證
Android和iOS允許你信任“設(shè)備上已注冊的所有指紋”或“設(shè)備上當(dāng)前已注冊的所有指紋”。在后一種情況下,如果添加或刪除了指紋,則加密對象將無法使用。對于Android,默認(rèn)值為“所有指紋”,而在將指紋添加到設(shè)備的情況下,你可以使用setInvalidatedByBiometricEnrollment刪除CryptoObject。對于iOS,可以在biometryAny和biometryCurrentSet之間進(jìn)行選擇。雖然“當(dāng)前已注冊”選項是最安全的,但在本文中,我們不會對這種區(qū)別給予重視。
基于事件的身份驗證真的不安全嗎?是的。這完全取決于你的移動應(yīng)用程序的威脅模型。應(yīng)用程序提供基于結(jié)果的身份驗證的要求是OWASP MASVS(MSTG-AUTH-8)中的2級要求。級別2表示你的應(yīng)用程序正在處理敏感信息,通常用于金融,醫(yī)療或政府部門的應(yīng)用程序。
OWASP MASVS驗證級別
如果你的應(yīng)用程序使用基于事件的生物特征認(rèn)證,則將發(fā)生特定的攻擊,這些攻擊將使用戶的憑據(jù)可供攻擊者使用:
· 使用取證軟件進(jìn)行物理提取
· 從備份文件中提取數(shù)據(jù)(例如iTunes備份或adb備份)
· 具有root權(quán)限訪問設(shè)備的惡意軟件
最后一個示例也將能夠攻擊使用基于結(jié)果的生物特征認(rèn)證的應(yīng)用程序,因為有可能在憑據(jù)已在內(nèi)存中解密后立即注入到應(yīng)用程序中,但這種攻擊的門檻比只需復(fù)制應(yīng)用程序的本地存儲。