14.2.介绍

安全是每个人的责任。任何系统中的弱入口点都可能允许入侵者并访问关键信息,并对整个网络造成严重破坏。信息安全的核心原则之一是 CIA 三位一体,它代表信息系统的机密性,完整性和可用性。

CIA 三位一体是计算机安全的基本概念,因为客户和用户希望他们的数据受到保护。例如,客户希望其信用卡信息被安全存储(机密性),他们的订单不会在幕后更改(完整性),并且他们可以随时访问其订单信息(可用性)。

为了保证 CIA,安全专业人员应用了纵深防御策略。纵深防御策略的思想是增加几层安全层,以防止单一层失效和整个安全系统崩溃。例如,系统管理员不能简单地打开防火墙并认为网络或系统是安全的。还必须审计帐户,检查二进制文件的完整性,并确保没有安装恶意工具。要实施有效的安全战略,必须了解威胁以及如何防范它们。

什么是与计算机安全有关的威胁?威胁不仅限于试图在未经许可的情况下从远程位置访问系统的远程攻击者。威胁还包括员工、恶意软件、未经授权的网络设备、自然灾害、安全漏洞,甚至是竞争对手。

有时在偶然下,系统和网络可以在未经许可的情况下访问,或者由远程攻击者访问,在某些情况下,他们通过商业间谍或前雇员访问。作为用户,重要的是准备和承认有一个错误导致了安全漏洞,并向安全团队报告可能的问题。作为管理员,重要的是了解威胁并降低威胁的危险性。

在对系统进行安全防护时,建议从保护基本帐户和系统配置开始,然后保障网络层的安全,使其符合系统安全策略和组织的安全程序。许多组织已经制定了涵盖技术设备配置的安全策略。该策略应包括工作站、台式机、移动设备、电话、生产服务器和开发服务器的安全配置。在许多情况下,标准操作程序(SOP)已经存在。当有疑问时,请询问安全团队。

本节的其余部分介绍了如何在 FreeBSD 系统上执行这些基本安全配置。本章的其余部分介绍了在 FreeBSD 系统上实施安全策略时可以使用的一些具体工具。

14.2.1. 阻止登录

在确保系统安全方面,一个好的开始是对账户进行审计。确保 root 账户有一个健壮的密码,并且这个密码未被共享。禁用任何不需要登录权限的账户。

拒绝账户的登录访问有两种方法。第一种是锁定账户。以下是锁定 toor 账户的示例。

  1. # pw lock toor

第二种方法是通过将 shell 更改为 /usr/sbin/nologin 来防止登录访问。只有使用超级账户可以为其他用户更改 shell:

  1. # chsh -s /usr/sbin/nologin toor

/usr/sbin/nologin 命令防止系统在用户试图登录时给他们分配一个shell。

14.2.2. 允许的帐户升级

在某些情况下,需要与其他用户共享系统管理。FreeBSD 有两种方法可以实现。第一种方法(不推荐使用)是采用 wheel 组成员共同使用 root 密码。使用此方法时,用户在需要超级用户访问时键入 su 并输入 wheel 的密码。在完成需要管理权限的命令后,用户应该键入 exit 来退出用户共享。如需将一个用户添加到这个组中,请编辑 /etc/group 并将该用户添加到 wheel 条目的末尾。该用户必须用逗号字符隔开,不能有空格。

第二种方法,也是推荐的方法是安装 security/sudo 包或 port。该软件能提供额外的审计,更细粒度的进行用户控制,并且可以为锁定用户配置仅运行指定的权限命令。

安装后,使用 visudo 来编辑 /usr/local/etc/sudoers。下面的示例是创建一个新的 webadmin 组,将 trhodes 账户加入该组,并配置该组的访问权限,以重新启动 apache24

  1. # pw groupadd webadmin -M trhodes -g 6000
  2. # visudo
  3. %webadmin ALL=(ALL) /usr/sbin/service apache24 *

14.2.3. 密码哈希

密码是技术的一个必要缺陷。当必须使用它们时,它们应该很复杂,并且应该使用强大的哈希机制来加密存储在密码数据库中的。FreeBSD 在其 crypt() 库中支持 DES、MD5、SHA256、SHA512 和 Blowfish 哈希算法。不应该将默认的 SHA512 改成安全性较低的散列算法,但可以改成安全性更高的 Blowfish 算法。

注意
Blowfish 算法不是 AES 的一部分,通常被认为不符合联邦信息处理标准(FIPS)。在某些环境中可能不允许使用它。

为了确定用来加密用户的密码使用了哪个哈希算法。超级用户可以在 FreeBSD 密码数据库中查看用户的哈希值。每个哈希值以一个符号开始,表示用于加密密码的哈希机制的类型。如果使用的是 DES,则没有开头符号。对于 MD5, 符号是 $。 对于 SHA256 和 SHA512, 符号是 6$。对于 Blowfish,符号是 2a$。在下面的例子中,dru 的密码是用默认的 SHA512 算法散列的,因为散列值以 $6$ 开始。请注意,密码是以加密的哈希值的形式存储在密码数据库中。

  1. # grep dru /etc/master.passwd
  2. dru:$6$pzIjSvCAn.PBYQBA$PXpSeWPx3g5kscj3IMiM7tUEUSPmGexxta.8Lt9TGSi2lNQqYGKszsBPuGME0:1001:1001::0:0:dru:/usr/home/dru:/bin/csh

哈希机制是在用户的登录类中设置的。在下面的例子中,用户是在 default 登录类别中,哈希算法是通过 /etc/login.conf 中的下面的配置进行配置的。

  1. :passwd_format=sha512:\

假如要将加密算法更改为 Blowfish,请将该行修改为如下所示:

  1. :passwd_format=blf:\

然后 按照 配置登录名类 中所述运行 cap_mkdb /etc/login.conf。注意,此更改不会改变任何现有的密码哈希。这意味着所有密码都应通过要求用户运行 passwd 来更改他们的密码散列值。

对于远程登录,应使用双因素身份验证(2FA)。双因素身份验证的一个示例是”你拥有的东西”(如密钥)和”你知道的内容”(如该密钥的密码)。由于 OpenSSH 是 FreeBSD 基础系统的一部分。所有网络登录都应该通过加密连接。并使用基于密钥的身份验证而不是密码。有关更多信息,请参阅 OpenSSH。Kerberos 用户可能需要进行其他更改才能在其网络中实现 OpenSSH。在 Kerberos 中对有关的内容进行了描述。

14.2.4. 密码策略实施

对本地帐户强制实施强密码策略是系统安全的一个基本方面。在 FreeBSD 中。密码长度、密码强度和密码复杂性可以通过内置的可插拔身份验证模块 (PAM) 来实现。

本节演示如何使用 pam_passwdqc.so 模块进行最小和最大密码长度以及混合字符强制执行的配置。当用户更改其密码时,将强制执行此模块。

要配置此模块,请成为超级用户并取消 /etc/pam.d/passwd 中包含pam_passwdqc.so的行的注释。然后,编辑该行以匹配密码策略:

  1. password requisite pam_passwdqc.so min=disabled,disabled,disabled,12,10 similar=deny retry=3 enforce=users

本示例为新密码设置了多个要求。min 设置控制最小密码长度。它有五个值,因为此模块根据其复杂性定义了五种不同类型的密码。复杂性由密码中必须存在的字符类型(如字母、数字、符号和大小写)定义。密码类型在 pam_passwdqc(8) 中进行了描述。在此示例中,前三种类型的密码被禁用,这意味着满足这些复杂性要求的密码将不被接受,无论其长度如何。12 设置了一个最小的密码策略,即如果密码也包含有三种类型的复杂性的字符,则至少要有 12 个字符。10 设置了密码策略,如果密码包含有四种类型的复杂性的字符,则也允许至少十个字符的密码。

similar 设置拒绝与用户之前的密码相似的密码。retry 设置为用户提供了三次输入新密码的机会。

保存此文件后,更改密码的用户将看到类似于以下内容的消息:

  1. % passwd
  2. Changing local password for trhodes
  3. Old Password:
  4. You can now choose the new password.
  5. A valid password should be a mix of upper and lower case letters,
  6. digits and other characters. You can use a 12 character long
  7. password with characters from at least 3 of these 4 classes, or
  8. a 10 character long password containing characters from all the
  9. classes. Characters that form a common pattern are discarded by
  10. the check.
  11. Alternatively, if no one else can see your terminal now, you can
  12. pick this as your password: "trait-useful&knob".
  13. Enter new password:

如果输入的密码与策略不匹配,将被拒绝并发出警告,用户有机会重试,重试次数不超过配置的次数。

大多数密码策略要求密码在多少天后失效。在 FreeBSD 中设置密码时间,在 /etc/login.conf 中为用户的登录类设置 passwordtimedefault 登录类包含一个示例:

  1. # :passwordtime=90d:\

因此,要将此登录类的有效期设置为 90 天,请删除注释符号 (#),保存编辑,然后运行 cap_mkdb /etc/login.conf

要设置单个用户的过期时间,需要传递一个过期日期或过期天数以及一个用户名给 pw:

  1. # pw usermod -p 30-apr-2015 -n trhodes

如此处所示,到期日期以日、月和年的形式设置。有关更多信息,请参见 pw(8)

14.2.5. Rootkit 检测

任何试图获得系统根权限的未经授权的软件都是 rootkit。一旦安装,这种恶意软件通常会给攻击者开辟另一条进入途径。现实上,一旦系统被 rootkit 入侵并进行了调查,就应该从头开始重新安装该系统。即使是最谨慎的安全或系统工程师,也有极大的风险会错过攻击者留下的东西。

rootkit 对管理员来说有一个作用:一旦检测到,它就表明在某个时候发生了破坏。但是,这些类型的应用程序往往隐藏得非常好。本节展示了一个可以用来检测 rootkit 的工具,security/rkhunter

安装此软件包或 port 后,可以使用以下命令检查系统。它将产生大量信息,并且需要手动按下回车键:

  1. # rkhunter -c

该过程完成后,一条状态信息将被打印到屏幕上。该信息将包括检查的文件数量、可疑文件、可能的 rootkit 等等。在检查过程中,可能会产生一些关于隐藏文件、OpenSSH 协议选择和已安装软件的已知脆弱版本的通用安全警告。这些可以现在处理,也可以在进行了更详细的分析后处理。

每个管理员都应该知道他们所负责的系统上正在运行什么。第三方工具(如 rkhunter 和 sysutils/lsof)以及本地命令如 netstatps,可以显示系统的大量信息。记下什么是正常的,当有什么东西看起来不对劲的时候要问清楚,并且要多疑。虽然防止入侵是理想的,但检测入侵是必须的。

14.2.6. 二进制验证

对系统文件和二进制文件的验证非常重要,因为它为系统管理和安全团队提供了有关系统变化的信息。一个监控系统变化的软件应用程序被称为入侵检测系统(IDS)。

FreeBSD 为基本的 IDS 系统提供了原生支持。虽然每晚的安全邮件会通知管理员更改的信息。但这些信息是存储在本地的。恶意用户有可能会修改这些信息以隐藏他们对系统的更改。因此,建议创建一套单独的二进制签名,并将其存储在一个只读的、root 拥有的目录下,或者最好是存储在可移动的 USB 盘或远程 rsync 服务器上。

内置的 mtree 工具可以用来生成一个目录内容的规范。一个种子,或一个数字常数,被用来生成规范,并被要求检查规范是否已经改变。这使得确定一个文件或二进制文件是否被修改成为可能。由于种子值对攻击者来说是未知的,伪造或检查文件的校验值将很难甚至不可能。下面的例子生成了一组 SHA256 哈希值,为 /bin 中的每个系统二进制文件生成一个,并将这些值保存在 root 的主目录下的一个隐藏文件中,即 /root/.bin_chksum_mtree

  1. # mtree -s 3483151339707503 -c -K cksum,sha256digest -p /bin > /root/.bin_chksum_mtree
  2. # mtree: /bin checksum: 3427012225

3483151339707503 代表种子。应记住此值,但不要共享此值。

查看 /root/.bin_cksum_mtree 应生成类似于以下内容的输出:

  1. # user: root
  2. # machine: dreadnaught
  3. # tree: /bin
  4. # date: Mon Feb 3 10:19:53 2014
  5. # .
  6. /set type=file uid=0 gid=0 mode=0555 nlink=1 flags=none
  7. . type=dir mode=0755 nlink=2 size=1024 \
  8. time=1380277977.000000000
  9. \133 nlink=2 size=11704 time=1380277977.000000000 \
  10. cksum=484492447 \
  11. sha256digest=6207490fbdb5ed1904441fbfa941279055c3e24d3a4049aeb45094596400662a
  12. cat size=12096 time=1380277975.000000000 cksum=3909216944 \
  13. sha256digest=65ea347b9418760b247ab10244f47a7ca2a569c9836d77f074e7a306900c1e69
  14. chflags size=8168 time=1380277975.000000000 cksum=3949425175 \
  15. sha256digest=c99eb6fc1c92cac335c08be004a0a5b4c24a0c0ef3712017b12c89a978b2dac3
  16. chio size=18520 time=1380277975.000000000 cksum=2208263309 \
  17. sha256digest=ddf7c8cb92a58750a675328345560d8cc7fe14fb3ccd3690c34954cbe69fc964
  18. chmod size=8640 time=1380277975.000000000 cksum=2214429708 \
  19. sha256digest=a435972263bf814ad8df082c0752aa2a7bdd8b74ff01431ccbd52ed1e490bbe7

此报告中包括计算机的主机名、创建规范的日期和时间以及创建规范的用户的名称。目录中的每个二进制文件都有一个校验和、大小、时间和 SHA256 摘要。

为了验证二进制签名没有变化,将目录中的当前内容与先前生成的规范进行比较,并将结果保存到文件中。这个命令需要用来生成原始规范的种子。

  1. # mtree -s 3483151339707503 -p /bin < /root/.bin_chksum_mtree >> /root/.bin_chksum_output
  2. # mtree: /bin checksum: 3427012225

这应该产生与创建规范时相同的 /bin 的校验和。如果这个目录中的二进制文件没有发生变化,那么 /root/.bin_chksum_output 输出文件将是空的。为了模拟变化,用 touch 改变 /bin/cat 的日期,然后再次运行验证命令。

  1. # touch /bin/cat
  2. # mtree -s 3483151339707503 -p /bin < /root/.bin_chksum_mtree >> /root/.bin_chksum_output
  3. # more /root/.bin_chksum_output
  4. cat changed
  5. modification time expected Fri Sep 27 06:32:55 2013 found Mon Feb 3 10:28:43 2014

建议为包含二进制文件和配置文件的目录以及包含敏感数据的任何目录创建规范。通常,为 /bin、/sbin/usr/bin/usr/sbin、/usr/local/bin、/etc/usr/local/etc 创建规范。

还有更高级的 IDS 系统存在,例如 security/aide。在大多数情况下,mtree 提供了管理员需要的功能。保持种子值和校验输出不被恶意用户发现是很重要的。关于 mtree 的更多信息可以在 mtree(8) 中找到。

14.2.7. 系统安全调优

在 FreeBSD 中,许多系统特性都可以使用 sysctl 进行调整 。本节将介绍一些可以调整以防止拒绝服务(DoS)攻击的安全功能。关于使用 sysctl 的更多信息,包括如何临时改变数值,以及如何在测试后使改变永久化,请参阅 “使用 sysctl(8) 进行调优”

注意
任何时候用 sysctl 改变一个设置,都会增加造成不希望的伤害的机会,影响系统的可用性。所有的改变都应该被监控,如果可能的话,在生产系统上使用之前,应该在测试系统上试用。

默认情况下。FreeBSD 内核启动时的安全级别为 -1。这被称为 “不安全模式”。因为不可变的文件标志可以被关闭,所有设备都可以被读出或写入。除非通过 sysctl 或启动脚本的设置来改变安全级别,否则安全级别将保持为 -1。通过在 /etc/rc.conf 中设置 kern_securelevel_enableYES,并将 kern_securelevel 的值设为所需的安全级别,可以在系统启动时提高安全级别。参见 security(7)init(8) 以了解更多关于这些设置和可用安全级别的信息。

警告
增加 securelevel 可能会破坏 Xorg 并导致其他问题。应该准备好做一些调试工作。

net.inet.tcp.blackholenet.inet.udp.blackhole 设置可以用来在关闭的端口上丢弃传入的 SYN 数据包,而不发送返回的 RST 响应。默认行为是返回 RST 以显示一个端口已关闭。更改默认值提供了针对端口扫描的某种级别的保护,用于确定系统上运行的应用程序。将 net.inet.tcp.blackhole 设置为 2,将 net.inet.udp.blackhole 设置为 1。请参考 blackhole(4) 以了解关于这些设置的更多信息。

et.inet.icmp.drop_redirectnet.inet.ip.redirect 设置有助于防止重定向攻击。重定向攻击是一种 DoS 类型,它发送大量的 ICMP 类型 5 数据包。由于这些数据包是不需要的,请将 net.inet.icmp.drop_redirect 设置为 1,将 net.inet.ip.redirect 设置为 0

源路由是一种检测和访问内部网络中不可路由的地址的方法。这应该被禁用,因为不可路由的地址通常都是故意不可路由的。要禁用这个功能,请将 net.inet.ip.sourceroutenet.inet.ip.accept_sourceroute 设置为 0

当网络上的一台机器需要向子网中的所有主机发送消息时,会向广播地址发送一个 ICMP 回声请求消息。然而,外部主机没有理由进行这样的操作。要拒绝所有的外部广播请求,把 net.inet.icmp.bmcastecho 设置为 0

另外 security(7) 中记录了一些其他设置。