安全
本文包含了加固 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 为“可插拔身份验证模块”(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 存在硬件漏洞。这些漏洞的列表见关于硬件漏洞的 Linux 内核文档,其中也包含了修补方法选择指南,有助于针对特定场景对内核自定义,从而修补这些漏洞。
要检查是否受到已知漏洞影响,请运行:
$ grep -r . /sys/devices/system/cpu/vulnerabilities/
大部分情况下,更新内核和微码能够修补漏洞。
同步多线程(SMT),在英特尔 CPU 上又称超线程,这一硬件功能可能是 L1 Terminal Fault 与微架构数据采样(Microarchitectural Data Sampling)漏洞的来源。 Linux 内核和微码更新含有针对已知漏洞的补丁,但是如果存在不受信任的虚拟化客户机,则对于某些 CPU 可能仍然需要禁用 SMT。
SMT 往往可以在系统固件中关闭。更多信息见主板或系统文档。通过添加以下内核参数,也可以在内核中禁用 SMT:
mitigations=auto,nosmt
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
若能接受使用 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。
了解系统中哪些文件启用了 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)在从睡眠状态唤醒时,极易受到安全擦除单元(ATA SECURITY ERASE UNIT)命令的攻击。若需降低此风险,参阅固态硬盘#从睡眠中唤醒时设置 SATA SSD 为冻结模式。
根据最小权限原则,不要日常使用 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 应用程序可以在不活动时记录击键。
如果必须运行 Xorg,建议避免以 root 身份运行,参考Xorg#没有 root 权限的 Xorg,并确保其不监听抽象套接字(Abstract sockets)和 TCP 套接字。 在 Wayland 中,Xwayland 兼容层将自动使用无 root 权限的 Xorg。
按照系统的设计,root 用户是系统中最强大的用户。审计 root 用户帐户也很困难。因此,重要的是尽可能多地限制root用户帐户的使用。有多种方法可以保持 root 用户的权力,同时限制其造成损害的能力。
- sudo 记录了普通权限用户运行每个特权命令的日志。
- root 用户的密码不需要告知每个请求 root 权限的用户。
sudo可以防止用户意外地以 root 身份执行无需该权限的命令,因为 sudo 并没有为 root 创建完整的终端。这符合最小权限原则。- 可以为单个用户启用单个程序的 root 权限,而不用为了运行一个程序启用该用户对 root 的完整访问权。
有关更多信息,参见Sudo#配置。
参见Sudo#编辑文件。另外,你也可以使用像rvim或rnano这样限制了部分高级功能的的编辑器,因而可以安全地在 root 环境下运行。
正确配置 sudo 后,完全的 root 权限就可以被严格限制或停用,且不会损失太多可用性。要禁用 root 而允许使用 sudo,可以运行 passwd -l root。
PAM 的 pam_wheel.so 模块可以做到仅允许 wheel 组中的用户使用 su包登录。参见Su#su 和 wheel 用户组。
即使你不想禁止 root 用户在本地登录,也最好禁止 root 通过 SSH 登录。这样做的目的是在用户可以在远程完全破坏系统之前添加额外的一层安全保护。
+:(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 可以在更广泛的文件系统上实现,这与基于标签的另一种可选方案是不同的。
- TOMOYO Linux 是另一种提供访问控制的系统,简单而易用。它的使用方式和内部实现都被设计得足够简单,需要的依赖也很少。
基于标签的访问控制意味着每份文件都带有扩展属性用于决定它的安全权限。虽然这类系统应该比基于路径的控制更灵活,但它只适用于支持这些扩展属性的文件系统。
- SELinux 是一个基于 美国国家安全局(NSA) 的项目,用于提高 Linux 的安全性。它完整实现了 MAC,将系统用户与角色独立开来。它实现了一个非常强大的多级 MAC 策略,可以在系统扩大和改变得超出其原始配置时也能轻松控制系统。
访问控制列表(Access Control Lists, ACLs)是以某种方式将规则直接附加到文件系统的一种可选方法。ACLs 将程序的实际操作与允许的操作对照,来实现访问控制。
linux-hardened包 相较于 linux包 使用了基本内核加固补丁集和更多安全相关的编译时配置选项。也可以使用自定义编译选项来把握安全性和性能之间的平衡,而不是使用强调安全性的默认选项。
然而需要注意的是,当使用该内核时,某些软件包(例如throttled包)将无法正常工作。
如果你用了内核代码树以外的驱动,比如 NVIDIA,可能会需要切换到它的 DKMS 包。
linux-hardened包 包为用户空间进程提供了改进的 ASLR(Address Space Layout Randomization,地址空间布局随机化)实现。paxtest包 命令可用于获取所提供熵的估计值:
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)
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
将 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 是一种用在运行时动态向内核加载并执行字节码的系统。它被广泛应用于许多 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(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 允许替换当前正在运行的内核。
/etc/sysctl.d/51-kexec-restrict.conf
kernel.kexec_load_disabled = 1
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)。
LKRG(lkrg-dkmsAUR)是一个用于对内核进行完整性检查并检测漏洞利用尝试的内核模块。
紧急 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是一种易于使用的用于沙盒化应用程序和服务器的工具。它原本是为浏览器和面向互联网的应用程序创建的,但现在已经支持大量的应用程序。为了建立具有各种特性的沙盒环境,它被安装为一个suid二进制文件,并根据黑名单和白名单为目标应用程序构建一个沙盒化的运行时环境。
bubblewrap 是为无特权容器工具(如 Flatpak)开发的沙箱应用程序,其资源占用和复杂性都远远小于Firejail。虽然它缺少某些功能,如文件路径白名单,但bubblewrap确实提供了bind挂载以及创建用户/IPC/PID/网络/cgroup命名空间的功能,并且可以支持简单和复杂的沙箱。对于 linux-hardened包 内核,你需要使用 bubblewrap-suid包
Bubblejail沙箱基于bubblewrap,并提供了一个面向资源的权限模型,用户可以通过图形界面进行权限的调整。
Portable 是一个沙箱框架,它利用 bubblewrap 和许多其他工具来锁定运行中的应用程序。该框架旨在为打包者提供便利,同时为用户保证效率,并且默认切断安全漏洞并监控后台进程。
关于由 portable 沙箱化的应用程序仓库,参见 portable-arch。
如果沙箱化的应用程序没有使用 Portal 文件选择器,portable 可以将文件传递给沙箱(通过传递 --actions share-files 参数)。
Portable 在 GNOME 上功能完全正常,而其他桌面环境可能会缺少诸如高级后台监控和屏幕截图 Portal 等少量特性
也可以手动构建chroot囚禁来创建沙箱化的进程环境。其相比其他沙箱技术的功能有限;它的沙箱程度仅限于文件路径隔离。
由 Google 主导的 gVisor 项目提供了一款沙箱应用程序,重点专注于遵循 OCI 倡议的容器技术,例如 Docker 和 Kubernetes。它通过拦截绝大多数发往内核的系统调用,并将自身伪装为用户机内核(Guest Kernel),从而实现容器及单个应用程序与宿主机的隔离。
与其他拦截型沙箱项目的一个关键区别在于,gVisor 使用 Go 语言重新实现了系统调用,具体详见其设计概述。有关已重新实现的系统调用列表细节,可以在 git 中查看。关于使用示例、局限性以及特殊特性,请参阅此项目的项目文档。
该应用程序可以通过 gvisor-gitAUR 和 gvisor-binAUR 获取。
当你需要比其他选项提供的更多分离时(简略于 #完全虚拟化选项) ,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。
为了减轻暴力攻击,建议强制使用基于密钥的身份验证。对于 OpenSSH,请参阅 OpenSSH#保护。另外,Fail2ban 或 Sshguard 通过监控日志并写入 iptables 规则提供了较少形式的保护,但这样做可能会使服务器拒绝服务,因为攻击者可以伪装成管理员的地址并发送欺骗性的数据包。
你可以用双因素身份验证来进一步强化身份验证。Google Authenticator(Google 身份验证器)使用一次性密码 (OTP) 提供两步验证过程。
拒绝 root 登录也是一种很好的做法,既可以跟踪入侵,也可以在 root 访问之前添加额外的安全层。对于 OpenSSH,请参阅 OpenSSH#Deny。
Mozilla公开发布了一个OpenSSH配置指南,其中设置了更为详尽的审计日志记录,并限制了密码。
默认的域名解析(DNS)配置具有很高的兼容性,但存在安全弱点。查看域名解析#隐私与安全获得更多信息。
代理通常用作应用程序和网络之间的额外层,对来自不可信来源的数据进行清理。从攻击面上看,一个以较低权限运行的小型代理的攻击面显著小于以最终用户权限运行的复杂应用程序。
例如,DNS解析器在glibc包中实现,该解析器与应用程序(可能以root身份运行)链接,因此DNS解析器中的错误可能导致远程代码执行。通过安装DNS缓存服务器,例如dnsmasq,它可以起到代理的作用,可以防止这种情况发生。[16]
请查看 TLS#信任管理。
只要有足够的时间和资源,对计算机的物理访问就等同于 root 权限的访问。然而,通过设置足够的障碍,可以获得较高的实际安全级别。
攻击者可以通过简单地连接一个恶意的IEEE 1394(FireWire)、雷电或PCI Express设备,即可在下次启动时完全控制您的计算机,因为这些设备默认被赋予全内存访问权限。[17] 对于雷电,您可以完全限制直接内存访问或仅限于已知设备,参见雷电#用户设备授权。对于Firewire和PCI Express,防止此类事件或硬件自身的修改(例如在驱动器上刷新恶意固件)您能做的很少。但是,大多数攻击者并非这么有知识和决心。
#静态数据加密可以防止计算机被盗时对您的数据的访问,但是资源充足的攻击者可以安装恶意固件,在您下次登录时获取此数据。
在BIOS中添加密码可以防止他人启动至可移动媒体,这基本上相当于对您的计算机拥有根访问权限。您应确保您的驱动程序在启动顺序中排在第一,并尽可能禁用其他驱动程序的启动功能。
保护您的引导加载程序非常重要。一个未受保护的启动加载器可以绕过任何登录限制:例如通过设置init=/bin/sh内核参数以直接启动到shell,它会使得任何用户的登录限制完全无用。
Syslinux支持对启动加载器进行密码保护。它允许您设置菜单项密码 或者 全局启动加载器密码。
GRUB也支持启动加载器密码。请查看GRUB/技巧和窍门#用密码保护 GRUB 菜单以获取详细信息。它还支持 #加密的/boot,这可以加密GRUB的配置,内核和 initramfs ,只剩下启动加载器代码中的一部分未加密。
当启用了#安全启动(Secure Boot)时,systemd-boot会自动禁用对内核参数的编辑功能。此外,也可以在 systemd-boot 中设置带密码保护的内核参数编辑器,以使用更传统的密码验证方案。
安全启动是UEFI的功能,允许验证你的计算机启动的文件。这有助于防止一些邪恶女仆攻击,如替换启动分区内的文件。通常,计算机会携带由供应商(OEM)授予的密钥,不过,密钥可以被删除,并使计算机进入设置模式,允许用户导入并管理自己的密钥。
安全启动页面会引导你如何通过使用自己的密钥来设置安全启动。
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 设备(又称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