第 4 章 认证

当用户(或程序)需要访问系统时,需要进行认证,确认身份是受信任。

[警告]警告

PAM 的配置错误可能会锁住你的系统。你必须有一个准备好的救援 CD,或者设立一个替代的 boot 分区。为了恢复系统,你需要使用它们启动系统并纠正错误。

[警告]警告

本章是基于 2013 年发布的 Debian 7.0 (Wheezy) 编写的,所以其内容正在变得过时。

4.1. 一般的 Unix 认证

一般的 Unix 认证由 PAM (Pluggable Authentication Modules,即可插入的验证模块) 下的 pam_unix(8) 模块提供。它的 3 个重要文件如下,其内的条目使用 “:” 分隔。

表 4.1. pam_unix(8) 使用的 3 个重要配置文件

文件权限用户说明
/etc/passwd-rw-r—r—rootroot(明文的)用户账号信息
/etc/shadow-rw-r——-rootshadow安全加密的用户账号信息
/etc/group-rw-r—r—rootroot组信息

/etc/passwd” 包含下列内容。

  1. ...
  2. user1:x:1000:1000:User1 Name,,,:/home/user1:/bin/bash
  3. user2:x:1001:1001:User2 Name,,,:/home/user2:/bin/bash
  4. ...

如 passwd(5) 中所述,这个文件中被 “:” 分隔的每项含义如下。

  • 登录名

  • 密码形式说明

  • 数字形式的用户 ID

  • 数字形式的组 ID

  • 用户名或注释字段

  • 用户家目录

  • 可选的用户命令解释器

/etc/passwd” 的第二项曾经被用来保存加密后的密码。在引入了 “/etc/shadow” 后,该项被用来说明密码形式。

表 4.2. “/etc/passwd” 第二项的内容

内容说明
(空)无需密码的账号
x加密后的密码保存在 “/etc/shadow
*无法登陆的账号
!无法登陆的账号

/etc/shadow” 包含下列内容。

  1. ...
  2. user1:$1$Xop0FYH9$IfxyQwBe9b8tiyIkt2P4F/:13262:0:99999:7:::
  3. user2:$1$vXGZLVbS$ElyErNf/agUDsm1DehJMS/:13261:0:99999:7:::
  4. ...

如 shadow(5) 中所述,这个文件中被 “:” 分隔的每项含义如下。

  • 登录名

  • 加密后的密码(开头的 “$1$” 表示使用 MD5 加密。“*” 表示无法登陆。)

  • 最后一次修改密码的时间,其表示从 1970 年 1 月 1 日起的天数

  • 允许用户再次修改密码的天数间隔

  • 用户必须修改密码的天数间隔

  • 密码失效前的天数,在此期间用户会被警告

  • 密码失效后的天数,在次期间密码依旧会被接受

  • 账号失效的时间,其表示从 1970 年 1 月 1 日起的天数

/etc/group” 包含下列内容。

  1. group1:x:20:user1,user2

如 group(5) 中所述,这个文件中被 “:” 分隔的每项含义如下。

  • 组名称

  • 加密后的密码(不会被真正使用)

  • 数字形式的组 ID

  • 使用 “,” 分隔的用户名列表

[注意]注意

/etc/gshadow” 为 “/etc/group” 提供了与 “/etc/shadow” 相似的功能,但没有被真正地使用。

[注意]注意

如果”auth optional pam_group.so“ 这行添加到了”/etc/pam.d/common-auth“,并且在”/etc/security/group.conf“ 里进行了设置,一个用户的实际组就可以被动态添加。参见 pam_group(8).

[注意]注意

base-passwd 软件包包含了一份用户和组的官方文档:“/usr/share/doc/base-passwd/users-and-groups.html”。

4.2. 管理账号和密码信息

下面是一些管理账号信息的重要命令。

表 4.3. 管理账号信息的命令

命令功能
getent passwd <user_name>浏览 “<user_name>” 的账号信息
getent shadow <user_name>浏览用户 “<user_name>“ 隐藏的账户信息
getent group <group_name>浏览 “<group_name>” 的组信息
passwd管理账号密码
passwd -e为激活的账号设置一次性的密码
chage管理密码有效期信息

其中的一些功能只能被 root 使用。密码和数据的加密参见 crypt(3)。

[注意]注意

在设置了 PAM 和 NSS 的系统上(例如 Debian salsa 机器),本地的 “/etc/passwd”、“/etc/group” 和 “/etc/shadow” 可能不会被系统激活使用。上述的命令即使处于这种环境下依旧是有效的。

4.3. 好密码

在系统安装时建立一个账号或使用 passwd(1) 命令时,你应该选择一个好密码,它应该由 6 到 8 个字符组成,其中包含下列根据 passwd(1) 设定的每个组合中的一个或多个字符。

  • 小写字母

  • 数字 0 到 9

  • 标点符号

[警告]警告

密码中不要使用可以猜到的词。账号名、身份证号码、电话号码、地址、生日、家庭成员或宠物的名字、字典单词、简单的字符序列(例如 “12345” 或 “qwerty”)等都是糟糕的选择。

4.4. 设立加密的密码

下面是一些用于 生成加盐的加密密码) 的独立工具。

表 4.4. 生成密码的工具

软件包流行度大小命令功能
whoisV:35, I:393364mkpasswd具备 crypt(3) 库所有特性的前端
opensslV:794, I:9931465openssl passwd计算密码哈希 (OpenSSL). passwd(1ssl)

4.5. PAM 和 NSS

现代的类 Unix 系统(例如 Debian 系统)提供 PAM (Pluggable Authentication Modules,插入式验证模块)NSS(Name Service Switch,名称服务切换) 机制给本地系统管理员,使他们能够配置自己的系统。它们的功能可以概括为以下几点。

  • PAM 给应用软件提供了一个灵活的认证机制,因此涉及到了密码数据的交换。

  • NSS 提供了一个灵活的名称服务机制,它经常被 C 标准库使用,使例如 ls(1) 和 id(1) 这样的程序获得用户和组名称。

PAM 和 NSS 系统必须保持配置一致。

PAM 和 NSS 系统中重要的软件包如下。

表 4.5. PAM 和 NSS 系统中重要的软件包

软件包流行度大小说明
libpam-modulesV:807, I:9991032插入式验证模块(基础服务)
libpam-ldapI:12249允许 LDAP 接口的插入式验证模块
libpam-cracklibI:16115启用 cracklib 支持的插入式验证模块
libpam-systemdV:474, I:853573用于 logind 注册用户会话的插入式验证模块(PAM)
libpam-docI:11044插入式验证模块(html 和 文本文档)
libc6V:935, I:99912771GNU C 库:同样提供“名称服务切换”服务的共享库
glibc-docI:113161GNU C 库:帮助页面
glibc-doc-referenceI:512740GNU C 库:参考手册,有 info、pdf 和 html 格式(non-free)
libnss-mdnsI:526150用于解析组播 DNS 名称的 NSS 模块
libnss-ldapI:11265NSS 模块,用于使用 LDAP 作为一个名称服务的
libnss-ldapdI:14153NSS 模块,用于使用 LDAP 作为一个名称服务的(libnss-ldap 的新 fork)
  • libpam-doc 中 “The Linux-PAM System Administrators’ Guide” 是了解 PAM 配置的必要文档。

  • glibc-doc-reference 中的 “System Databases and Name Service Switch” 是了解 NSS 配置的重要文档。

[注意]注意

你可以使用 “aptitude search ‘libpam-|libnss-‘” 命令查看更多的相关软件包。NSS 缩写也可能意味着 “Network Security Service,网络安全服务”,它不同于 “Name Service Switch,名称服务切换”。

[注意]注意

PAM 是为每个程序初始化环境变量为系统默认值的最基础方法。

systemd 下, libpam-systemd 软件包被安装用来管理用户登录,通过在 systemd 控制组层,为 logind 注册用户会话来实现。参见 systemd-logind(8), logind.conf(5), 和 pam_systemd(8).

4.5.1. PAM 和 NSS 访问的配置文件

下面是一些 PAM 和 NSS 访问的重要配置文件。

表 4.6. PAM 和 NSS 访问的配置文件

配置文件功能
/etc/pam.d/<program_name>为 “<program_name>” 程序设置 PAM 配置;参加 pam(7) 和 pam.d(5)
/etc/nsswitch.conf为每个服务条目设置 NSS 配置。参见 nsswitch.conf(5)
/etc/nologin通过 pam_nologin(8) 模块限制用户登陆
/etc/securetty通过 pam_securetty(8) 模块限制 root 访问 tty
/etc/security/access.conf通过 pam_access(8) 模块设置访问限制
/etc/security/group.conf通过 pam_group(8) 模块设置基于组的限制
/etc/security/pam_env.conf通过 pam_env(8) 模块设置环境变量
/etc/environment通过带有 “readenv=1” 参数的 pam_env(8) 模块设置额外的环境变量
/etc/default/locale通过带有 “readenv=1 envfile=/etc/default/locale” 参数的 pam_env(8) 模块设置语言环境值(在 Debian 系统中)
/etc/security/limits.conf通过 pam_linits(8) 模块设置资源限制(ulimit、core 等等)
/etc/security/time.conf通过 pam_time(8) 模块设置时间限制
/etc/systemd/logind.conf设置systemd 的登录管理器配置 (参见 logind.conf(5) 和 systemd-logind.service(8))

密码选择的限制是通过 PAM 模块 pam_unix(8) 和 pam_cracklib(8) 来实现的。它们可以通过各自的参数进行配置。

[提示]提示

PAM 模块在文件名中使用后缀 “.so”。

4.5.2. 现代的集中式系统管理

现代的集中式系统管理可以使用集中式的轻量目录访问协议(LDAP)服务器进行部署,从而通过网络管理许多类 Unix 和 非类 Unix 系统。轻量目录访问协议的开源实现是 OpenLDAP 软件

LDAP 服务器使用带有 PAM 和 NSS 的libpam-ldaplibnss-ldap 软件包为 Debian 系统提供账号信息。需要一些动作来启用 LDAP(我没有使用过这个设置,并且下面的信息纯粹是第二手的信息。请在这种前提下阅读下列内容。)。

  • 你通过运行一个程序,例如独立的 LDAP 守护进程 slapd(8),来建立集中式的 LDAP 服务器。

  • 你在 “/etc/pam.d/” 目录中的 PAM 配置文件里,使用 “pam_ldap.so” 替代默认值 “pam_unix.so”。

    • Debian 使用 “/etc/pam_ldap.conf” 作为 libpam-ldap 的配置文件,“/etc/pam_ldap.secret” 作为保存 root 密码的文件。
  • 你在 “/etc/nsswitch.conf” 文件中改变 NSS 配置,使用 “ldap” 替代默认值(“compat” 或 “file”)。

    • Debian 使用 “/etc/libnss-ldap.conf” 作为 libnss-ldap 的配置文件。
  • 为了密码的安全,你必须让 libpam-ldap 使用 SLL(或 TLS)连接。

  • 为了确保 LDAP 网络开销数据的完整性,你必须让 libpam-ldap 使用 SLL(或 TLS)连接。

  • 为了减少 LDAP 网络流量,你应该在本地运行 nscd(8) 来缓存任何 LDAP 搜索结果。

参见由 libpam-doc 软件包提供的 pam_ldap.conf(5) 中的文档和 “/usr/share/doc/libpam-doc/html/”,以及 glibc-doc 软件包提供的 “info libc 'Name Service Switch'”。

类似地,你可以使用其它方法来设置另一种集中式的系统。

4.5.3. “为什么 GNU su 不支持 wheel 组”

这是在旧的 “info su” 底部 Richard M. Stallman 所说的一句名言。别担心:Debian 系统中当前的 su 命令使用了 PAM,这样当在 “/etc/pam.d/su” 中启用了带有 “pam_wheel.so” 的行后,就能够限制非 wheel 组的用户 suroot 组的能力。

4.5.4. 严格的密码规则

安装 libpam-cracklib 软件包你能够强制使用严格的密码规则,例如,通过在 “/etc/pam.d/common-password” 中添加下列行。

对于 squeeze 发行版:

  1. password required pam_cracklib.so retry=3 minlen=9 difok=3
  2. password [success=1 default=ignore] pam_unix.so use_authtok nullok md5
  3. password requisite pam_deny.so
  4. password required pam_permit.so

4.6. 其它的访问控制

[注意]注意

参见 第 9.3.15 节 “Alt-SysRq 键” 来限制内核的安全警告密钥(SAK)功能。

4.6.1. sudo

sudo(8) 程序是为了使一个系统管理员可以给用户受限的 root 权限并记录 root 活动而设计的。sudo 只需要一个普通用户的密码。安装 sudo 软件包并通过设置 “/etc/sudoers” 中的选项来使用它。参见 “/usr/share/doc/sudo/examples/sudoers” 和 第 1.1.12 节 “sudo 配置” 中的配置示例。

我将 sudo 用于单用户系统(参见 第 1.1.12 节 “sudo 配置”)是为了防止自己可能做出的愚蠢行为。就我个人而言,我认为使用 sudo 会比使用 root 账号操作系统来得好。例如,下列命令将 “<some_file>” 的拥有者改变为 “<my_name>”。

  1. $ sudo chown <my_name> <some_file>

当然如果你知道 root 密码(比如自行安装 Debian 的用户所做的),任何用户账号都可以使用 “su -c” 让任何命令以 root 运行。

4.6.2. PolicyKit

PolicyKit 是在类 Unix 操作系统中控制整个系统权限的一个操作系统组件。

较新的 GUI 图形界面程序设计时便考虑到了不作为特权进程来运行。它们通过 PolicyKit 来和特权进程通信,从而执行管理操作。

在 Debian 系统中,PolicyKit 限制了属于 sudo 组的用户账号的这种操作。

参见 polkit(8)。

4.6.3. SELinux

Security-Enhanced Linux (SELinux) 是一个收紧权限模块的框架,它比普通的类 Unix 安全模块 mandatory access control (MAC) 策略更严格。 root 权限在某些条件下被限制。

4.6.4. 限制访问某些服务端的服务

对系统安全而言,尽可能的禁用服务程序,是一个好的主意。网络服务是危险的。有不使用的服务,不管是直接由后台守护进程(daemon))激活,还是通过super-server 程序激活,都被认为是安全风险。

许多程序,比如说 sshd(8), 使用基于 PAM 的访问控制。也还有许多方式来限制访问一些服务端的程序。

参见 第 3.2.6 节 “systemd 下的系统管理”, 第 4.5.1 节 “PAM 和 NSS 访问的配置文件”, 和 第 5.10 节 “Netfilter 网络过滤框架”.

[提示]提示

NFS 和其它基于 RPC 的程序,需要激活 Sun RPC 服务。

[提示]提示

如果你远程访问最新的 Debian 系统有问题,看下在”/etc/hosts.deny“里是否存在”ALL: PARANOID”这样讨厌的配置,请把它注释掉。(但是你必须注意这种行为所带来的安全风险。)

4.7. 安全认证

[注意]注意

这里的信息也许不能完全满足你的安全需求,但这里应当是一个好的起点

4.7.1. 确保互联网上的的密码安全

许多流行的传输层服务都使用纯文本来传输包括密码验证信息在内的各类消息。使用纯文本在公网上传输密码是很糟糕的做法,因为这样传输的密码很容易在网上被他人截获。为了确保整个沟通过程,包括密码信息在内都使用加密传输来确保安全,您可以在“传输层安全(Transport Layer Security,TLS)”协议或者其前身,“安全套接字层(Secure Sockets Layer,SSL)”协议之上运行这些服务。

表 4.7. 安全和不安全的服务端口列表

不安全的服务名端口安全的服务名端口
www (http)80https443
smtp (邮件)25ssmtp (smtps)465
ftp-data20ftps-data989
ftp21ftps990
telnet23telnets992
imap2143imaps993
pop3110pop3s995
ldap389ldaps636

加密消耗 CPU 时间。作为对 CPU 有益的替代方案,你可以保持使用纯文本通讯,仅仅使用安全认证协议加密密码,比如说:POP 使用”Authenticated Post Office Protocol” (APOP),SMTP 和 IMAP 使用 “Challenge-Response Authentication Mechanism MD5” (CRAM-MD5)。(你的邮件客户端通过互联网上你的邮件服务器发送邮件时,最近流行使用新的递交端口 587 来代替传统的 SMTP 端口 25,这样可以避免在使用 CRAM-MD5 认证自己时,网络提供商阻塞 25 端口。)

4.7.2. 安全 Shell

安全 Shell (SSH) 程序使用安全认证来提供不安全网络上两个不可信任主机之间的安全加密通讯。它由 OpenSSH 客户端, ssh(1), 和 OpenSSH 后台守护进程(daemon), sshd(8)组成.SSH 使用端口转发特性,可以给 POP 和 X 之类的不安全的协议通讯建立隧道,使其可以在互联网上安全传输。

客户端可以使用如下方式来认证自己:基于主机的认证、公钥认证、质疑应答认证、密码认证。使用公钥认证,可以实现远程免密码登录。参见 第 6.9 节 “服务器远程访问和工具 (SSH)”.

4.7.3. 互联网额外的安全方式

即使你运行 Secure Shell (SSH)Point-to-point tunneling protocol (PPTP) 这样的安全服务,在互联网上,仍然有机会使用野蛮暴力猜测密码攻击进入。 使用防火墙策略 (参见 第 5.10 节 “Netfilter 网络过滤框架”),并和下面的安全工具一起,可以提升安全形势。

表 4.8. 提供额外安全方式的工具列表

软件包流行度大小说明
knockdV:0, I:3102小的 port-knock 后台守护进程(daemon) knockd(1) 和客户端 konck(1)
fail2banV:112, I:1232092禁用造成多个认证错误的 IP
libpam-shieldV:0, I:0115把尝试猜测密码的远程攻击者关在外面

4.7.4. root 密码安全

为阻止人们使用 root 权限访问你的机器,你需要做下面的操作。

  • 阻止对硬盘的物理访问

  • 锁住 BIOS 来阻止从可移动介质启动

  • 为 GRUB 交互式会话设置密码

  • 锁住 GRUB 菜单,禁止编辑

如果可以物理访问硬盘,则可以使用下面的步骤,相对简单的重置密码。

  1. 将硬盘拿到一个可以设置 BIOS 从CD 启动的电脑。

  2. 使用紧急介质启动系统(Debian 启动磁盘, Knoppix CD, GRUB CD, …)。

  3. 用读写访问挂载根分区。

  4. 编辑根分区的”/etc/passwd“文件,使 root 账户条目的第二段为空。

对于 grub-rescue-pc ,即使用紧急介质启动的电脑,如果有编辑 GRUB 菜单条目 (参见 第 3.1.2 节 “第二阶段:引载加载程序”) 的权限,在启动时,使用下面的步骤更加简单。

  1. 使用内核参数启动系统来修改一些事情,比如说,”root=/dev/hda6 rw init=/bin/sh“.

  2. 编辑 “/etc/passwd“ 文件,使 root 账户条目的第二段为空。

  3. 重启系统。

系统的 root shell 现在可以无密码访问了。

[注意]注意

一旦某人拥有 root shell 访问权限,他能够访问任何内容,并可以重设系统上的任何密码。此外,他可以使用 johncrack 等软件包的暴力破解工具来比较所有用户的密码 (参见 第 9.4.11 节 “系统安全性和完整性检查”)。被破解的密码,可以用来和其它系统进行比较。

为避免这些相关问题,仅有的理论上的软件解决方案是使用 dm-crypt 和 initramfs (参见 第 9.8 节 “数据加密提示”)加密 root 分区(或 “/etc“ 分区) 。这样的话,你总是需要密码来启动系统。