大家好!我是大聰明-PLUS!
這是有關嵌入式Linux安全性的文章的第二部分。
在第一部分中,我們討論了一些安全概念、威脅建模、安全啟動、代碼和數據加密、加密密鑰和密鑰存儲技術。
在第二部分中,讓我們繼續討論提高嵌入式 Linux 設備安全性的技術,包括安全編碼、靜態分析工具、運行時保護、模糊測試工具、權限、Linux 功能、強制訪問控制、沙盒、更新系統和網絡安全。
本文的第一部分討論了代碼和數據的加密。但是,如果您運行的應用程序存在可能被利用的漏洞,那么僅通過加密來保護代碼和數據是不夠的。
這就是為什么我們需要保護應用程序安全。有很多技術可以做到這一點,首先是安全編碼。
安全編碼
如果應用程序具有攻擊媒介(用戶輸入、配置文件、網絡通信等),則可以利用錯誤來利用系統。
尤其是使用 C/C++ 等內存不安全語言編寫的程序,緩沖區溢出等錯誤可能會被用于堆棧破壞和格式化字符串等攻擊。
舉個例子,這是一個在 Linux 內核(從 2.6.34 到 5.2.x 版本)中發現的緩沖區溢出漏洞,存在于 vhost 功能將 virtqueue 緩沖區轉換為 IOV 的過程中。特權客戶機用戶能夠在遷移過程中向主機傳遞長度無效的描述符,從而利用此漏洞提升其在主機上的權限。
|
|
該漏洞已注冊為CVE-2019-14835,并于2019年修復。實際上,虛擬機(客戶機)內的用戶可以利用此漏洞獲取主機的 root 權限。該漏洞(以及許多其他漏洞)在 Linux 內核中已經存在多年!
軟件終究會存在 bug,但我們可以嘗試減少 bug。為此,我們可以使用靜態分析工具。
靜態分析工具能夠分析源代碼(無需運行程序),從而在程序運行時遇到問題之前發現它們。這些工具可以發現諸如空指針引用、內存泄漏、整數溢出、越界訪問、初始化前使用等等程序錯誤!
有很多優秀的開源工具(例如 cppcheck、splint、clang 等)和商業工具(例如 Coverity、PC-Lint 等)可用于靜態代碼分析,從編譯器開始,它們通常內置有靜態分析工具,會在編譯代碼時生成警告或錯誤。這就是為什么我們永遠不應該忽略編譯器警告,對吧?
總之,我不會在這里深入探討靜態分析工具。如果你感興趣,可以看看“使用靜態分析工具尋找漏洞”。因此,降低應用程序安全漏洞風險的第一步是切勿忽略編譯器警告并使用靜態分析工具。但有些漏洞在源代碼級別很難識別,有時甚至無法識別。因此,我們可能需要在應用程序中添加運行時保護措施。
運行時保護
運行時保護使得對應用程序進行動態分析成為可能。這意味著您的程序將受到運行時執行的保護和檢查。
例如,AddressSanitizer (ASan) 是一款非常有趣的插樁工具,由谷歌安全研究人員創建,用于識別 C 和 C++ 程序中的內存訪問問題。在啟用 AddressSanitizer 的情況下編譯 C/C++ 應用程序的源代碼時,該程序將在運行時進行插樁,以識別并報告內存訪問錯誤。
另一個例子是地址空間布局隨機化,這是一種計算機安全技術,它隨機排列進程關鍵數據區域(文本、堆棧、堆、庫等)的地址空間位置。因此,如果您關心嵌入式 Linux 設備的安全性,則應該啟用 ASLR,至少在 Linux 內核中啟用。
Valgrind是另一個非常有用的工具,可以幫助檢測與內存相關的問題,如泄漏和數據爭用。
當然,這其中也存在一些權衡。雖然這些工具可以在運行時識別錯誤和安全漏洞,但它們可能會影響應用程序性能,并使系統調試變得更加困難。
此外,要使用這些工具查找錯誤,你必須確保代碼中存在錯誤的部分能夠運行。更好的是,應用程序的測試覆蓋率應該接近 100%。模糊測試工具或許能幫到你。
模糊測試是一種自動化軟件測試技術,涉及向程序提供無效、意外或隨機數據作為輸入。
然后監視程序是否存在異常,例如崩潰、內置代碼斷言失敗或潛在的內存泄漏。
有很多免費和開源的模糊測試工具可供使用,包括 AFL(美國模糊測試循環)和 syzkaller(Linux 內核模糊測試器)。
這正是安全研究人員和威脅行為者用來查找軟件安全漏洞的工具。有時,他們甚至會自己編寫模糊測試工具,而不是使用流行的框架。這樣做是有代價的,因為一些安全研究人員在BugBounty平臺上通過查找軟件漏洞賺取了數百萬美元。
因此,如果您關心安全性,請嘗試使用模糊測試工具測試您的嵌入式 Linux 系統!
最終,模糊測試、靜態分析和運行時保護等技術和工具將有助于顯著減少軟件中的錯誤數量。但這并不意味著您的軟件發布時不會出現任何錯誤!軟件總是會存在錯誤,因此我們需要另一層保護,以防軟件被利用。這就引出了系統權限。
權限
緩解漏洞利用風險的一種方法是不要以 root(超級用戶)權限運行程序!您應該利用操作系統的訪問控制機制,以非特權用戶身份運行進程,并在僅授予運行所需資源訪問權限的組中運行進程。
這被稱為最小特權原則,是設計安全系統的規則之一。應用程序應該僅以完成其工作所需的權限運行。
但問題是,有時我們需要“root 權限”來執行某些特權操作(例如設置系統時鐘、使用 RAW 套接字等)。在這種情況下,我們需要以 root 身份運行程序,對嗎?
錯了!解決這個問題的一個方法是使用 Linux 的一項名為 capabilities 的功能。
Linux 功能
Linux 功能是針對以 root 權限運行的進程的細粒度訪問控制系統。
Linux 內核將超級用戶相關的權限劃分為不同的單元,稱為“能力”,這些能力可以單獨啟用或禁用。因此,我們的想法是編寫一個程序,使其以 root 身份運行,但只啟用完成工作所需的能力。
如果您正在運行利用 Linux 功能的 Linux 發行版,則可以使用getcap工具列出特定程序運行所需的功能:
$ getcap /usr/bin/ping
/usr/bin/ping = cap_net_raw+ep
雖然權限控制機制為進程提供了一部分可用的 root 權限,但它不夠靈活。如果您需要對權限進行更嚴格的控制,可以考慮使用一種稱為強制訪問控制 (MAC) 的訪問控制類型。
強制訪問控制
Linux 傳統上支持自主訪問控制 (DAC)。DAC 是一種訪問控制類型,它根據主體的身份和/或所屬組(實際上就是我們習慣使用的用戶和組標志)來限制對對象的訪問。
另一種訪問控制稱為強制訪問控制(MAC)。MAC 是指操作系統限制主體訪問或對客體執行某種操作的能力的一種訪問控制類型。
MAC 通過 Linux 安全模塊 (LSM) 在內核中實現,該框架允許 Linux 內核支持多種計算機安全模型。
實現強制訪問控制的兩個最著名的 Linux 安全模塊是 SELinux 和 AppArmor:
- SELinux 是最流行(且最復雜)的 MAC 實現之一,最初由 NSA 開發,如今用于 Android 和 Fedora 等更大的項目。
- AppArmor 也是一種流行且更加用戶友好的 MAC 實現,由 Canonical 支持并用于一些 Linux 發行版,如 Ubuntu 和 Debian。
因此,如果您需要對進程權限進行細粒度的控制,您應該考慮使用 MAC 機制。
但有時限制權限不足以保護系統免受易受攻擊的應用程序的攻擊。沙盒可以用來緩解這種情況。
應用程序沙盒
沙盒可以將應用程序與系統的其余部分隔離。
Linux 內核中最古老的沙盒機制可能是chroot。但它在安全性方面用處不大,因為它只能隔離文件系統。
虛擬化是應用程序沙盒的另一種形式,但成本太高,尤其是在嵌入式系統中。
目前,嵌入式 Linux 中沙盒應用程序的兩種可能解決方案是容器和可信執行環境 (TEE)。
容器
Linux 容器是一個極簡文件系統,僅包含運行特定應用程序或應用程序組所需的軟件組件。容器與系統其他部分完全隔離運行,僅共享內核。
容器運行時實現利用了 Linux 內核提供的一些功能,包括:
- 命名空間:隔離 Linux 上進程的執行(PID、用戶、網絡連接、掛載點等)。
- cgroups:允許按進程或進程組劃分系統資源(CPU、內存、I/O)。
- seccomp:允許限制進程可以執行的系統調用。
有幾種工具可用于管理 Linux 中的容器,包括 LXC、Systemd-nspawn、Podman 和 Docker。
容器本身并不安全,但如果配置得當,我們可以限制容器內各個進程的權限,并控制它們之間的通信,從而減少攻擊面,提高系統的安全性。
與安全模塊(例如 AppArmor 或 SELinux)結合使用,我們可以大大增強系統的安全性。
但在基于容器的系統中,如果內核被攻破,整個操作系統都將面臨風險。在這種情況下,可信執行環境(TEX)是另一層安全保障,可以幫助防止這種情況發生。
可信執行環境
可信執行環境 (TEE) 是一種環境,其中執行的代碼和訪問的數據在機密性(沒有人可以訪問數據)和完整性(沒有人可以更改代碼及其行為)方面受到隔離和保護。
在具有 TEE 的系統中,不可信應用程序 (UA) 在富執行環境 (REE) 上運行,可信應用程序 (TA) 在可信執行環境 (TEE) 上運行。只有在 TEE(安全環境)上運行的可信應用程序才能完全訪問主處理器、外設和內存。硬件隔離可保護 TA 免受在主操作系統(非安全環境)上運行的不可信應用程序的攻擊。
我們需要硬件支持來實現 TEE,這樣我們就可以對硬件(總線、外設、內存區域、中斷等)進行分區和隔離,以防止不受信任的應用程序訪問受保護的資源。大多數現代處理器都內置了此功能(例如 ARM 的 TrustZone、RISC-V 的 MultiZone 和 Intel SGX)。
我們身邊的許多設備都使用了可信執行環境 (TEE),包括智能手機、機頂盒、視頻游戲機和智能電視。目前有一些商業化的 TEE 實現,例如 Kinibi、QSEE 和 iTrustee,以及一些開源實現,例如 Trusty 和 OP-TEE。TEE 可以很好地解決沙盒應用、加密密鑰的存儲和管理、憑證和敏感數據的存儲和管理,以及數字版權信息的保護問題。
盡管我們已經看到了各種緩解措施,但一個擁有數百萬行代碼的操作系統肯定存在錯誤和漏洞!對于嵌入式系統和連接設備來說,建立更新系統至關重要,因為安全性是產品的關鍵特性。
更新系統應在產品開發的早期階段進行設計,如果可能的話,應具有 OTA(無線)功能。
實施良好的更新系統給產品開發帶來了一些真正的挑戰,包括通信協議的安全性、更新過程的原子性、防電源故障、帶寬和存儲使用、回滾功能等。
嵌入式 Linux 的更新系統可以采用一些策略,包括:
- 基于應用程序:易于實現,但操作系統的其余部分怎么辦?
- 基于包:更新圖像很小,但更新是非原子的,并且包依賴性可能是一個問題。
- 基于圖像:使用 A/B 機制是一個很好的解決方案,問題可能是帶寬和存儲使用情況。
- 基于容器:另一個不錯的選擇,有助于實現原子、電源故障安全、使用更少帶寬、速度更快、停機時間最短且具有回滾能力的更新系統。
如果你正在進行 OTA 更新,你的設備需要網絡連接(Wi-Fi、以太網等)。這意味著網絡接口會增加系統的攻擊面,你需要增加更多安全層來防御攻擊。
網絡安全
這里的規則很簡單:盡可能減少攻擊面。但這并不意味著實施起來很容易。但我們可以先關注一些容易實現的目標。
例如,關閉所有未使用/不需要的 TCP/UDP 端口(nmap等工具可以提供幫助),禁用所有未使用的協議(例如 IPv6、PPP 等),設置防火墻規則以防止入站/出站連接,防止 DoS 攻擊,防止端口掃描等。
如果您需要與外部設備通信,請始終使用安全連接(VPN、反向 SSH、TLS、HTTPS 等),優先使用公鑰認證進行遠程連接并禁用以 root 身份登錄。
最后,有幾種技術可以提高網絡安全,我可以寫一整篇文章來闡述。我的目的只是提高大家對這個話題的認識,確保我們不會忽視它。
結論
這真是一段瘋狂的旅程!在本文的第一部分,我們討論了一些安全概念、威脅建模、安全啟動、代碼和數據加密、加密密鑰以及密鑰存儲技術。在第二部分,我們討論了安全編碼、靜態分析工具、運行時保護、模糊測試工具、權限、Linux 功能、強制訪問控制、沙盒、更新系統以及網絡安全。
雖然我沒有深入研究這些技術的實現,但我想談談我們必須降低風險并實現更安全的嵌入式 Linux 設備的概念和資源。
在安全領域,有一個“縱深防御”的概念,這意味著我們需要始終擁有不止一層或多種類型的防御。想象一下,你是一座城堡的國王。你會如何保護你的城堡?你可以把城堡建在山頂上,建造高大的城墻,在城堡周圍設置水壩,在城墻上設置弓箭手,在城堡內安排戰士等等。這些都是層層防御。如果攻擊者突破了一層防御,將不得不面對下一層,以此類推。
在開發嵌入式 Linux 設備時我們可以應用相同的概念!
說到底,100% 安全的系統是不存在的。攻擊者只需一個漏洞就能攻陷設備。問題在于我們想讓這個過程變得多么艱難。
因此,我們在設計時應該充分考慮安全性,并充分考慮其中的利弊。一個系統應該“足夠安全”。我們應該遵循良好的安全實踐,了解可用的技術和工具,并在需要時使用它們。
讓我們保護我們的嵌入式 Linux 設備!