第13章  安全

13.1. 何谓沙盒 (sandbox)?
13.2. 什么是 securelevel?
13.3. BIND (named) 除了在通讯端口 53 以外, 也在其它高编号通讯端口监听。 这是怎么回事?
13.4. sendmail 除了在标准的通讯端口 25 之外, 也监听了 587 端口! 这是怎么了?
13.5. 我发现了这个 UID 0 toor 账号, 这是什么玩意? 我被黑掉了吗?
13.6. 为什么 suidperl 无法正常运作?

13.1. 何谓沙盒 (sandbox)?

“沙盒” 是一个安全术语。 它有两种含义:

  • 放在某些虚拟防护墙里的执行程序, 这些防护墙是用来阻止某些人侵入进程, 进而出入于系统中更大的范围。

    进程可以完全在防护墙里 “动作”。 也就是说, 它所执行的任何程序不可能会渗透到墙的外面。 所以如果您对它有安全上的顾虑, 并不需要特别去监听它的一举一动, 因为反正它只能在墙内活动。

    举例来说,可以用 user ID 来做这道防护墙,这正是 security(7)named(8) 联机手册中的定义。

    现在就用 ntalk 这个服务作说明 (见 inetd(8))。 这个服务以前的 user ID 是 root, 现在执行时则是用 ttytty 这个用户就是一个 sandbox, 即使有人能够顺利用 ntalk 侵入系统, 现在他就算进得来也只能用这个 user ID。

  • 放在某个仿真机器里的程序,这比上述来得更严密。 基本上这表示能侵入该程序的人相信他能再进入所属的机器, 但事实上只会进入模拟出来的机器, 无法进一步修改任何真实的数据。

    达到这个目的最常用的方法, 就是在某个子目录下做出仿真的环境, 然后用 chroot 执行该程序 (也就是说, 对于那个进程而言 / 并不是系统中真实的 /)。

    另一个常见作法是将某个档案系统 mount 成只读, 但在它上面另外制造出程序以为可以写入的档案系统。 这个程序会相信它可以对其他档案读写, 但只有它看不到这个只读效应 ── 系统执行的一般程序都看得到。

    我们试图将这类沙盒尽量透明化, 让使用者或侵入者无法看到他是否在某个沙盒里面。

UNIX® 实现了两种核心沙盒。 其一是在进程层面, 另一个则是通过 userid 来达成。

每个 UNIX 执行程序会用防火墙将它和所有其它程序隔开, 某个程序不可以随意修改其它程序地址空间中的数据。 这和 Windows® 中, 进程可以轻易覆盖其它地址空间的数据, 并导致崩溃的情形完全不同。

每个 UNIX 进程都归属于特定的 user ID。 如果 user ID 不是 root 用户, 则它也是对于其他用户所有的进程的一道防火墙。 除此之外, user ID 也被用来管理磁盘配额。

13.2. 什么是 securelevel?

securelevel 是在内核中实现的一种安全机制。 基本上, 当 securelevel 是正值时, 内核会限制某些操作; 即使是超级用户 (也就是 root) 也无法完成那些工作。 在撰写在一般的限制外,还能够限制以下的功能:

  • 清除某些文件标记, 例如 schg (系统只读标志),

  • 经由 /dev/mem/dev/kmem 将数据写入至内核内存中,

  • 加载内核模块, 以及

  • 修改防火墙规则

想要检查在某个运作中的系统的 securelevel 状态, 只要执行以下命令即可:

# sysctl kern.securelevel

输出的结果会包含一个 sysctl(8) 变量名称 (本例中为 kern.securelevel) 以及一个数字。 后者即是目前 securelevel 的值。 如果它是一个正值 (也就是大于 0), 则表示启用了某些或全部 securelevel 的保护机制。

运行中的系统是无法降低其 securelevel 的; 如果可以的话, 这个机制就失去意义了。 如果你要作一些需要 securelevel 为非正值才可以的动作的话 (例如 installworld 或修改日期), 就必须修改 /etc/rc.conf 中的 securelevel 配置 (找找 kern_securelevelkern_securelevel_enable 变量), 并重启系统。

如欲了解更多有关于 securelevel 以及不同等级影响的细节, 请参见 init(8) 联机手册。

警告: securelevel 可不是万灵丹; 它有许多已知的缺陷, 往往造成一种安全的假象。

它最大的一个问题是, 要让这个功能完全有效的话, 在 securelevel 发挥作用前的启动过程中, 所有使用到的文件都必须被保护起来。 如果一个攻击者在 securelevel 生效前 (由于有些系统在启动中所作的事情, 无法在较高的 securelevel 中正常运作, 所以这会在启动过程中后期才会运作), 能让他们的程序被执行的话, securelevel 的保护就完全无效了。 保护启动程序中所有的档案在技术上是可行的, 但是如果真的这样作的话, 系统维护将会变成一场梦魇。 即使只是修改一个设定档, 也必须将整个系统关闭, 至少也得到单用户模式。

除了这点, 还有许多其它的东西都在邮件列表, 特别是 FreeBSD 安全问题邮件列表 上讨论。 请在 此处 搜索先前的讨论。 有些人希望 securelevel 能够尽快消失, 由另一个更优秀的机制取代, 不过机会有点渺茫。

风险自行承担。

13.3. BIND (named) 除了在通讯端口 53 以外, 也在其它高编号通讯端口监听。 这是怎么回事?

BIND 用随机的高编号通讯端口来对外查询。 如果你因为要适合防火墙的配置, 或是单纯的想让自己看来舒服一点而想用 53 通讯端口进行对外查询, 则可以尝试更改 /etc/namedb/named.conf 中的相关内容:

options {
        query-source address * port 53;
};

如果希望进行进一步的限制, 还可以将 * 改为特定 IP 地址。

顺便恭喜你。 能够读取你系统上的 sockstat(1) 报告并且留意不正常状况是一件好事!

13.4. sendmail 除了在标准的通讯端口 25 之外, 也监听了 587 端口! 这是怎么了?

较新版本的 sendmail 支持 mail submission 这项功能, 并且使用通讯端口 587。 这项功能还没有被广泛支持, 但是支持的数目正在增长中。

13.5. 我发现了这个 UID 0 toor 账号, 这是什么玩意? 我被黑掉了吗?

放心。 toor 是一个 “备用的” 超级用户帐号 (toor 是 root 的反向拼法)。 以往它是随安装 bash(1) 而建立的, 后来则成为系统内定建制的一个账号。 这个账号将伴随一个非标准的 shell 测试使用, 让你不需要去更改 root 的内建 shell。 因为这些其它的 shell 默认并不随系统安装 (举例来说,某些由 ports 安装的 shell packages), 会默认安装在 /usr/local/bin 目录下, 有可能存在不同的文件系统中。 倘若 root 的 shell 位于 /usr 中的 /usr/local/bin (或其它包含 /usr/local/bin 的文件系统) 由于某种原因没有挂接, 则 root 将没有机会登录并修正问题 (不过, 如果您重启并进入单用户模式, 则系统会提示您选择 shell 所在的路径)。

有些人使用 toor 账号进行日常的 root 维护工作, 如此可以使用非标准的 shell, 而 root 则可以保留标准 shell, 以因应单用户模式或紧急状况处理。 依照系统默认值, 是无法使用 toor 登入的, 因为这个账号尚未更改密码。 因此如果想启用这个账号, 就需要为 toor 设置口令了。

13.6. 为什么 suidperl 无法正常运作?

出于安全方面的考虑, suidperl 默认并不安装。 如果您希望在以源代码方式升级时联编 suidperl, 应在联编 perl 之前修改 /etc/make.conf 并添加 ENABLE_SUIDPERL=true

本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.