跳转到内容

Ict-创新/LPI/110.1

来自维基教科书,开放世界中的开放书籍

110.1 执行安全管理任务

[编辑 | 编辑源代码]

候选人应该知道如何审查系统配置,以确保主机安全符合本地安全策略。

关键知识领域

  • 审计系统以查找具有 suid/sgid 位设置的文件。
  • 设置或更改用户密码和密码老化信息。
  • 能够使用 nmap 和 netstat 发现系统上的开放端口。
  • 设置用户登录、进程和内存使用量的限制。
  • 基本的 sudo 配置和使用。
  • 在启动时阻止 Root 访问。



加固 init

许多系统(在其默认配置中)可以启动到单用户模式以获取 root shell,而无需提供 root 密码。例如,对于 RHEL5 来说就是这样。为了防止这种情况,编辑 /etc/inittab 并添加以下行

ss:S:respawn:/bin/sulogin

这行告诉系统,要进入状态“S”(单用户),它必须成功运行程序 /sbin/sulogin,该程序会要求输入 root 密码。此更改将阻止用户通过简单的单用户启动获得 root 访问权限。


加固 GRUB

还有其他引导时漏洞会涉及修改 GRUB 传递给内核的选项。您可以通过设置 GRUB 密码来防止这些漏洞。 为此

  1. 启动 Linux 并运行 grub
  2. 在 grub 提示符下,输入命令 md5crypt
  3. 在密码提示符下,输入所需的密码
  4. 您将看到密码哈希(以“$1...”开头)
  5. 编辑文件 /boot/grub/grub.conf 并添加类似以下内容的行

password --md5 $1$c1Vcl/$RlF6Wm6XF3amlhOcDTCdv.

(这里您应该复制并粘贴您在步骤 4 中得到的密码哈希)。

此行的效果取决于您在 grub.conf 中的位置。如果您将其放在与特定引导菜单选择相对应的节段(即“title”行之后)中,那么如果您从引导菜单中选择该项,grub 将始终要求输入密码。但是,如果您将其放在这些节段之外,grub 将只会在您尝试在引导时编辑命令时要求输入密码。换句话说,使用 grub 配置中的现有项进行标准引导不需要密码。


以下是将密码放在“title”节段内的 grub.conf 示例

default=0

timeout=5

splashimage=(hd0,0)/boot/grub/splash.xpm.gz

hiddenmenu

title Red Hat Enterprise Linux Client (2.6.18-92.el5)

root (hd0,0)

kernel /boot/vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet

initrd /boot/initrd-2.6.18-92.el5.img

password --md5 $1$c1Vcl/$RlF6Wm6XF3amlhOcDTCdv.


加固 BIOS

对计算机有物理访问权限的潜在入侵者可以从救援磁盘(或任何“实时”Linux CD)启动,然后挂载并访问硬盘上的文件系统。为了防止这种情况,BIOS 应该配置为只从硬盘启动。完成后,在 BIOS 上设置密码。


入侵检测

在您的系统上拥有合法帐户的用户,如果获得了 root 访问权限一段时间(也许是因为您在 root 登录仍然处于活动状态的情况下离开了计算机),他们可以通过创建由 root 拥有并打开了“setuid”位的可执行程序来植入“后门”。此特殊模式位会导致可执行文件以文件所有者的有效权限运行。

您可以通过列出更改密码程序来查看此类程序的示例

# ls -l /usr/bin/passwd

-rwsr-xr-x 1 root root 27768 Jul 17 2006 /usr/bin/passwd


请注意第 4 个字符位置的“s”,它表明设置用户 ID 位已打开。此程序“设置为 root”,以便普通(非 root)用户可以使用它来更改他们的密码(这需要更新其密码哈希在 /etc/shadow 中)。

系统上存在许多合法的 setuid 程序。但是,意外的 setuid 程序(尤其是由 root 拥有的)表明入侵者可能创建了后门。您可以使用 find 命令找到此类程序;例如

# find / -user root -perm +4000 2> /dev/null

/bin/ping

/bin/su

/bin/mount

/usr/bin/passwd

/usr/bin/sudo

/usr/bin/crontab

/usr/bin/sudoedit

/usr/bin/chage

/usr/bin/rlogin

/usr/bin/rsh

/usr/bin/at

/usr/bin/chfn

/usr/bin/newgrp

... 删除了许多输出行 ...

在此示例中,值“+4000”表示 setuid 模式位的八进制值。

您可以通过在系统处于原始状态时首先捕获这些文件的列表来实现简单的入侵检测系统

# find / -user root -perm +4000 2> /dev/null > /root/good-setuid-list



之后,您可以构建一个新列表,然后比较这两个列表。在下面的示例中,故意创建了 bash 的新的 setuid 复制品


# find / -user root -perm +4000 2> /dev/null > /root/new-setuid-list

# diff /root/good-setuid-list /root/new-setuid-list

36a37

> /home/chris/bash

入侵检测工具(如 tripwire 和 AIDE(高级入侵检测环境))提供了一种更彻底、更系统的方法来检测文件系统中意外的变化。它们的使用超出了 LPI-1 的范围。

还存在一个“设置组 ID”位(八进制值为 2000),它会导致可执行文件以其组的有效组标识运行。例如

# ls -l /usr/bin/wall

-r-xr-sr-x 1 root tty 14792 Oct 13 2006 /usr/bin/wall

虽然不太常见(也不太危险),但您也可以使用 find 搜索 setgid 程序


# find / -perm +2000 2> /dev/null

/usr/bin/ssh-agent

/usr/bin/xterm

/usr/bin/crontab

/usr/bin/locate

... 删除行 ...

/usr/bin/wall


密码管理

用户可以使用 passwd 命令设置他们自己的密码

$ passwd

正在更改用户 chris 的密码。

正在更改 chris 的密码

(当前)UNIX 密码

新 UNIX 密码

重新输入新 UNIX 密码

passwd: 所有身份验证令牌已成功更新。


Root 可以设置或更改任何用户的密码

# passwd chris

正在更改用户 chris 的密码。

新 UNIX 密码

密码错误:基于字典词

重新输入新 UNIX 密码

passwd: 所有身份验证令牌已成功更新。


注意,当非 root 用户设置其密码时,会强制执行密码强度检查。但是,当 root 设置用户的密码时,密码强度检查只会发出警告;它不会阻止 root 设置弱密码。

密码强度检查策略由 PAM 模块控制。要进一步控制密码强度,请考虑使用 pam_passwdqc 或 pam_cracklib 模块。

密码不会以纯文本形式存储在系统的任何位置。相反,它们的哈希会被写入文件 /etc/shadow 中。这是一个示例行

# grep chris /etc/shadow

chris:$1$z5b2XDJ7$LLOh4VX5us3UMP2PMFXFp0:14869:0:99999:7::


当用户登录并提供其密码时,它会被哈希化,并且哈希会与 /etc/shadow 中的哈希进行比较。密码可以被锁定解锁以暂时禁用和重新启用帐户。Root 可以使用 passwd -l 锁定任何用户的密码,并使用 passwd -u 解锁。锁定密码只是在密码哈希前面放置“!!” 以便它不再是有效的哈希。解锁密码只是删除“!!” 字符

# passwd -l chris

正在锁定用户 chris 的密码。

passwd: 成功

# grep chris /etc/shadow

chris:!!$1$z5b2XDJ7$LLOh4VX5us3UMP2PMFXFp0:14869:0:99999:7::

# passwd -u chris

正在解锁用户 chris 的密码。

passwd: 成功。

# grep chris /etc/shadow

chris:$1$z5b2XDJ7$LLOh4VX5us3UMP2PMFXFp0:14869:0:99999:7::

可以实施密码老化策略,迫使用户定期选择新密码,或者在指定日期强制用户帐户过期。密码老化参数存储在 /etc/shadow 中的字段 3-8 中,并使用 chage 命令进行管理。chage 命令的选项包括

-ESet 帐户过期日期

-mSet 密码更改之间的最短天数(0 表示“无最低天数”)

-MSet 密码的最大有效期

-WSet 密码即将过期时向用户发出警告的提前期(天数)

-l列出当前的密码老化值


示例

# chage -E 31-12-2011 -M 30 -W 7 chris

# chage -l chris

上次密码更改时间:Sep 17, 2010

密码过期时间:Oct 17, 2010

密码失效时间:从不

帐户过期时间:Jun 02, 2037

密码更改之间最短天数:0

密码更改之间最长天数:30

密码过期前警告天数:7


最佳实践

[编辑 | 编辑源代码]

系统管理员应尽量减少以 root 用户身份登录的时间。他们应该拥有一个用于一般工作的普通帐户,并且只在需要执行需要 root 权限的操作时才切换到 root 用户。切换到 root 用户使用 su(替换用户)命令执行。

该命令的一般形式为

su [-l] [user]

su 会提示输入用户的密码,然后启动一个以该用户身份运行的 shell。如果未指定用户名,则该命令会启动一个 root shell。这是最常见的用法。'-l' 选项告诉 su 启动一个登录 shell。此 shell 将执行与用户最初登录时相同的启动处理;也就是说,它将设置用户的环境,包括其搜索路径。通常,这就是您想要执行的操作。(您也可以使用 '-' 代替 '-l'

id 命令可用于显示用户的标识和组成员资格。在下面的示例中,我们使用它来检查使用 su 之前和之后的身份

[[Image:]]

$ id

uid=500(chris) gid=500(chris) groups=500(chris)

$ su - l

密码

# id

uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)

sudo 命令可用于授予非 root 用户以 root 用户身份运行特定命令的能力,而无需告诉他们 root 密码。它由文件配置。

以下是从该文件中的一条简单规则的示例

chris ALL=(ALL) /sbin/iptables

有了这条规则,chris 可以提升其权限以 root 用户身份运行 iptables 命令

$ /sbin/iptables -F

iptables v1.3.5: 权限被拒绝(您必须是 root 用户)

$ sudo /sbin/iptables -F

[sudo] chris 的密码

$

这里请求的密码是用户自己的密码,不是 root 密码。

以下是从 sudoers 中的一条更复杂的规则

harry williambox=(william) /bin/ls, /home/william/bin/testscript.sh

此规则允许 harry 以 william 的身份在 williambox 机器上运行 /bin/ls 和 /home/william/bin/testcript.sh。 (将 sudo 规则限制在特定机器上,对于网络共享 sudoers 文件很有用。)请注意,sudoers 文件中的命令必须使用绝对路径名指定。

sudo 存在一个“宽限期”,在此期间不会再次提示输入密码。 这可以通过在 sudoers 文件中添加以下类似的行来设置

Defaults timestamp_timeout=10

将其设置为 0 将强制 sudo 每次都提示输入密码。 用户可能会觉得这很烦人!

通过定义 *用户别名*(用户命名列表)、*主机别名*(主机命名列表)和 *命令别名*(命令命名列表),可以使更大、更复杂的 sudoers 文件更易于维护。 以下是一个更长的示例

User_Alias ADMINS = jsmith, mikem

Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum

Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig

Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount

Host_Alias FILESERVERS = fs1, fs2

Host_Alias MAILSERVERS = smtp, smtp2

ADMINS FILESERVERS = STORAGE

chris ALL = SOFTWARE

%wheel ALL = (ALL) ALL

在这个例子中,命令别名实际上定义了角色,从该角色需要能够执行的命令集合的角度来看。 文件的最后三行是实际规则。 依次来看

  1. 用户别名 ADMINS 的成员可以在主机别名 FILESERVERS 列出的任何机器上执行命令别名 STORAGE 中的任何命令
  2. chris 可以在所有机器上执行命令别名 SOFTWARE 中的命令
  3. Linux wheel 组的成员可以在任何机器上以 root 身份执行任何命令

必须使用 visudo 命令编辑 sudoers 文件。 不要直接编辑它。 visudo 命令将在保存文件之前验证文件是否语法有效。

使用 sudo 有许多优点

  1. 需要知道 root 密码的人数最少
  2. 用户以 root 身份运行的时间最短(仅执行一个命令的持续时间),并且立即恢复到非 root 命令提示符
  3. sudo 记录其所有操作,通常记录在 /var/log/secure 中。 因此,保留了所有 root 活动的审计跟踪。

Ubuntu 专用于 root 命令。 在默认配置中,root 帐户被锁定,因此无法直接以 root 身份登录或使用 su 成为 root。 相反,所有操作都使用 sudo。 Ubuntu sudoers 文件中的关键行如下所示

%admin ALL = (ALL) ALL

安装 Ubuntu 时创建的初始帐户会自动成为 *admin* 组的成员。

查找和关闭端口

机器只应运行其应该运行的服务。 不需要的服务及其关联的开放端口可能会削弱安全性。 如果不应该运行服务,请确保它没有配置为启动。 对于 RedHat 风格的发行版(或使用传统“System-V”风格服务管理的其他发行版),使用 chkconfig 命令检查和修改服务的运行状态。 以下命令序列展示了如何检查 httpd 守护程序(Web 服务器)的当前状态并禁用它。

# chkconfig --list httpd

httpd 0:off1:off2:on3:on4:on5:on6:off

# chkconfig httpd off

# chkconfig --list httpd

httpd 0:off1:off2:off3:off4:off5:off6:off

在上面的示例中,我们看到 httpd 最初被配置为在运行级别 2、3、4 和 5 中启动。

请注意,chkconfig 仅影响启动时行为(或更准确地说,运行级别更改时的行为)。 使用 chkconfig 关闭服务实际上不会停止它运行。 为此,您应该运行服务的控制脚本

# /etc/init.d/httpd stop

Stopping httpd: [ OK ]

检查正在运行的服务的另一种方法是列出机器上的开放端口。 您可以使用 netstat 或 lsof 来执行此操作; 这些在主题 109.3 中进行了讨论。

您还可以使用 nmap 确定哪些端口已打开。 Nmap 是一个“网络侦察”工具,更常被称为 *端口扫描器*。 Nmap 会从“外部”检查您的开放端口,而 netstat 和 lsof 会从机器的“内部”检查它们。 Nmap 也用于验证您的防火墙是否按预期的方式工作。

但是,请注意,nmap 也可用于攻击机器的初始阶段,以确定正在运行的端口,从而确定可能被利用的漏洞。 因此,在您的机器上运行端口扫描(即使是您自己的机器)也可能被视为敌对行为,您应该在执行此操作之前获得管理权限。

下图总结了 nmap 的命令语法

以下是一个 nmap 扫描的示例

$ nmap 192.168.81.130

Starting Nmap 5.00 ( http://nmap.org ) at 2010-09-17 16:09 BST

Interesting ports on 192.168.81.130

Not shown: 997 closed ports

PORT STATE SERVICE

22/tcp open ssh

80/tcp open http

111/tcp open rpcbind

Nmap done: 1 IP address (1 host up) scanned in 0.20 seconds


用户限制

当 /etc/nologin 文件存在(它可以为空)时,它将阻止所有用户登录到系统(root 用户除外)。 如果 **nologin** 文件包含一条消息,则该消息将在成功身份验证后显示。

在 /etc/security/ 目录中,是一组允许管理员限制用户 CPU 时间、最大文件大小、最大连接数等,以每用户为基础的文件。

/etc/security/access.conf 文件可用于禁止来自特定位置的组和用户登录。

/etc/security/limits.conf 文件可用于为多种资源设置硬限制和软限制。 此文件中的每一行都采用以下格式

<domain> <type> <item> <value>


domain 用户名或组名(带 @group)


type hard 或 soft


item

core - 限制核心文件大小(KB)

data - 最大数据大小(KB)

fsize - 最大文件大小(KB)

memlock - 最大锁定在内存中的地址空间(KB)

nofile - 最大打开文件数

cpu - 最大 CPU 时间(分钟)

nproc - 最大进程数

as - 地址空间限制

maxlogins - 此用户的最大同时登录数

priority - 运行用户进程的优先级

locks - 用户可以持有的最大文件锁数


这不是完整的列表 - 有关完整列表,请参阅 limits.conf(5) 的手册页。

以下是一些来自 limits.conf 的示例条目,并附有注释

# 用户 ellie 永远无法创建大于 100 MB 的文件

ellie hard fsize 102400

# Ellie 必须增加其软限制才能创建大于 50 MB 的文件

ellie soft fsize 51200

# student 组的用户无法运行超过 50 个同时进程

@student hard nproc 20

# 默认情况下,除非用户提高其软限制,否则任何用户都无法创建核心文件

* soft core 0

资源的软限制是目前有效的限制。 硬限制是用户可以将软限制增加到的最大值。

用户可以使用 ulimit 命令(shell 内置命令)来更改当前有效的限制。 (非 root)用户可以将软限制设置为不超过硬限制的任何值。 他也可以降低硬限制(但不能再将其提高)。 这些限制在该 shell 的上下文中保持,并由该 shell 启动的任何程序继承。 但是,如果用户注销并重新登录,则限制将从 limits.conf 中重新建立。


ulimit 命令接受许多选项,包括

-a 报告所有当前限制

-c 创建的核心文件的最大大小

-d 进程数据段的最大大小

-e 最大调度优先级(“nice”)

-f shell 及其子进程写入的文件的最大大小

-i 最大挂起信号数

-l 可以锁定到内存中的最大大小

-n 最大打开文件描述符数

-p 以 512 字节块为单位的管道大小(这可能无法设置)

-q POSIX 消息队列中的最大字节数

-r 最大实时调度优先级

-s 最大堆栈大小

-t 最大 CPU 时间(秒)

-u 单个用户可用的最大进程数

-v shell 可用的最大虚拟内存

-x 最大文件锁数


在下面的示例中,我们将最大 CPU 时间设置为 100 秒,然后报告所有值

$ ulimit -t 100

$ ulimit -a

core file size (blocks, -c) 0

data seg size (kbytes, -d) unlimited

scheduling priority (-e) 0

file size (blocks, -f) unlimited

pending signals (-i) 8192

max locked memory (kbytes, -l) 32

max memory size (kbytes, -m) unlimited

open files (-n) 1024

pipe size (512 bytes, -p) 8

POSIX message queues (bytes, -q) 819200

real-time priority (-r) 0

stack size (kbytes, -s) 10240

cpu time (seconds, -t) 100

max user processes (-u) 8192

virtual memory (kbytes, -v) unlimited

file locks (-x) unlimited

从 limits.conf 中的设置在登录时建立 ulimit 设置是由 PAM 模块 pam_limits 执行的。 一些系统也支持 /etc/security/limits.d 目录。 发现的任何文件的內容将依次处理,就好像它们附加到 /etc/security/limits.conf 一样。



以下是使用过的文件、术语和实用程序的部分列表:* find

  • passwd
  • lsof
  • nmap
  • chage
  • netstat
  • sudo
  • /etc/sudoers
  • su
  • usermod
  • ulimit


上一章 | 下一章

华夏公益教科书