安全
本文包含了加固 Arch Linux 系統的常用建議與最佳實踐。
概念
- 收緊安全措施有可能達到使系統無法使用的程度。安全性與便利性需要得到平衡。訣竅在於建立一個安全且有用的系統。
- 最大的威脅是(並且一直都會是)用戶。
- 最小權限原則:系統的每一部分應該只能訪問到它確實需要的東西,除此之外的則不可以。
- 縱深防禦:多個獨立的層次能帶來更好的安全性。當一層防護被攻破時,另一層應該能夠阻止攻擊。
- 保持一點點的偏執和多疑。如果有件事看起來太好了,不像是真的,那可能確實如此。
- 永遠無法令系統 100% 安全,除非把機器從網絡上斷開,關掉電源,鎖進保險柜,用混凝土封住並不再使用它。
- 為失敗做好準備。預先為安全措施被攻破的情況制定可供執行的計劃。
密碼
密碼是一個安全系統的關鍵。它可以保護你的用戶帳戶、加密的文件系統和 SSH/GPG 密鑰。密碼也是讓計算機信任使用者的主要方式,所以安全性的很大一部分就在於選擇高強度的密碼並保護它們不被洩露。
選擇安全的密碼
密碼必須足夠複雜,不能輕易地被猜中(比如和個人信息有關的密碼),也不能輕易地被社會工程或暴力嘗試等方法破解。強密碼的要點在於長度和隨機性。在密碼學中,密碼的質量被稱為它的熵安全性。
不安全的密碼包括:
- 個人可識別信息(如:狗的名字,出生日期,區號,最喜歡的視頻遊戲)
- 對單詞簡單地替換一些字符(如:
k1araj0hns0n),因為現代字典攻擊可以輕鬆對付它們 - 在基本單詞或常見字符串的前後加上數字,符號或其他字符(如:
DG091101%) - 常見句子或詞典中單詞的序列(如:
photocopyhauntbranchexpose),包括對其字符進行替換(如:Ph0toc0pyh4uN7br@nch3xp*se) - 任何一個最常見的密碼
最好的選擇是由隨機來源生成的長密碼(越長越好)。使用長密碼很重要。弱哈希算法會使得一個8字符密碼的哈希值在幾小時之內便被攻破。
像 pwgen包 或 apgAUR 這樣的工具可生成隨機密碼,不過這些密碼可能很難記住:為了記住它們,一種方法(僅針對經常使用的密碼)是生成一個長密碼並記住一小段(這一小段要能保證最低限度的安全),暫時把完整的密碼寫下來。在一次次的密碼輸入過程中,嘗試著記住從一小段到一大段乃至全部密碼,隨著時間推移,密碼就會隨著肌肉記憶根深蒂固。這種方法很難,但是能保證密碼不會出現在破解用的字典裡,也可以抵禦「智能地」組合單詞並替換部分字符的暴力破解手段。
除了密碼管理,keepassxc包 還提供密碼/口令生成功能。用戶可以在圖形用戶界面中自定義生成密碼。還支持基於字典的口令。
還有個方法可以產生安全性好的、看起來隨機的密碼,那就是從一句句子的每一個詞中提煉出一個符號。
例如 「the girl is walking down the rainy street」 這句話可以轉換為 t6!WdtR5 或是更加複雜的 t&6!RrlW@dtR,57。
這種方法可以更為簡單地幫助記憶密碼,但是請注意,不同字母出現在單詞開頭的概率不同 (Wikipedia:字母頻率)。
另外一種有效的技術是寫下隨機生成的密碼並將其存儲在安全的地方,例如錢包、挎包或文件保險箱中。不少人在保護其物理貴重物品免受盜竊方面通常做得很好,並且與數字安全實踐相比,大多數人更容易理解物理安全最佳實踐。
將助記符和隨機技術結合起來,通過密碼管理器保存長的隨機生成的密碼也非常有效。密碼管理器需要用一個易記的「主密碼」來訪問,這個密碼只能用於此目的。主密碼必須記住,絕不能保存。這就要求在系統上安裝密碼管理器,以便輕鬆訪問密碼(根據情況,這可以被視為不方便或安全特性)。一些密碼管理器還有智慧型手機應用,可以用來顯示用於在沒有安裝該密碼管理器的系統上進行手動輸入的密碼(如果這是常見的使用情況,那麼你仍然可以為每個服務使用易於輸入但安全的密碼,而不是完全隨機的密碼,參見下文)。注意,如果你忘記了主密碼,密碼管理器就引入了一個單點故障。
有些密碼管理器根據主密碼和你想要登錄的服務名稱計算包含的密碼,而不是加密它們,使得在新的系統上無需同步任何數據也可以使用它。
使用一長串相互無關的單詞作為密碼或許是有效的方法。原理在於,如果使用足夠長的短語,從密碼長度所獲得的熵就可以抵消使用字典詞彙而失去的熵。這個 XKCD 漫畫描繪了此方法中對於熵的權衡,考慮到短語中每個單詞可能的單詞集的限制。如果你使用的單詞集很大(數千個單詞)並且您從中選擇 5-7 個甚至更多隨機單詞,那就算攻擊者知道你所選擇的可能單詞集和選擇的單詞數量,這種方法仍能提供很大的熵。參見Diceware。
參閱 The passphrase FAQ 或 Wikipedia:Password strength ,獲取額外背景信息。
維護密碼安全
一旦你選擇了一個強密碼,就一定要保證它的安全。當心鍵盤記錄器(軟體層面 和 硬體層面),屏幕記錄器,社會工程,肩窺,並避免對不同的伺服器(網站)使用重複密碼,以防止不安全的伺服器洩漏超出其範圍的信息。密碼管理器可以幫助管理大量複雜密碼:將密碼從管理器複製粘貼到其他程序中時,記住每次粘貼完都清除複製緩衝區,並確保密碼不會「意外地」保存在任何類型的文件中(例如,不要將它們粘貼在普通的終端命令中,因為這些命令會存到 .bash_history 之類的文件裡)。
最好不要因為安全性強的密碼難記而選擇不安全的密碼,密碼是它們之間的一種平衡。與擁有許多相似的弱密碼相比,更好的做法是建立一個加密的安全密碼資料庫,資料庫由密鑰和一個強主密碼保護著。把密碼寫下來也許同樣有效[1],可以避開軟體中的潛在漏洞,同時也需要保證物理安全。
衡量密碼強度的另一個指標是它不能夠被輕易從其他地方恢復。
如果你使用與登錄密碼相同的磁碟加密密碼(這在登錄時自動掛載加密分區或目錄很有用),請確保 /etc/shadow 也在加密分區上,或者/並 使用強哈希算法(即 sha512/bcrypt,而不是 md5)來存儲密碼哈希(詳細信息請參閱 SHA password hashes)。
passwd 執行一次密碼修改,即可應用新的默認算法。如果要備份密碼資料庫,請勿將備份的副本存儲在密碼保護之下(比如存儲在加密的驅動器或需要身份驗證的遠程存儲服務),而解鎖副本的密碼又存儲在副本中,這樣在需要時將無法訪問它(相當於把房間的鑰匙鎖在了房間裡)。一個有用的技巧是,使用主密碼的簡單哈希來加密存儲密碼資料庫的驅動器或帳戶。維護一份記錄備份位置的列表:如果有一天你覺得主密碼已被洩露,一是要更改所有資料庫備份的密碼,二是要使用從新主密碼派生的新哈希來保護存有資料庫的位置。
以安全的方式控制資料庫的版本可能非常複雜:如果你這樣做,那你必須有辦法更新所有資料庫版本的主密碼。主密碼洩露時,你可能並不能馬上知道:為了降低其他人在你意識到主密碼洩露之前發現密碼的風險,你可以選擇定期更改主密碼。如果你擔心自己失去了對資料庫副本的控制權,則需要根據主密碼的熵,在暴力破解主密碼所需的時間內更改資料庫副本中包含的所有密碼。
密碼的散列值
散列函數(又稱哈希函數)是一種單向不可逆函數。其設計旨在於確保無法通過輸出結果(散列值,又稱哈希值)逆向推導出原始輸入。優秀的散列算法(又稱哈希算法)需要具備極強抗碰撞性(即很難找到兩個不同輸入產生相同的散列值)與雪崩效應(輸入微調即導致輸出結果劇烈變化)。
密碼散列函數(Cryptographic hash function;例如:bcrypt)則專用於存儲密碼,為防止攻擊者通過彩虹表、暴力窮舉等手段破解密碼,密碼散列函數除了前述不可逆性外往往使用密鑰拉伸技術或加鹽(Salting)機制。
密鑰派生函數(Key derivation function, KDF;例如:yescrypt、scrypt、PBKDF2、Argon2)是從一個或多個值(如主密鑰、密碼)中派生出一個或多個安全密鑰(如 AES 密鑰、密碼散列值)的加密算法。現代 KDF 使用密鑰拉伸技術,通過增加算法執行步驟資源消耗,使派生出的密鑰在抗暴力破解能力上更優,因此,KDF 可適用於多種應用場景,其中便包括作為密碼散列函數。
默認情況下,Arch 將用戶密碼散列值存儲在僅 root 可讀的 /etc/shadow 文件中,與存儲在所有人可讀的 /etc/passwd 文件中的其他用戶參數分開,請參閱 Users and groups#用戶信息存儲。另請參閱 #限制 root 權限。
使用 passwd 命令來設置密碼,該命令會調用系統的 crypt 函數對密碼進行密鑰拉伸,然後將它們保存在 /etc/shadow 中。密碼在處理中還會被加鹽(salting),以抵禦彩虹表攻擊。若需了解其底層原理,參見密碼在 Linux 中的存儲方式(理解 shadow 工具集的散列機制)。
由於密碼散列值遵循特定的格式,因此可針對後續新執行的 passwd 命令配置不同的加密方法與參數。這也意味著,/etc/shadow 文件中存儲的各個用戶散列值可以是系統所支持的各種散列函數的混合體。
若需了解有關格式、散列方法和參數的更多信息,請參考 crypt(5)。
/etc/login.defs 文件用於配置默認密碼散列方法 ENCRYPT_METHOD YESCRYPT 及其參數 YESCRYPT_COST_FACTOR。
例如,調高默認的 YESCRYPT_COST_FACTOR 參數值,將導致從密碼推導哈希值所需的計算時間呈對數級增長。此時間增長對試圖破解密碼的第三方和進行用戶登錄認證的系統同樣有效。
相比之下,SHA-512 哈希函數的計算時間受其參數呈線性影響。關於 Arch 之前的默認配置,請參考 SHA password hashes。需要注意,yescrypt 算法在內部結合了 SHA-256、HMAC 和 PBKDF2 來計算密碼哈希,其主要目的在於融合這些經過廣泛測試的常用函數的優點,以提升抗攻擊能力。由於 SHA 在各類場景中的廣泛應用,硬體層面已對其提供了加速支持。這意味著純 SHA 哈希的計算性能已大幅提升,因而直接將其用作密碼哈希函數已逐漸被時代淘汰。
禁用空密碼
允許空密碼進行身份驗證會擴大系統的攻擊面。例如CVE-2020-27780 或 dirtyfrag (CVE-2026-43284 , CVE-2026-43500)——後者即為通過惡意篡改 /etc/shadow 並利用 pam_unix 中啟用的 nullok 選項來實現攻擊。
若要禁用空密碼,請移除 /etc/pam.d/system-auth 的 nullok 選項:
/etc/pam.d/system-auth
auth [success=1 default=bad] pam_unix.so try_first_pass
若要列出當前密碼為空的用戶,請執行:
# getent shadow | awk -F: '($2=="") {print $1}'
若輸出結果中包含本地系統無對應帳號的用戶(例如通過 OpenLDAP 進行身份驗證的用戶),這些用戶將不受移除 nullok 選項的影響。
用 pam_pwquality 強制使用強密碼
PAM 為「可插拔身份驗證模塊」(Pluggable Authentication Modules)的縮寫。pam_pwquality 提供針對字典攻擊的保護,並可用於配置在整個系統中實施的密碼策略。它基於 pam_cracklib,故也向後兼容其選項。
安裝 libpwquality包 軟體包。
舉個例子,假設要強制執行下面的策略:
- 如果密碼錯誤,則提示 2 次輸入密碼(retry 選項)
- 最小長度為10個字符(minlen 選項)
- 輸入新密碼時,新密碼應至少有 6 個字符與舊密碼不同(difok 選項)
- 至少 1 個數字(dcredit 選項)
- 至少 1 個大寫字母(ucredit 選項)
- 至少 1 個小寫字母(lcredit 選項)
- 至少 1 個除上述之外的其他字符(ocredit 選項)
- 不能包含單詞 "myservice" 和 "mydomain"
- 為 root 應用此策略
編輯 /etc/pam.d/passwd 文件,把它改成:
#%PAM-1.0 password required pam_pwquality.so retry=2 minlen=10 difok=6 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1 [badwords=myservice mydomain] enforce_for_root password required pam_unix.so use_authtok yescrypt shadow
password required pam_unix.so use_authtok 用來告訴 pam_unix 模塊不要顯示輸入密碼的提示符,而採用 pam_pwquality 所提供的。
更多信息可以參考 pam_pwquality(8) 和 pam_unix(8) 手冊頁。
CPU
微碼
關於如何為CPU微碼安裝重要安全更新的信息見微碼。
硬體漏洞
有些 CPU 存在硬體漏洞。這些漏洞的列表見關於硬體漏洞的 Linux 內核文檔,其中也包含了修補方法選擇指南,有助於針對特定場景對內核自定義,從而修補這些漏洞。
要檢查是否受到已知漏洞影響,請運行:
$ grep -r . /sys/devices/system/cpu/vulnerabilities/
大部分情況下,更新內核和微碼能夠修補漏洞。
同步多線程(超線程)
同步多線程(SMT),在英特爾 CPU 上又稱超線程,這一硬體功能可能是 L1 Terminal Fault 與微架構數據採樣(Microarchitectural Data Sampling)漏洞的來源。 Linux 內核和微碼更新含有針對已知漏洞的補丁,但是如果存在不受信任的虛擬化客戶機,則對於某些 CPU 可能仍然需要禁用 SMT。
SMT 往往可以在系統固件中關閉。更多信息見主板或系統文檔。通過添加以下內核參數,也可以在內核中禁用 SMT:
mitigations=auto,nosmt
內存
加固 malloc
hardened_mallocAUR 是 glibc 函數 malloc() 加固過的替代品。此項目最開始由 GrapheneOS 的 Daniel Micay 開發,集成在 Android 的 Bionic 和 musl,他也內置了對 x86_64 標準 Linux 發行版的支持。
存儲
靜態數據加密
靜態數據加密,最好是使用強密碼的全磁碟加密,是保護數據免受物理恢復的唯一方法。這在計算機關閉或相關磁碟卸載時提供了數據機密性。
然而,一旦計算機啟動並且驅動器被掛載,其數據將變得與未加密的驅動器一樣容易受到攻擊。因此,最佳做法是在不再需要數據分區時立即卸載它們。
你還可以使用存儲在 TPM 中的密鑰對驅動器進行加密,儘管它過去存在可以通過總線嗅探攻擊提取密鑰的漏洞。
某些程序,如 dm-crypt,允許用戶將 Loop file 加密為虛擬卷。當系統只有特定的部分需要加密時,這種方法可以替代全盤加密。
雖然數據靜態加密wiki 中比較的基於塊設備或文件系統的加密類型對於保護物理媒體上的數據很有用,但大多數不能用於保護無法控制的遠程系統上的數據(例如雲存儲)。在某些情況下,個別文件加密會很有用。
以下是一些加密文件的方法:
- age包 是一款簡單易用的文件加密工具。該工具支持多接收者模式以及使用 SSH 密鑰進行加密,非常適合用於安全文件共享。
- 一些歸檔和壓縮工具還提供基本的加密功能。由於部分工具出於兼容性考慮可能會使用弱加密算法(尤其是在使用 zip 文件格式時[2]),因此在未充分了解特定工具及其配置的安全屬性前,切勿盲目依賴此類功能。典型示例包括7-zip(
-p參數)和zip包(-e參數)。 - GnuPG 亦可用於加密文件。然而,安全地使用該工具需要大量專業培訓與知識儲備[3][4],且其包含的 GnuPG 專屬拓展與 OpenPGP 標準並不兼容。為防止常見的用戶操作失誤,GunPG 維護者建議使用圖形化界面程序 kleopatra包,而非 GPG 命令行工具[5]。
文件系統
如果用 sysctl 啟用了內核的 fs.protected_hardlinks 和 fs.protected_symlinks 選項,內核就可以防止出現硬連結和軟連結(符號連結)相關的安全問題。因此將全局可寫的目錄獨立出來不再具有安全方面的優勢。
使包含全局可寫目錄的文件系統保持獨立 仍然可以作為一種防止惡意程序填充垃圾內容使磁碟空間耗盡的粗略手段。但是,把 /var 或 /tmp 所在分區塞滿也足以使系統停止響應。處理這種問題的更靈活的機制是存在的(比如磁碟配額),並且某些文件系統自身就帶有相關功能(Btrfs 的子卷可以設置配額)。
掛載點
根據最小權限原則,掛載文件系統時應該採用最為嚴格的掛載選項(在不損失功能的情況下)。
相關的掛載選項有:
-
nodev: 文件系統中,禁止解釋任何字符或屏蔽特殊設備。 -
nosuid: 禁止 set-user-identifier 或 set-group-identifier 標誌位生效。 -
noexec: 禁止文件系統裡的任何二進制文件直接運行。- 在
/home上設置noexec選項會禁用可執行腳本,影響 Wine* 、PyCharm 、 Steam 、 .NET等軟體正常運行。 - 部分軟體包(比如編譯 nvidia-dkms包)可能需要
/var目錄下有exec權限。
- 在
用於存放數據的文件系統應該堅持使用 nodev、nosuid 和 noexec 掛載。
可能的文件系統劃分參考:
/var/home/dev/shm/tmp/boot
無 SUID
若能接受使用 run0 替代 sudo 以及移除所有其他 SUID 和文件系統能力(Capabilities)而帶來部分功能缺失,那麼將包括根系統在內的所有文件系統都掛載為 nosuid 是完全可行的。
首先,找出系統中的 SUID 和 SGID 文件。
接著,排查帶有文件系統能力(Capabilities)的二進制文件:
$ getcap -r /
由於移除了 nvidia-modprobe 的 SUID 權限,配備 NVIDIA 顯卡的系統需要添加以下配置單元以進行補償:
/etc/systemd/system/local-nvidia.service
[Service] Type=simple ExecStart=/usr/bin/nvidia-modprobe -m -l -s [Install] WantedBy=multi-user.target
在無 SUID 的配置中,還可以全局啟用NoNewPrivileges=yes,這同樣會禁用 SUID/SGID 以及文件系統的能力(Capabilities):
/etc/systemd/system.conf.d/local-nnp.conf
[Manager] NoNewPrivileges=yes
快照
當使用 Btrfs、LVM 或 ZFS 等文件系統快照功能時,必須注意:快照可能會保留用戶認為已被刪除的敏感信息。在配置了 Snapper 等自動快照工具時尤為如此,因為它們會定期或在特定系統事件發生時自動創建快照。以下是一些 /home/ 目錄下的敏感信息如何在快照中殘留的典型場景:
- 已刪除的文件和目錄:即便文件或目錄已從當前文件系統中刪除,它們仍可能存在於歷史快照中。在大多數情況下這符合備份預期,但需仔細考量是否應當保留如
.local/share/Trash/、.history等文件和目錄。 - 臨時文件與緩存:應用程式生成的臨時文件和緩存數據可能會被包含在快照中。例如,保存在加密目錄中的文件在被打開時,可能會產生縮略圖(
.cache/thumbnails)或工作副本,這些內容進而可能會被寫入快照。同理,瀏覽記錄(如.mozila/、.config/chromium/等)也可能在被徹底清理之前就已經被保存在了某次快照中。
如果系統支持,建議考慮將此類目錄完全排除在快照範圍之外。例如,若使用 Btrfs,可根據實際需求,為 .cache/、.local、.var/或任何其他目錄創建獨立的子卷(Subvolume)。
.local/share/Trash 移動到獨立的子卷可能會導致回收站功能失效,例如在GNOME/文件中。文件訪問權限
默認的文件權限對幾乎所有文件都賦予了讀權限,修改文件權限可以在取得了非 root 帳戶(如http 或 nobody 帳戶)的攻擊者面前隱藏有價值的信息。
您可以使用 chmod 取消組和其他人的所有權限:
例如:
# chmod go-r path_to_hide
g(或者如果已經運行,則使用chmod g+r path重新添加權限)。需要考慮的一些路徑是:
-
/boot:引導目錄,其中可能包含傳統的 vmlinuz 和 initramfs 鏡像,或是統一內核鏡像(UKI)。請注意,在使用 systemd 的 GPT 分區自動掛載時,默認會採用更安全的權限設置。 -
/etc/nftables.conf:nftables 配置,適用於 nftables包 和 iptables-nft包。 -
/etc/iptables: 舊版 iptables 配置,適用於iptables-legacy包 。
可以修改默認的 Umask 0022 來為新建的文件提高安全性。NSA RHEL5 安全指南建議將 umask 設置為 0077 以獲得最充分的安全性,這將使得新文件無法被創建者之外的用戶讀取。要修改 umask,參見 Umask#Set the mask value。如果你使用 sudo,可以考慮將其配置為使用默認的 root umask。
SUID 和 SGID 文件
了解系統中哪些文件啟用了 Setuid(SUID)或 Setgid(SGID)權限至關重要。若要搜索所有設置了 SUID 或 SGID 權限的文件,請運行:
$ find / -perm "/u=s,g=s" -type f 2>/dev/null
常見的已設置 SUID 權限的相關文件示例:
- unix_chkpwd
- chage、expiry、gpasswd、passwd、sg(shadow包)
- fusermount3、fusermount2
- pkexec
- ssh-keysign
- chfn、chsh、mount、newgrp、umount、wall、write(util-linux包)
- sudo、sudo-rs包、doas、su、su-rs、ksu
- firejail
- dbus-daemon-launch-helper
- chromium-sandbox
- Xorg.wrap
這類可執行文件最顯著的風險在於可能存在特權提升(提權)漏洞,具體參考 Setuid 的安全影響[7][8][9]。
未歸 root 所有但設置了 SUID 權限的文件,或是設置了 SGID 權限的文件,「通常」潛在影響較小,但如果存在漏洞,理論上仍可能造成不小的危害。通常情況下,可以通過分配能力(Capabilities)來完全避免使用 SUID 或 SGID。
備份
備份對於安全至關重要,因為通過備份,系統可以在遭遇勒索軟體、數據損壞、誤刪除以及系統受損時進行恢復,從而避免永久性的數據丟失。參見系統備份
SATA SSD 凍結模式
SATA 固態硬碟(SSD)在從睡眠狀態喚醒時,極易受到安全擦除單元(ATA SECURITY ERASE UNIT)命令的攻擊。若需降低此風險,參閱固態硬碟#從睡眠中喚醒時設置 SATA SSD 為凍結模式。
帳戶設置
不要日常使用 root 帳戶
根據最小權限原則,不要日常使用 root 帳戶。給每個使用系統的人建立一個沒有特權的用戶帳戶。有關臨時獲取特權的方法,參見應用程式列表/安全#提權。
在失敗的登錄嘗試後強制延時一段時間
將下方的行添加至 /etc/pam.d/system-login 即可在失敗的登錄嘗試後延時至少 4 秒:
/etc/pam.d/system-login
auth optional pam_faildelay.so delay=4000000
4000000 是延時的微秒數。
除 pam_faildelay 外,其他 PAM 模塊也可以建議此類延遲;如果多個模塊同時指定了延遲,PAM 將採用其中最長的時間。
特別是 pam_unix 和 pam_faillock,它們默認會設置至少 2 秒的最低延遲。
若要完全移除該延遲,你需要為這些模塊的任何 auth 配置行添加 nodelay 參數,例如:
/etc/pam.d/system-auth
auth [success=1 default=bad] pam_unix.so try_first_pass nullok nodelay
在三次登錄嘗試失敗後封鎖用戶
至 pambase包 20200721.1-2時,pam_faillock.so 默認啟用,在15分鐘內3次失敗的登錄嘗試之後會封鎖用戶10分鐘(見 FS#67644)。這一封鎖只適用於密碼認證(如登錄及 sudo),通過 SSH 的公鑰認證仍然會被接受。為防止徹底拒絕服務,該封鎖對於 root 禁用。
要解鎖用戶,執行:
$ faillock --reset --user username
默認情況下,封鎖機制為每個用戶一個文件,位於 /run/faillock/。刪除或清空此文件及可解鎖該用戶——該目錄是由 root 所有,但文件是由該用戶所有,故 faillock 命令只會清空文件,因此並不需要 root。
pam_faillock.so 模塊可通過文件 /etc/security/faillock.conf 配置。封鎖參數:
-
unlock_time——封鎖時間(單位為秒,默認10分鐘)。 -
fail_interval——導致封鎖的失敗嘗試時間範圍(單位為秒,默認15分鐘)。 -
deny——封鎖前允許的登錄失敗次數(默認為3)。
deny = 0 會禁用封鎖。默認情況下,重新啟動後所有用戶鎖都會丟失。如果攻擊者可以重新啟動計算機,則鎖定持續存在會更安全。要使鎖定持續存在,請將 /etc/security/faillock.conf 中的 dir 參數更改為 /var/lib/faillock 。
}systemctl edit polkit-agent-helper@.service 為其 systemd 服務單元創建一個配置補丁,並添加如下內容:
[Service] ReadWritePaths=/var/lib/faillock
更改無需重啟即可生效。更多配置選項見 faillock.conf(5) ,如啟用 root 帳戶封鎖、在中心化登錄(如 LDAP)情況下禁用等。
限制進程數量
在有很多用戶或存在不可信用戶的系統上,限制每個用戶同時可運行的進程數很重要,這樣可以防止 fork bombs 以及其他拒絕服務攻擊。/etc/security/limits.conf 配置文件決定了每個用戶或組可以運行的進程數,默認情況下為空(除了有用的注釋)。將以下行添加到此文件將限制所有用戶每位最多運行 100 個活動進程,除非他們使用 prlimit 命令將此次會話的最大值顯式地提高到 200。可以根據用戶應當運行的進程數量或當前管理的系統的硬體條件來確定這些值。
* soft nproc 100 * hard nproc 200
當前每個用戶運行的進程數量可以使用 ps --no-headers -Leo user | sort | uniq -c 查看。這可以幫助確定合適的用戶進程限額。參見en:limits.conf。
顯示伺服器
儘量使用 Wayland 代替 Xorg 作為顯示伺服器。Xorg 的設計早於現代安全實踐,並且被許多人認為是不安全的。例如,Xorg 應用程式可以在不活動時記錄擊鍵。
在 Wayland 中,Xwayland 兼容層將自動使用無 root 權限的 Xorg。如果必須運行 Xorg,建議避免以 root 身份運行,參考Xorg#沒有 root 權限的 Xorg,並確保其不監聽抽象套接字(Abstract sockets)和 TCP 套接字。
限制 root 權限
按照系統的設計,root 用戶是系統中最強大的用戶。審計 root 用戶帳戶也很困難。因此,重要的是儘可能多地限制root用戶帳戶的使用。有多種方法可以保持 root 用戶的權力,同時限制其造成損害的能力。
用 sudo 替代 su
- sudo 記錄了普通權限用戶運行每個特權命令的日誌。
- root 用戶的密碼不需要告知每個請求 root 權限的用戶。
-
sudo可以防止用戶意外地以 root 身份執行無需該權限的命令,因為 sudo 並沒有為 root 創建完整的終端。這符合最小權限原則。 - 可以為單個用戶啟用單個程序的 root 權限,而不用為了運行一個程序啟用該用戶對 root 的完整訪問權。
有關更多信息,參見Sudo#配置。
使用 sudo 編輯文件
參見Sudo#編輯文件。另外,你也可以使用像rvim或rnano這樣限制了部分高級功能的的編輯器,因而可以安全地在 root 環境下運行。
限制 root 登錄
正確配置 sudo 後,完全的 root 權限就可以被嚴格限制或停用,且不會損失太多可用性。要禁用 root 而允許使用 sudo,可以運行 passwd -l root。
僅允許特定用戶
PAM 的 pam_wheel.so 模塊可以做到僅允許 wheel 組中的用戶使用 su包登錄。參見Su#su 和 wheel 用戶組。
拒絕 SSH 登錄
即使你不想禁止 root 用戶在本地登錄,也最好禁止 root 通過 SSH 登錄。這樣做的目的是在用戶可以在遠程完全破壞系統之前添加額外的一層安全保護。
使用 access.conf 指定允許的登錄組合
+:(gdm):LOCAL規則來實現。[10]
當用戶嘗試通過 PAM進行登錄時,系統會檢查 /etc/security/access.conf 文件,並從中查找第一個 與其登錄屬性匹配的組合。隨後,系統將根據該匹配規則決定允許還是拒絕此次登錄嘗試。
+:root:LOCAL -:root:ALL
我們可以為特定的組和用戶設置規則。在下面的示例中,用戶 archie、wheel 組和 adm 組的所有成員都被允許進行本地登錄,而所有其他登錄嘗試均被拒絕:
+:archie:LOCAL +:(wheel):LOCAL +:(adm):LOCAL -:ALL:ALL
更多信息請參閱 access.conf(5)
強制訪問控制
強制訪問控制(Mandatory Access Control, MAC)是一種安全策略,它與 Arch 以及大部分 Linux 發行版默認使用的 自主訪問控制 (Discretionary Access Control, DAC)有很大的不同。MAC 本質上是對照著一個安全規則集,檢查程序的每一個可能對系統造成影響的操作。與 DAC 方式相比,用戶不能修改 MAC 的規則集。使用幾乎任 何強制訪問控制系統都將顯著提高計算機的安全性,儘管它們的實現方式存在差異。
基於路徑的MAC
基於路徑的訪問控制是一種簡單的訪問控制形式,它根據文件的路徑提供相應的權限。這種方式有缺點,就是當文件改變路徑以後相應的權限並沒有隨著文件一起移動,或是在給無法訪問的文件添加硬連結將使文件可被訪問。從積極的方面來說,基於路徑的 MAC 可以在更廣泛的文件系統上實現,這與基於標籤的另一種可選方案是不同的。
- TOMOYO Linux 是另一種提供訪問控制的系統,簡單而易用。它的使用方式和內部實現都被設計得足夠簡單,需要的依賴也很少。
基於標籤的MAC
基於標籤的訪問控制意味著每份文件都帶有擴展屬性用於決定它的安全權限。雖然這類系統應該比基於路徑的控制更靈活,但它只適用於支持這些擴展屬性的文件系統。
- SELinux 是一個基於 美國國家安全局(NSA) 的項目,用於提高 Linux 的安全性。它完整實現了 MAC,將系統用戶與角色獨立開來。它實現了一個非常強大的多級 MAC 策略,可以在系統擴大和改變得超出其原始配置時也能輕鬆控制系統。
訪問控制表 (ACLs)
訪問控制列表(Access Control Lists, ACLs)是以某種方式將規則直接附加到文件系統的一種可選方法。ACLs 將程序的實際操作與允許的操作對照,來實現訪問控制。
內核加固
內核自我保護 / 漏洞防護
linux-hardened包 相較於 linux包 使用了基本內核加固補丁集和更多安全相關的編譯時配置選項。也可以使用自定義編譯選項來把握安全性和性能之間的平衡,而不是使用強調安全性的默認選項。
然而需要注意的是,當使用該內核時,某些軟體包(例如throttled包)將無法正常工作。
如果你用了內核代碼樹以外的驅動,比如 NVIDIA,可能會需要切換到它的 DKMS 包。
用戶空間 ASLR 比較
linux-hardened包 包為用戶空間進程提供了改進的 ASLR(Address Space Layout Randomization,地址空間布局隨機化)實現。paxtest包 命令可用於獲取所提供熵的估計值:
64 位進程
linux-hardened 5.4.21.a-1-hardened
Anonymous mapping randomization test : 32 quality bits (guessed) Heap randomization test (ET_EXEC) : 40 quality bits (guessed) Heap randomization test (PIE) : 40 quality bits (guessed) Main executable randomization (ET_EXEC) : 32 quality bits (guessed) Main executable randomization (PIE) : 32 quality bits (guessed) Shared library randomization test : 32 quality bits (guessed) VDSO randomization test : 32 quality bits (guessed) Stack randomization test (SEGMEXEC) : 40 quality bits (guessed) Stack randomization test (PAGEEXEC) : 40 quality bits (guessed) Arg/env randomization test (SEGMEXEC) : 44 quality bits (guessed) Arg/env randomization test (PAGEEXEC) : 44 quality bits (guessed) Offset to library randomisation (ET_EXEC): 34 quality bits (guessed) Offset to library randomisation (ET_DYN) : 34 quality bits (guessed) Randomization under memory exhaustion @~0: 32 bits (guessed) Randomization under memory exhaustion @0 : 32 bits (guessed)
linux 5.5.5-arch1-1
Anonymous mapping randomization test : 28 quality bits (guessed) Heap randomization test (ET_EXEC) : 28 quality bits (guessed) Heap randomization test (PIE) : 28 quality bits (guessed) Main executable randomization (ET_EXEC) : 28 quality bits (guessed) Main executable randomization (PIE) : 28 quality bits (guessed) Shared library randomization test : 28 quality bits (guessed) VDSO randomization test : 20 quality bits (guessed) Stack randomization test (SEGMEXEC) : 30 quality bits (guessed) Stack randomization test (PAGEEXEC) : 30 quality bits (guessed) Arg/env randomization test (SEGMEXEC) : 22 quality bits (guessed) Arg/env randomization test (PAGEEXEC) : 22 quality bits (guessed) Offset to library randomisation (ET_EXEC): 28 quality bits (guessed) Offset to library randomisation (ET_DYN) : 28 quality bits (guessed) Randomization under memory exhaustion @~0: 29 bits (guessed) Randomization under memory exhaustion @0 : 29 bits (guessed)
linux-lts 4.19.101-1-lts
Anonymous mapping randomization test : 28 quality bits (guessed) Heap randomization test (ET_EXEC) : 28 quality bits (guessed) Heap randomization test (PIE) : 28 quality bits (guessed) Main executable randomization (ET_EXEC) : 28 quality bits (guessed) Main executable randomization (PIE) : 28 quality bits (guessed) Shared library randomization test : 28 quality bits (guessed) VDSO randomization test : 19 quality bits (guessed) Stack randomization test (SEGMEXEC) : 30 quality bits (guessed) Stack randomization test (PAGEEXEC) : 30 quality bits (guessed) Arg/env randomization test (SEGMEXEC) : 22 quality bits (guessed) Arg/env randomization test (PAGEEXEC) : 22 quality bits (guessed) Offset to library randomisation (ET_EXEC): 28 quality bits (guessed) Offset to library randomisation (ET_DYN) : 28 quality bits (guessed) Randomization under memory exhaustion @~0: 28 bits (guessed) Randomization under memory exhaustion @0 : 28 bits (guessed)
32 位進程(運行在 x86_64 內核上)
linux-hardened
Anonymous mapping randomization test : 16 quality bits (guessed) Heap randomization test (ET_EXEC) : 22 quality bits (guessed) Heap randomization test (PIE) : 27 quality bits (guessed) Main executable randomization (ET_EXEC) : No randomization Main executable randomization (PIE) : 18 quality bits (guessed) Shared library randomization test : 16 quality bits (guessed) VDSO randomization test : 16 quality bits (guessed) Stack randomization test (SEGMEXEC) : 24 quality bits (guessed) Stack randomization test (PAGEEXEC) : 24 quality bits (guessed) Arg/env randomization test (SEGMEXEC) : 28 quality bits (guessed) Arg/env randomization test (PAGEEXEC) : 28 quality bits (guessed) Offset to library randomisation (ET_EXEC): 18 quality bits (guessed) Offset to library randomisation (ET_DYN) : 16 quality bits (guessed) Randomization under memory exhaustion @~0: 18 bits (guessed) Randomization under memory exhaustion @0 : 18 bits (guessed)
linux
Anonymous mapping randomization test : 8 quality bits (guessed) Heap randomization test (ET_EXEC) : 13 quality bits (guessed) Heap randomization test (PIE) : 13 quality bits (guessed) Main executable randomization (ET_EXEC) : No randomization Main executable randomization (PIE) : 8 quality bits (guessed) Shared library randomization test : 8 quality bits (guessed) VDSO randomization test : 8 quality bits (guessed) Stack randomization test (SEGMEXEC) : 19 quality bits (guessed) Stack randomization test (PAGEEXEC) : 19 quality bits (guessed) Arg/env randomization test (SEGMEXEC) : 11 quality bits (guessed) Arg/env randomization test (PAGEEXEC) : 11 quality bits (guessed) Offset to library randomisation (ET_EXEC): 8 quality bits (guessed) Offset to library randomisation (ET_DYN) : 13 quality bits (guessed) Randomization under memory exhaustion @~0: No randomization Randomization under memory exhaustion @0 : No randomization
手動配置
在 linux-hardened包 之外的內核上,也可以通過使用以下 sysctl 參數來達到相同的效果:
/etc/sysctl.d/51-aslr.conf
vm.mmap_rnd_bits = 32 vm.mmap_rnd_compat_bits = 16
限制訪問 proc 文件系統中的內核指針
將 kernel.kptr_restrict 設置為 1 將針對沒有 CAP_SYSLOG 的普通用戶隱藏 /proc/kallsyms 中的內核符號地址,這使得利用內核漏洞動態解析地址/符號變得更加困難。這對預編譯好的 Arch Linux 內核沒有多大幫助,因為攻擊者可以直接下載到內核包並從那裡手動獲取符號,但如果你正在編譯自己的內核,這可以幫助減輕本地根攻擊。這樣做以後會影響非 root 用戶運行部分 perf包 命令(雖然很多 perf包 功能本身就需要 root 權限)。更多信息請參見 FS#34323。
將 kernel.kptr_restrict 設置為 2 將隱藏 /proc/kallsyms 中的內核符號地址,而忽略用戶的權限。
/etc/sysctl.d/50-kptr-restrict.conf
kernel.kptr_restrict = 1
BPF 加固
BPF 是一種用在運行時動態向內核加載並執行字節碼的系統。它被廣泛應用於許多 Linux 內核子系統中,例如網絡(如 XDP、tc)、跟蹤(如 kprobes、uprobes、tracepoints)以及安全(如 seccomp)。此外,它在高級網絡安全、性能分析和動態跟蹤方面也大有裨益。
BPF 最初是伯克利包過濾器(Berkeley Packet Filter)的縮寫,因為最初的經典 BPF 僅用於 BSD 的數據包捕獲工具。該技術最終演變為擴展 BPF(eBPF),不久後被簡稱為 BPF(不再作為縮寫)。不應將 BPF 與 iptables 或 netfilter 等數據包過濾工具混淆,儘管 BPF 可以用於實現此類數據包過濾工具。
BPF 代碼既可被解釋執行,也可以使用即時編譯器(JIT)進行編譯。Arch 內核在構建時啟用了CONFIG_BPF_JIT_ALWAYS_ON,該選項會禁用 BPF 解釋器,並強制所有 BPF 均使用 JIT 編譯。這使得攻擊者更難利用 BPF 來擴大對 SPECTRE(幽靈)這類漏洞的攻擊。有關更多細節,參見引入 CONFIG_BPF_JIT_ALWAYS_ON 的內核補丁。
內核包含一項針對 JIT 編譯 BPF 的加固特性,該特性可以緩解某些類型的 JIT 噴射(JIT spraying)攻擊,但代價是會損失部分性能,並會使許多 BPF 程序的跟蹤與調試功能失效。可以通過將net.core.bpf_jit_harden設置為1(僅對非特權代碼啟用加固)或2(對所有代碼啟用加固)來開啟此功能。
有關更多信息,參見內核文檔中的 net.core.bpf_* 設置。
-
linux-hardened包 默認將該值設置為
net.core.bpf_jit_harden=2而非0。 - 默認情況下,非特權用戶也可以運行 BPF 程序。若要更改此行為,請設置
kernel.unprivileged_bpf_disabled=1[11]。
ptrace 作用域
ptrace(2) 系統提供了一種手段,使得一個進程(「追蹤者」)可以觀察和控制另一個進程(「被追蹤者」)的執行情況,並檢查或更改被追蹤者的內存和寄存器。ptrace 通常被 gdb、strace、perf、reptyr 等調試及跟蹤工具使用。然而,它也為惡意進程讀取其他進程的數據並獲取控制權提供了可乘之機。
Arch 默認啟用了 Yama LSM ,它提供了一個 kernel.yama.ptrace_scope 內核參數。該參數默認設置為 1(受限模式),這會阻止追蹤者對受限作用域之外的進程執行 ptrace 調用,除非追蹤者擁有特權或具備 CAP_SYS_PTRACE 能力。與傳統權限相比,這在安全上是一次顯著的提升。如果沒有這個模塊,在沒有引入額外的安全層(如pid_namespaces(7))的情況下,以相同用戶運行的各進程之間將毫無隔離可言。
ptrace 的工具,仍可通過以特權進程身份運行它們來實現(例如使用Sudo)。如果無須使用調試工具,可以考慮將 kernel.yama.ptrace
_scope 設置為 2(僅限管理員)或 3(完全禁用 ptrace)以加固系統。
ptrace 才能工作,包括 Wine 環境下的 Easy Anti-Cheat 和 Ubisoft Connect。將此參數設置為 2 或更高可能會導致使用這些方案的遊戲無法啟動。隱藏進程標識符
- 這可能會導致某些應用程式出現問題,例如在沙盒和 Xorg 中運行的應用程式(請參閱解決方法)。
- 當所使用的 systemd包 版本大於 237.64-1 時,這可能會導致 D-Bus、PulseAudio 和 bluetooth 出現問題。
其他用戶的進程通常可以在 /proc 訪問到,而內核有能力向非特權用戶隱藏這些進程,按照此處記錄的方法以 hidepid= 和 gid= 選項掛載 proc 文件系統即可。
這使得入侵者收集正在運行的進程信息變得異常艱難,同樣艱難的還包括判斷是否存在特權運行的守護進程、其他用戶是否正在運行敏感程序,甚至無法捕捉到其他用戶運行的任何程序,更無法捕捉到特定的程序是否正在運行(假設該程序不會因為其自身行為暴露自己),並且作為額外的優勢,那些通過外部參數傳遞敏感信息的、寫得不那麼好的程序現在可以防範本地竊聽了。
由 filesystem包 軟體包提供的 proc 用戶組相當於一個白名單,包含了有權訪問其他用戶進程信息的用戶。如果用戶或服務需要訪問除自身以外的 /proc/<pid> 目錄,請將他們加入該用戶組。
例如,把除了 proc 組中用戶之外的其他用戶的進程信息都隱藏起來:
/etc/fstab
proc /proc proc nosuid,nodev,noexec,hidepid=2,gid=proc 0 0
要使用戶會話正常工作,需要為 systemd-logind 添加例外:
/etc/systemd/system/systemd-logind.service.d/hidepid.conf
[Service] SupplementaryGroups=proc
限制模塊加載
默認的 Arch 內核啟用了 CONFIG_MODULE_SIG_ALL,這會對作為 linux包 軟體包一部分構建的所有內核模塊進行簽名。這使得內核只能加載帶有有效簽名的模塊,也就是說,本地編譯的樹外(out-of-tree)模塊或由 virtualbox-host-modules-arch包 等軟體包提供的模塊將被無法加載。可以使用 modinfo 來驗證當前加載的模塊是否包含簽名;而手動驗證簽名則稍微複雜一些[13]。
可以通過設置 module.sig_enforce=1 內核參數來限制內核模塊的加載。更多信息可以在內核文檔中找到。
此外,可以將不需要的特定模塊列入黑名單,具體示例可以參考secureblue。
禁用模塊加載
某些安全漏洞(例如 Copy Fail)存在於大多數用戶並不需要的內核模塊中。禁用所有無關模塊的加載可以防止此類漏洞被利用。要使此方案可行,內核通常必須處於穩定狀態,這意味著一旦系統完全啟動,通常就不再需要加載任何模塊。當內核達到該狀態時,可以切換 modules_disabled 選項,以不可逆地禁用模塊的加載和卸載,直至下一次重啟後失效。
禁用 kexec
Kexec 允許替換當前正在運行的內核。
/etc/sysctl.d/51-kexec-restrict.conf
kernel.kexec_load_disabled = 1
Kernel 鎖定模式(Lockdown)
Linux 支持一項可選的鎖定(Lockdown)特性,旨在強化 UID 0(root)與內核之間的邊界。啟用此功能後,某些依賴對硬體或內核進行底層訪問的應用程式可能會停止工作。
要使用鎖定功能,必須先初始化其 LSM(Linux 安全模塊)並設置一種鎖定模式。
所有官方支持的內核都會初始化該 LSM,但默認都不會強制執行任何鎖定模式。
cat /sys/kernel/security/lsm 來驗證已初始化的 LSM。鎖定模式有兩種運行級別:
-
integrity(完整性):禁止允許用戶空間修改正在運行的內核的特性(例如 kexec、bpf)。 -
confidentiality(機密性):在完整性的基礎上,進一步禁用允許用戶空間從內核提取機密信息的內核特性。
除非特定的威脅模型另有要求,否則建議使用 integrity 模式。
若要在運行時啟用內核鎖定,請運行:
# echo mode > /sys/kernel/security/lockdown
若要在引導時啟用內核鎖定,請使用內核參數 lockdown=mode。
- 內核鎖定在運行時無法被禁用。
- 內核鎖定會禁用休眠(掛起到磁碟)功能。
- 在早於 6.17 的 kernel_lockdown(7) 手冊頁版本中,錯誤地寫到「如果系統在 EFI 安全啟動模式下引導,鎖定將被自動啟用」。這既不是上游內核的行為,也不是 Arch 打包的內核的行為。
另請參見 kernel_lockdown(7)。
Linux 內核運行時守護(LKRG)
LKRG(lkrg-dkmsAUR)是一個用於對內核進行完整性檢查並檢測漏洞利用嘗試的內核模塊。
禁用緊急 Shell
緊急 Shell(Emergency shell)用於在引導過程中對機器進行交互式故障排除。然而,它也是攻擊者可以用來訪問 TPM 等安全資源的工具。有關實際案例,參見這篇文章。禁用緊急 Shell 可以增加攻擊的難度,但代價是移除了一款用於排查早期引導故障的工具。
若要禁用緊急 Shell,參見Systemd#在遠程主機上關閉救援(emergency)模式。
禁用非特權用戶命名空間
除 linux-hardened包 外,在所有官方支持的內核中,非特權user_namespace(7)(用戶命名空間)的使用默認都是啟用的。非特權用戶命名空間極大地擴大了本地特權提升的攻擊面;參見 AppArmor 的 Wiki 和 FS#36969。
為緩解此風險,可以執行以下操作之一:
- 使用已具備安全默認設置的 linux-hardened包 內核,或
- 將
kernel.unprivileged_userns_cloneSysctl 參數設置為0。
注意,這可能會破壞諸如 nsjail包 等應用程式。在此設置下,基於 Chromium 的應用程式需要為 chrome-sandbox 開啟 SUID 位才能正常工作。
限制系統服務
可以對系統服務允許執行的操作進行限制。使用 systemd-analyze security 命令可以審查機器上 systemd 服務單元的安全屬性,閱讀專屬文章 en:systemd/sandbox 以了解更多信息。
沙箱程序
另請參閱 Wikipedia:Sandbox (computer security)。
Firejail
Firejail是一種易於使用的用於沙盒化應用程式和伺服器的工具。它原本是為瀏覽器和面向網際網路的應用程式創建的,但現在已經支持大量的應用程式。為了建立具有各種特性的沙盒環境,它被安裝為一個suid二進制文件,並根據黑名單和白名單為目標應用程式構建一個沙盒化的運行時環境。
bubblewrap
bubblewrap 是為無特權容器工具(如 Flatpak)開發的沙箱應用程式,其資源占用和複雜性都遠遠小於Firejail。雖然它缺少某些功能,如文件路徑白名單,但bubblewrap確實提供了bind掛載以及創建用戶/IPC/PID/網絡/cgroup命名空間的功能,並且可以支持簡單和複雜的沙箱。對於 linux-hardened包 內核,你需要使用 bubblewrap-suid包
Bubblejail沙箱基於bubblewrap,並提供了一個面向資源的權限模型,用戶可以通過圖形界面進行權限的調整。
Portable
Portable 是一個沙箱框架,它利用 bubblewrap 和許多其他工具來鎖定運行中的應用程式。該框架旨在為打包者提供便利,同時為用戶保證效率,並且默認切斷安全漏洞並監控後台進程。
關於由 portable 沙箱化的應用程式倉庫,參見 portable-arch。
如果沙箱化的應用程式沒有使用 Portal 文件選擇器,portable 可以將文件傳遞給沙箱(通過傳遞 --actions share-files 參數)。
Portable 在 GNOME 上功能完全正常,而其他桌面環境可能會缺少諸如高級後台監控和屏幕截圖 Portal 等少量特性
chroots
也可以手動構建chroot囚禁來創建沙箱化的進程環境。其相比其他沙箱技術的功能有限;它的沙箱程度僅限於文件路徑隔離。
gVisor
由 Google 主導的 gVisor 項目提供了一款沙箱應用程式,重點專注於遵循 OCI 倡議的容器技術,例如 Docker 和 Kubernetes。它通過攔截絕大多數發往內核的系統調用,並將自身偽裝為用戶機內核(Guest Kernel),從而實現容器及單個應用程式與宿主機的隔離。
與其他攔截型沙箱項目的一個關鍵區別在於,gVisor 使用 Go 語言重新實現了系統調用,具體詳見其設計概述。有關已重新實現的系統調用列表細節,可以在 git 中查看。關於使用示例、局限性以及特殊特性,請參閱此項目的項目文檔。
該應用程式可以通過 gvisor-gitAUR 和 gvisor-binAUR 獲取。
Linux容器
當你需要比其他選項提供的更多分離時(簡略於 #完全虛擬化選項) ,Linux Containers是另一個很好的選擇。LXC在現有內核之上運行,採用偽chroot,並擁有自己的虛擬硬體。
完全虛擬化選項
如果你計劃運行風險應用程式或瀏覽危險網站,使用完全虛擬化選項如VirtualBox,KVM,Xen或 Qubes OS (基於Xen)也可以提高隔離和安全性。
網絡與防火牆
防火牆
雖然源裡面的 Arch 內核能夠啟用 Netfilter 的 nftables(以及它的前身 iptables),但其服務默認是不啟用的。強烈建議配置防火牆來保護系統上運行的服務。許多資料(包括 ArchWiki)沒有明確說明哪些服務值得保護,因此啟用防火牆是一個很好的預防措施。
- 參閱 nftables 來獲取一般信息。
- 參閱 Uncomplicated Firewall 來獲取配置一個基礎防火牆的指南。
- 參閱 Category:Firewalls 來獲取設置 netfilter 的其他方法。
- 參閱 Ipset 以設置 IP 地址黑名單,內容可參考來自 Bluetack 的名單。
開放埠
一些服務會在開放的網絡埠上監聽入站流量。只將這些服務綁定到嚴格必要的地址和接口是非常重要的。遠程攻擊者可能能夠利用有缺陷的網絡協議訪問暴露的服務。即使在綁定到localhost的進程中,這種情況也可能發生。
總的來說,如果一個服務只需要對本地系統可訪問,那麼就綁定到一個Unix域套接字 (unix(7))或者一個迴環地址,比如localhost,而不是非迴環地址,比如0.0.0.0/0。
如果一個服務需要通過網絡對其他系統可訪問,那麼就通過嚴格的防火牆規則控制訪問,並且儘可能配置認證、授權和加密。
你可以使用ss -l來列出所有當前開放的埠。要顯示所有正在監聽的進程及其數值化的 tcp 和 udp 埠號:
# ss -lpntu
查看 ss(8) 以獲取更多選項。
內核參數
作用於網絡的內核參數可以使用 Sysctl 來設置。要查詢具體方法,請參閱 Sysctl#TCP/IP stack hardening。
SSH
為了減輕暴力攻擊,建議強制使用基於密鑰的身份驗證。對於 OpenSSH,請參閱 OpenSSH#保護。另外,Fail2ban 或 Sshguard 通過監控日誌並寫入 iptables 規則提供了較少形式的保護,但這樣做可能會使伺服器拒絕服務,因為攻擊者可以偽裝成管理員的地址並發送欺騙性的數據包。
你可以用雙因素身份驗證來進一步強化身份驗證。Google Authenticator(Google 身份驗證器)使用一次性密碼 (OTP) 提供兩步驗證過程。
拒絕 root 登錄也是一種很好的做法,既可以跟蹤入侵,也可以在 root 訪問之前添加額外的安全層。對於 OpenSSH,請參閱 OpenSSH#Deny。
Mozilla公開發布了一個OpenSSH配置指南,其中設置了更為詳盡的審計日誌記錄,並限制了密碼。
DNS
默認的域名解析(DNS)配置具有很高的兼容性,但存在安全弱點。查看域名解析#隱私與安全獲得更多信息。
代理
代理通常用作應用程式和網絡之間的額外層,對來自不可信來源的數據進行清理。從攻擊面上看,一個以較低權限運行的小型代理的攻擊面顯著小於以最終用戶權限運行的複雜應用程式。
例如,DNS解析器在glibc包中實現,該解析器與應用程式(可能以root身份運行)連結,因此DNS解析器中的錯誤可能導致遠程代碼執行。通過安裝DNS緩存伺服器,例如dnsmasq,它可以起到代理的作用,可以防止這種情況發生。[16]
管理TLS證書
請查看 TLS#信任管理。
物理安全
只要有足夠的時間和資源,對計算機的物理訪問就等同於 root 權限的訪問。然而,通過設置足夠的障礙,可以獲得較高的實際安全級別。
攻擊者可以通過簡單地連接一個惡意的IEEE 1394(FireWire)、雷電或PCI Express設備,即可在下次啟動時完全控制您的計算機,因為這些設備默認被賦予全內存訪問權限。[17] 對於雷電,您可以完全限制直接內存訪問或僅限於已知設備,參見雷電#用戶設備授權。對於Firewire和PCI Express,防止此類事件或硬體自身的修改(例如在驅動器上刷新惡意固件)您能做的很少。但是,大多數攻擊者並非這麼有知識和決心。
#靜態數據加密可以防止計算機被盜時對您的數據的訪問,但是資源充足的攻擊者可以安裝惡意固件,在您下次登錄時獲取此數據。
鎖定BIOS
在BIOS中添加密碼可以防止他人啟動至可移動媒體,這基本上相當於對您的計算機擁有根訪問權限。您應確保您的驅動程序在啟動順序中排在第一,並儘可能禁用其他驅動程序的啟動功能。
引導加載程序 (Bootloader)
保護您的引導加載程序非常重要。一個未受保護的啟動加載器可以繞過任何登錄限制:例如通過設置init=/bin/sh內核參數以直接啟動到shell,它會使得任何用戶的登錄限制完全無用。
Syslinux
Syslinux支持對啟動加載器進行密碼保護。它允許您設置菜單項密碼 或者 全局啟動加載器密碼。
GRUB
GRUB也支持啟動加載器密碼。請查看GRUB/技巧和竅門#用密碼保護 GRUB 菜單以獲取詳細信息。它還支持 #加密的/boot,這可以加密GRUB的配置,內核和 initramfs ,只剩下啟動加載器代碼中的一部分未加密。
systemd-boot
當啟用了#安全啟動(Secure Boot)時,systemd-boot會自動禁用對內核參數的編輯功能。此外,也可以在 systemd-boot 中設置帶密碼保護的內核參數編輯器,以使用更傳統的密碼驗證方案。
安全啟動
安全啟動是UEFI的功能,允許驗證你的計算機啟動的文件。這有助於防止一些邪惡女僕攻擊,如替換啟動分區內的文件。通常,計算機會攜帶由供應商(OEM)授予的密鑰,不過,密鑰可以被刪除,並使計算機進入設置模式,允許用戶導入並管理自己的密鑰。
安全啟動頁面會引導你如何通過使用自己的密鑰來設置安全啟動。
可信平台模塊 (TPM)
TPMs 是帶有嵌入式加密密鑰的硬體微處理器。這構成了大多數現代電腦的基本信任根(源),允許對啟動鏈執行端到端驗證。它們可用作內部智慧卡,驗證計算機上運行的固件,並允許用戶將密碼插入防篡改和抗暴力破解的存儲器中。
在可移動快閃記憶體驅動器上的啟動分區
一個流行的想法是將啟動分區放在快閃記憶體驅動器上,以便在沒有它的情況下系統無法啟動。提倡這個想法的人通常會使用全盤加密,有些人還會使用放在啟動分區的分離的加密頭。
自動註銷
如果您使用Bash或Zsh,您可以設置 TMOUT 在超時後自動從shell註銷。
例如,以下操作將在虛擬控制台(但不是X11中的終端模擬器)自動退出:
/etc/profile.d/shell-timeout.sh
TMOUT="$(( 60*10 ))";
[ -z "$DISPLAY" ] && export TMOUT;
case $( /usr/bin/tty ) in
/dev/tty[0-9]*) export TMOUT;;
esac
如果你確實希望每一個Bash/Zsh提示符(甚至在X內)都有超時,使用:
$ export TMOUT="$(( 60*10 ))";
注意,如果有一些命令在shell中運行(例如:一個SSH會話或沒有TMOUT支持的其他shell),這將不起作用。但是,如果你主要是用VC來重啟冷凍的GDM/Xorg作為root,那麼這會非常有用。
保護免受惡意USB設備的攻擊
內核提供了用於停用 USB 埠的設置,以保護計算機免受惡意 USB 設備(又稱BadUSB、PoisonTap 或 LanTurtle)的侵害。這些設置可以在運行時配置,並通過 sysctl 實現自動化。
如果需要更精細的控制,可以安裝 USBGuard。這是一個基於設備屬性實現基礎白名單和黑名單功能的軟體框架。
易失性數據收集
開啟狀態的計算機可能會受到易失性數據收集的威脅。將計算機完全關閉,在無需使用時或者計算機的物理安全暫時受到破壞時(例如,通過安全檢查點),是一種最好的做法。
軟體包
驗證
如果沒有正確地對包進行簽名,包管理器就有可能受到攻擊,甚至可能會影響原本具有簽名機制的包管理器。Arch 默認採用軟體包簽名機制,並依賴與 5 個受信任的主密鑰的信任網絡。詳情請參閱 pacman/Package signing。
升級
定期升級系統非常重要。
關注漏洞警報
可訂閱由國家漏洞資料庫提供的Common Vulnerabilities and Exposure(CVE)安全警報更新,在NVD Download網頁上可以找到。
如果您通過主要倉庫或AUR之外的其他方式安裝軟體,您還應考慮訂閱您使用的軟體的 發布通知。一些軟體有您可以訂閱的安全通知郵件列表。原始碼託管網站通常提供可以接收新版本發布消息的RSS源。參見 Arch 安全團隊#資源。
重新構建軟體包
軟體包可以去除不需要的功能並重新構建,這樣可以縮小受攻擊範圍。例如,bzip2包 可以在沒有 bzip2recover 的情況下重新構建,以試圖規避 CVE-2016-3189 漏洞。強化安全的自定義編譯參數也可以手動或通過包裝器在編譯時加入。
| 參數(Flag) | 用途(Purpose) |
|---|---|
| -D_FORTIFY_SOURCE=2 | 檢測運行時緩衝區溢出 |
| -D_GLIBCXX_ASSERTIONS | C++ 字符串和容器的運行時邊界檢查 |
| -fasynchronous-unwind-tables | 提高回溯(Backtrace)的可靠性 |
| -fexceptions | 啟用基於表的線程取消機制 |
| -fpie -Wl,-pie | 為可執行文件啟用完全地址布局空間隨機化(ASLR) |
| -fpic -shared | 共享庫無文本重定位 |
| -fplugin=annobin | 生成用於加固質量控制的數據 |
| -fstack-clash-protection | 提高棧溢出檢測的可靠性 |
| -fstack-protector, -fstack-protector-all or -fstack-protector-strong | 棧粉碎保護(Stack Smashing Protector) |
| -grecord-gcc-switches | 在調試信息中存儲編譯器參數 |
| -mcet -fcf-protection | 控制流完整性(CFI)保護 |
| -Werror=format-security | 拒絕潛在不安全的文件格式化字符串參數 |
| -Werror=implicit-function-declaration | 拒絕隱式函數聲明(缺少函數原型) |
| -Wl,-z,defs | 檢測並拒絕欠連結(Underlinking) |
| -Wl,-z,now | 禁用延遲綁定(Lazy binding) |
| -Wl,-z,relro | 重定位後將相關段設為只讀 |
參考資料
- unixchad 的視頻:《捍衛隱私的真正方法:Firejail,全盤加密,GPG和ufw》
- Arch Linux Security Tracker
- CentOS Wiki: OS Protection
- Hardening the Linux desktop
- Hardening the Linux server
- Linux Foundation: Linux workstation security checklist
- privacytools.io Privacy Resources
- Red Hat Enterprise Linux 7 Security Guide
- Securing Debian Manual
- The paranoid #! Security Guide