安全誤報
介紹
#我們偶爾會收到關於 Dart 和 Flutter 應用程式安全漏洞的錯誤報告,這些報告是由為其他型別應用程式(例如用 Java 或 C++ 編寫的應用程式)構建的工具生成的。本文件提供了有關我們認為不正確的報告的資訊,並解釋了擔憂的緣由。
常見擔憂
#共享物件應使用強化函式
#共享物件不包含任何強化函式。強化函式提供緩衝區溢位檢查,以防範 glibc 的常見不安全函式(如
strcpy、gets等)。使用編譯器選項-D_FORTIFY_SOURCE=2來強化函式。
當這指的是已編譯的 Dart 程式碼(例如 Flutter 應用程式中的 libapp.so 檔案)時,此建議是錯誤的,因為 Dart 程式碼不直接呼叫 libc 函式;所有 Dart 程式碼都透過 Dart 標準庫進行處理。
(通常情況下,MobSF 在此處會產生誤報,因為它會檢查任何使用帶有 _chk 字尾的函式,但由於 Dart 完全不使用這些函式,因此它既沒有帶字尾也沒有不帶字尾的呼叫,MobSF 因此將程式碼視為包含未強化呼叫。)
共享物件應使用 RELRO
#
libapp.so二進位制檔案未找到 RELRO
Dart 完全不使用常規的函式過程連結表 (PLT) 或全域性偏移表 (GOT) 機制,因此重定位只讀 (RELRO) 技術對於 Dart 來說實際上並沒有太大意義。
Dart 中相當於 GOT 的是池指標,與 GOT 不同,它位於隨機位置,因此更難被利用。
原則上,在使用 Dart FFI 時可以建立易受攻擊的程式碼,但只要 Dart FFI 使用的程式碼本身適當使用了 RELRO,那麼正常使用 Dart FFI 也不會容易出現這些問題。
共享物件應使用棧金絲雀值
#
libapp.so二進位制檔案未找到金絲雀
此共享物件未將棧金絲雀值新增到棧中。棧金絲雀用於檢測和防止利用程式覆蓋返回地址。使用選項 -fstack-protector-all 來啟用棧金絲雀。
Dart 不生成棧金絲雀,因為與 C++ 不同,Dart 沒有棧分配的陣列(這是 C/C++ 中棧溢位的主要來源)。
編寫純 Dart 程式碼(不使用 dart:ffi)時,由於純 Dart 程式碼是一種託管語言,其中不存在緩衝區溢位等問題,因此您已經擁有比任何 C++ 緩解措施都更強的隔離保證。
原則上,在使用 Dart FFI 時可以建立易受攻擊的程式碼,但只要 Dart FFI 使用的程式碼本身適當使用了棧金絲雀值,那麼正常使用 Dart FFI 也不會容易出現這些問題。
程式碼應避免使用 _sscanf、_strlen 和 _fopen API
#二進位制檔案可能包含以下不安全 API:
_sscanf、_strlen、_fopen。
報告這些問題的工具往往過於簡化其掃描;例如,它們會查詢具有這些名稱的自定義函式,並假定它們指的是標準庫函式。Flutter 的許多第三方依賴項都有名稱相似的函式,這些函式會觸發這些檢查。有些情況可能是有效的擔憂,但由於誤報數量巨大,無法從這些工具的輸出中判斷。
程式碼應使用 calloc(而不是 _malloc)進行記憶體分配
#二進位制檔案可能使用
_malloc函式而不是calloc。
記憶體分配是一個複雜的主題,需要在效能和抵禦漏洞的能力之間做出權衡。僅僅使用 malloc 並不一定表明存在安全漏洞。雖然我們歡迎具體的報告(見下文),但對於應優先使用 calloc 的情況,在實踐中,將所有 malloc 呼叫統一替換為 calloc 是不合適的。
iOS 二進位制檔案設定了 Runpath Search Path(@rpath)
#二進位制檔案設定了 Runpath Search Path(
@rpath)。在某些情況下,攻擊者可以濫用此功能來執行任意可執行檔案以執行程式碼並提升許可權。刪除編譯器選項-rpath以移除@rpath。
在構建應用程式時,Runpath Search Path 指的是連結器搜尋以查詢應用程式使用的動態庫 (dylibs) 的路徑。預設情況下,iOS 應用程式將其設定為 @executable_path/Frameworks,這意味著連結器應在應用程式包內相對於應用程式二進位制檔案的 Frameworks 目錄中搜索 dylibs。Flutter.framework 引擎與其他嵌入式框架或 dylibs 一樣,會被正確複製到此目錄中。應用程式執行時,會載入庫二進位制檔案。
Flutter 應用程式使用預設的 iOS 構建設定 (LD_RUNPATH_SEARCH_PATHS=@executable_path/Frameworks)。
涉及 @rpath 的漏洞不適用於移動環境,因為攻擊者無法訪問檔案系統,也無法任意替換這些框架。即使攻擊者能夠某種方式將框架替換為惡意框架,應用程式也會因程式碼簽名違規而在啟動時崩潰。
CBC 與 PKCS5/PKCS7 填充漏洞
#我們收到了關於某些 Flutter 包中存在“CBC 與 PKCS5/PKCS7 填充漏洞”的模糊報告。
據我們所知,這是由 ExoPlayer 中的 HLS 實現(com.google.android.exoplayer2.source.hls.Aes128DataSource 類)觸發的。HLS 是 Apple 的流媒體格式,它定義了 DRM 所需的加密型別;這不是漏洞,因為 DRM 並不保護使用者的計算機或資料,而僅僅是提供混淆以限制使用者完全使用其軟體和硬體的能力。
應用程式可讀寫外部儲存
#應用程式可讀寫外部儲存。任何應用程式都可以讀取寫入外部儲存的資料。
與來自任何不受信任源的資料一樣,您在處理來自外部儲存的資料時應執行輸入驗證。我們強烈建議您不要在動態載入之前將可執行檔案或類檔案儲存在外部儲存上。如果您的應用程式確實從外部儲存檢索可執行檔案,則在動態載入之前應先對檔案進行簽名和加密驗證。
我們收到報告稱,一些漏洞掃描工具將影像選擇器外掛讀寫外部儲存的能力視為一種威脅。
從本地儲存讀取影像是這些外掛的用途;這不是漏洞。
應用程式使用 file.delete() 刪除資料
#當您使用 file.delete 刪除檔案時,檔案系統表中只刪除了對檔案的引用。檔案仍然存在於磁碟上,直到被其他資料覆蓋,使其容易被恢復。
一些漏洞掃描工具將攝像頭外掛在記錄裝置攝像頭資料後刪除臨時檔案視為安全漏洞。因為影片是由使用者錄製的,並且儲存在使用者的硬體上,所以沒有實際風險。
已棄用的擔憂
#本節包含在使用舊版本 Dart 和 Flutter 時可能看到的有效訊息,但現在這些訊息應該不再出現。如果您在舊版本 Dart 或 Flutter 中看到這些訊息,請升級到最新的穩定版本。如果您在當前穩定版本中看到這些訊息,請報告它們(請參閱本文件末尾的部分)。
棧應設定 NX 位
#共享物件未設定 NX 位。NX 位透過將記憶體頁面標記為不可執行來防止記憶體損壞漏洞的利用。使用選項
--noexecstack或-z noexecstack將棧標記為不可執行。
(MobSF 的訊息具有誤導性;它檢查的是棧是否被標記為不可執行,而不是共享物件。)
在 Dart 和 Flutter 的早期版本中,ELF 生成器存在一個錯誤,它沒有發出具有 ~X 許可權的 gnustack 段,但現在此問題已修復。
報告真實擔憂
#雖然自動漏洞掃描工具會報告上述誤報,但我們不能排除存在需要密切關注的實際問題。如果您發現了一個您認為確實存在的安全漏洞,我們非常感謝您能將其報告給我們。