27.4 安全等级
安全等级为 FreeBSD 内核内置安全机制,可通过 sysctl kern.securelevel 查看当前等级,对于运行时,该值只能在 -1 至 3 五个级别间单向提升(不可降低)。
27.4.1 概述
安全等级是内核内置安全机制。安全等级为正值时,内核限制部分操作,root 用户亦不例外。
安全等级机制限制以下功能:
- 取消设置某些文件标志,如
schg(系统不可变标志)。 - 通过 /dev/mem 和 /dev/kmem 写入内核内存。
- 加载内核模块。
- 更改防火墙规则。
27.4.2 安全等级定义
内核共设五个安全等级。任何超级用户进程均可提升等级,但任何进程均不能降低等级。
安全等级递进关系(只能提升,不能降低):
-1 永久不安全模式(默认初始值)
│ 解除一切安全限制
│
│ 提升
▼
0 不安全模式
│ 可关闭不可变/仅追加标志
│ 所有设备可依权限读写
│
│ 提升(init 进入多用户模式时自动设为 1)
▼
1 安全模式
│ 无法关闭 schg/sappnd 标志
│ /dev/mem、/dev/kmem 不可写入
│ 无法加载/卸载内核模块
│
│ 提升
▼
2 高度安全模式
│ 磁盘(无论是否挂载)不可写入
│ 内核时间变更不超过 1 秒
│
│ 提升
▼
3 网络安全模式
防火墙规则(ipfw/pf)无法修改
dummynet/pf 配置无法调整各安全等级定义如下:
| 等级 | 名称 | 说明 |
|---|---|---|
-1 | 永久不安全模式 | 系统始终处于不安全模式。此为默认初始值。 |
0 | 不安全模式 | 可以关闭不可变和仅追加标志。所有设备可依其权限读写。 |
1 | 安全模式 | 无法关闭系统不可变和系统仅追加标志;已挂载文件系统所在磁盘、/dev/mem 和 /dev/kmem 均不可打开以写入;如果平台存在 /dev/io,则完全禁止打开;无法加载或卸载内核模块。禁止使用 sysctl debug.kdb.enter 进入内核调试器(除非 MAC(9) 策略授予访问权限,例如 mac_ddb(4));也无法通过 debug.kdb.panic、debug.kdb.panic_str 及其他 sysctl 强制触发 panic 或 trap。 |
2 | 高度安全模式 | 在安全模式基础上,磁盘(无论是否已挂载)均不可打开以写入,mount 操作除外。此等级可阻止以卸载文件系统方式篡改数据,但也意味着多用户模式下无法运行 newfs。此外,内核时间变更受限于不超过 1 秒;超出此范围修改时间将产生日志消息“Time adjustment clamped to +1 second”。 |
3 | 网络安全模式 | 在高度安全模式基础上,IP 数据包过滤规则(ipfw(8)、ipfw(4) 和 pfctl(8))均无法修改,dummynet(4) 或 pf(4) 配置也无法调整。 |
永久不安全模式与不安全模式的关键差别在于:前者彻底解除一切安全限制,而后者虽放宽了部分约束,仍保留相当程度的控制力。
按 init(8) 的工作方式,如果系统初始安全等级为 0,init 会在首次进入多用户模式前将其提升至 1。由于安全等级只能提升不能降低,此后即便返回单用户模式,系统也至少维持在等级 1。另外需要注意,引导阶段过早将安全等级设为大于 1 的值,可能阻碍 fsck(8) 修复不一致的文件系统,因此建议在 /etc/rc 末尾(多用户启动操作全部完成后)再行设置。
系统引导过程中安全等级变化:
内核加载
│
│ kern.securelevel = -1(永久不安全模式,默认初始值)
▼
init 启动
│
│ 安全等级从 -1 提升至 0(不安全模式)
▼
单用户模式(安全等级 = 0)
│
│ fsck 检查并修复文件系统
│ mount 挂载文件系统
│
▼
进入多用户模式前
│
│ init 自动将安全等级从 0 提升至 1(安全模式)
▼
多用户模式(安全等级 >= 1)
│
│ schg 标志不可取消、/dev/mem 不可写入
│ 内核模块不可加载/卸载
│
▼
/etc/rc 末尾(可选)
│
│ 可进一步提升至 2 或 3(通过 sysrc kern_securelevel=N)
▼
系统正常运行(安全等级为设定值)
│
│ 注意:安全等级只能提升,无法降低
│ 如需回退,必须重启并在单用户模式下修改27.4.3 修改安全等级
首先确保安全等级设置被启用:
# sysrc kern_securelevel_enable="YES"再将 kern.securelevel 设为期望的安全等级(允许的取值范围为 -1 至 3):
警告
安全等级只能提升不能降低。设置后若需回退,必须重启系统并在单用户模式下修改。远程管理场景下,过高的安全等级可能限制磁盘写入、内核模块加载等操作,导致无法正常运维。建议先在测试环境中验证影响后再行应用于生产环境。
# sysrc kern_securelevel=2重启后安全等级将生效。
查看运行中系统的当前安全等级:
# sysctl -n kern.securelevel
2输出为安全等级当前值。如果大于 0,说明系统至少已启用部分安全保护。
27.4.4 课后习题
将
kern.securelevel依次设置为 0、1、2,在每个等级下尝试以下操作:删除一个schg标志的文件、加载一个内核模块、修改kern.securelevel本身。列表汇总各操作在各安全等级下的允许/拒绝情况。解释为什么
kern.securelevel的数值只能增加而不能减少?从攻击者的角度分析,如果允许降低安全等级会引发哪些安全威胁场景?有观点认为此种安全等级在现代计算机安全中已不再重要,试述其理由。