前言
我们在前面介绍了 PAM ,接下来我们来看看实际情况下的常见安全加固。
安全加固
-
SSH 禁止 root 登录
Shell > vim /etc/ssh/sshd_config ... PermitRootLogin no PermitEmptyPasswords no ...
-
用户更改密码的密码复杂度
前面 《PAM03 — 身份认证的案例》 已经说明,略过。
-
限制 ssh 的密码尝试次数并锁定账号
前面 《PAM03 — 身份认证的案例》》已经说明,略过。
-
记住最近的三个密码(即禁止修改密码为最近三次的)
前面 《PAM03 — 身份认证的案例》已经说明,略过。
-
/etc/login.defs
该文件仅对新添加的用户生效,对已经存在的用户不生效
Shell > grep -v ^# /etc/login.defs |grep -v ^$ MAIL_DIR /var/spool/mail UMASK 022 HOME_MODE 0700 PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_MIN_LEN 5 PASS_WARN_AGE 7 UID_MIN 1000 UID_MAX 60000 SYS_UID_MIN 201 SYS_UID_MAX 999 GID_MIN 1000 GID_MAX 60000 SYS_GID_MIN 201 SYS_GID_MAX 999 CREATE_HOME yes USERGROUPS_ENAB yes ENCRYPT_METHOD SHA512 SHA_CRYPT_MAX_ROUNDS 5000
MAIL_DIR
– 定义系统自带邮件的目录位置UMASK
– 定义普通用户(uid>=1000)家目录的权限,默认值为 022,则表示权限为 755。可被 HOME_MODE 参数的值覆盖。PASS_MAX_DAYS
– 以天为单位定义密码的最大生存周期,即密码的最大有效期。当用户被添加后,其对应于 /etc/shadow 文件的第三个字段。PASS_MIN_DAYS
– 以天为单位定义密码的最小生存周期,即密码的最小有效期或两次密码的修改时间间隔。当用户被添加后,其对应于 /etc/shadow 文件的第四个字段。默认 0 值,也就是说第二次修改密码时不受限制;如果是 5 ,表示 5 天以内不允许修改密码。PASS_MIN_LEN
– 定义密码的长度。早期的 GNU/Linux 是用 login.defs 定义密码长度,但是由于定义的密码规则过于简单,因此该参数项不生效。PASS_WARN_AGE
– 定义密码到期前的警告天数,即/ etc/shadow 的第六个字段,与 /etc/shadow 第五字段有关。默认是7天。UID_MIN
和UID_MAX
– 定义添加普通用户时的 uid 范围SYS_UID_MIN
与SYS_UID_MAX
– 定义添加系统用户(伪用户)的 uid 范围GID_MIN
和GID_MAX
– 定义添加用户之后相应用户组的 gid 范围SYS_GID_MIN
和SYS_GID_MAX
– 定义系统组(伪组)的 gid 范围CREATE_HOME
– 是否为新添加的用户创建相应的家目录(主目录)USERGROUPS_ENAB
– 使用 userdel 命令删除用户时是否删除该用户的相应初始组(主组)ENCRYPT_METHOD
– 定义密码的加密方式。早期是 MD5,现在是 SHA512SHA_CRYPT_MAX_ROUNDS
– 针对 SHA256 和 SHA512 的设置,定义 SHA 的最大轮数。
按照实际的安全合规要求配置即可。
-
设置会话的超时时间
当登录服务器时(不论是用远程 SSH 登录还是在机房本地的终端登录),可能会出现忘记注销登录账户的情况,这会带来一定的安全隐患,所以需要配置会话的超时时间。比如说设置 60 秒,当终端(不论是远程还是本地)60 秒内无任何活动操作,终端就会自动断开。
Shell > vim /etc/profile ... export TMOUT=60 Shell > source /etc/profile
-
为
history
命令加上时间戳默认情况下,
history
命令的输出如下:787 rpm -e $(rpm -qa | grep ^kernel | grep -v 553\.40) 788 grub2-mkconfig -o /boot/grub2/grub.cfg 789 shutdown -h now 790 cat /etc/login.defs 791 grep -v ^# /etc/login.defs |grep -v ^$ 792 source /etc/profile 793 dnf list updates 794 shutdown -h now 795 history
我们可以为 histroy 命令添加上时间戳,在查询历史命令时会更加方便,也方便排错。
Shell > vim /etc/profile … export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S `whoami` " Shell > source /etc/profile Shell > history ... 793 2025-02-22 12:41:22 root dnf list updates 794 2025-02-22 12:41:22 root shutdown -h now 795 2025-02-22 12:41:35 root history 796 2025-02-22 12:44:09 root vim /etc/profile 797 2025-02-22 12:44:39 root source /etc/profile 798 2025-02-22 12:44:43 root history
-
禁止 Control + Alt + Delete 按键重启操作系统
默认情况下,通过 ctrl + alt + del 按键可将操作系统重启,这主要是因为 ctrl-alt-del.target 是 reboot.target 的软链接(符号链接),如下:
Shell > ls -l /usr/lib/systemd/system/ctrl-alt-del.target lrwxrwxrwx 1 root root 13 Dec 18 01:56 /usr/lib/systemd/system/ctrl-alt-del.target -> reboot.target
这会带来一定的安全隐患,我们要做的就是将这个 target 文件删除即可。
Shell > rm -rf /usr/lib/systemd/system/ctrl-alt-del.target
-
限制用户的可用资源
前面的文章中,我们介绍过 pam_limits.so 这个限制资源使用的 PAM 模块。请注意!uid=0 的用户也会受到限制。默认情况下,限制的内容会首先读取这个配置文件—— /etc/security/limits.conf,然后读取 /etc/security/limits.d/ 目录下的所有 .conf 文件
由于 system-auth 策略文件的 session 链使用了 pam_limits.so 这个模块,因此我们只需要修改相应的配置文件即可。
Shell > cat /etc/security/limits.conf ... # <domain> <type> <item> <value> #* soft core 0 #* hard rss 10000 #@student hard nproc 20 #@faculty soft nproc 20 #@faculty hard nproc 50 #ftp hard nproc 0 #@student - maxlogins 4 # End of file
该文件分为 4 列,分别是 domain、type、item、value。
domain 可以是:
- 用户名
- 以 "@" 开头组名
- "*",表示通配符
type 可以是:
- soft,软资源限制
- hard,硬资源限制
- -,表示同时执行软资源和硬资源限制
item 可以是以下的其中一个:
- core,限制核心文件大小(KB),同
ulimit -c
临时生效命令 - data,一个进程的数据区最大数据大小(KB),同
ulimit -d
临时生效命令 - fsize,当前 shell 以及子 shell 可以写入的最大文件大小(KB),同
ulimit -f
临时生效命令 - memlock,一个进程最大可锁定的内存地址空间大小(KB),同
ulimit -l
临时生效命令 - nofile,打开的文件描述符的最大数量,同
ulimit -n
临时生效命令 - rss,最大持久设置大小(KB)
- stack,堆栈的最大值(KB),同
ulimit -s
临时生效命令 - cpu,每个进程可使用cpu的最大时间(分钟),同
ulimit -t
临时生效命令 - nproc,每个用户可运行的最大进程并发数,同
ulimit -u
临时生效命令 - as,地址空间限制(KB)
- maxlogins,该用户最大的登录终端数
- maxsyslogins,系统的最大登录用户数
- priority,用户进程运行的优先级
- locks,用户可锁定文件的最大值
- sigpending,最多的可以挂起的信号数
- msgqueue,POSIX消息队列使用的最大内存(bytes),同
ulimit -q
临时生效命令 - nice,允许提升最大NICE优先级,值可以是[-20,19]
- rtprio,最大实时优先级
示例内容:
* soft nofile 65535 * hard nofile 65535 * soft nproc 65535 * hard nproc 65535
文件描述符的概念我们在 Redis基础篇07 — 配置文件详解(二) 中详细介绍过。
-
查找具有 SUID、SGID、SBIT(粘着位)权限的文件
众所周知,SUID、SGID、粘着位是为了弥补普通权限(r、w、x)的不足。
SUID:
- 只有可执行二进制文件才能设置 SUID 权限。
- 命令的执行者应该对程序具有 x 权限。
- 命令的执行者在执行程序时获得程序文件所有者的身份。
- 身份变更仅在执行过程中有效,一旦二进制程序执行完成,执行者的身份将恢复为原始身份。
SGID:
- 只有可执行二进制文件才能设置 SGID 权限。
- SGID 虽然还可以用于目录,但很少使用。
- 普通用户必须对目录具有 rwx 权限。
- 对于普通用户在该目录下创建的文件,其默认的所属组为该目录的所属组。
- 命令的执行者应该对程序具有 x 权限。
- 命令的执行者在执行程序时获取程序文件所属组的身份。
- 身份变更仅在执行过程中有效,一旦二进制程序执行完成,执行者的身份将恢复为原始身份。
Sticky BIT(SBIT,粘着位):
- 仅对目录有效。
- 普通用户对该目录具有 w 和 x 权限。
- 如果没有 Sticky BIT,具有 w 权限的普通用户可以删除该目录下的所有文件(包括其他用户创建的文件)。一旦目录被赋予 SBIT 权限,仅 root(uid=0) 用户可以删除所有文件,对于普通用户而言,即使拥有该目录的 w 权限,也只能删除自己创建的文件(其他用户创建的文件不能删除)。
信息请注意!root(uid=0) 用户不受 SUID、SGID 和 SBIT 权限的限制。
如您所见,SUID 和 SGID 是一个越权的变身命令,这会给我们的操作系统带来一定的安全隐患,因此我们需要找出具体的文件:
Shell > find / -perm -4000 -a -type f -exec ls -l {} \; Shell > find / -perm -2000 -a -type f -exec ls -l {} \;
重点关注 /usr/sbin/ 和 /usr/bin/ 这两个目录下具有这类权限的文件,若碰到不认识的文件,我们建议您将其删除。
-
保护重要的文件不被误删除
有时我们希望某些重要核心文件不被删除,可使用 chattr 权限,即使是 root 用户,也无法删除该文件。
比如,crontab 是常用的定时任务服务,当我们编辑完成后,我们不希望 /var/spool/cron/ 目录下的文件被删除。
比如我希望每周日的清晨 3 点重启机器:
Shell > crontal -e 0 3 * * 7 /sbin/shutdown -r now Shell > crontab -l 0 3 * * 7 /sbin/shutdown -r now
当您编辑完成后会出现
crontab: installing new crontab
的提示,同时 /var/spool/cron/ 目录下有与用户名同名的定时任务文件,该文件的文件内容即定时任务的规则。Shell > cat /var/spool/cron/root 0 3 * * 7 /sbin/shutdown -r now
这个文件非常重要,我们可以使用 chattr 权限保护其不被删除:
Shell > chattr +ai /var/spool/cron/root Shell > lsattr /var/spool/cron/root ----ia--------e----- /var/spool/cron/root # 即使是 root 用户也无法删除 Shell > rm -rf /var/spool/cron/root rm: cannot remove '/var/spool/cron/root': Operation not permitted # 解除 chattr 权限 Shell > chattr -ai /var/spool/cron/root Shell > lsattr /var/spool/cron/root --------------e----- /var/spool/cron/root
-
控制普通用户使用某些命令
有两种方式可以控制
- ACL 权限
visudo
比如采用 ACL 权限控制普通用户使用
rm
命令:Shell > whereis rm rm: /usr/bin/rm /usr/share/man/man1/rm.1.gz Shell > setfacl -m u:user1:r /usr/bin/rm # 将文件的 user1 的 ACL 权限移除 Shell > setfacl -x u:user1 /usr/bin/rm
也可采用
visudo
的方式,比如不让普通用户执行shutdown
命令:Shell > visudo ... user1 ALL=!/usr/sbin/shutdown ... Shell > grep -v ^# /etc/sudoers | grep -v ^$ Defaults !visiblepw Defaults always_set_home Defaults match_group_by_gid Defaults always_query_group_plugin Defaults env_reset Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE" Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES" Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE" Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin root ALL=(ALL) ALL user1 ALL=!/usr/sbin/shutdown %wheel ALL=(ALL) ALL Shell > visudo -c
user1 用户执行时则会出现:
Shell (user1)> shutdown -h now Failed to set wall message, ignoring: Interactive authentication required. Failed to power off system via logind: Interactive authentication required. Failed to open initctl fifo: Permission denied Failed to talk to init daemon. Shell (user1)> sudo shutdown -h now Sorry, user user1 is not allowed to execute '/sbin/shutdown -h now' as root on M1.
