互联网安全建设从0到1
上QQ阅读APP看书,第一时间看更新

3.3 Linux主机安全

Linux系统凭借着免费、开源等优势,已经逐渐成为互联网公司首选的操作系统,本章主要以CentOS 7为例,介绍与Linux系统相关的安全内容。

3.3.1 Linux补丁

Linux系统与Windows系统有所不同,Linux系统由内核及周边软件组成,对内核来说,并不存在打补丁一说,只有升级内核这个概念;而对于软件来说,打补丁更多是意味着升级,因此Linux并没有严格意义上的像WSUS那样的补丁管理工具。而且,由于Linux是开源的,有更多的程序员和安全人员可以研究Linux代码,因此Linux系统比Windows系统更加安全,对资源的控制比Windows更加合理,加上Linux本身免费,因此越来越多的服务器选择了Linux系统。不过与Windows相同,单纯一个Linux系统本身也不会存在较大的安全问题,真正有问题的还是上层应用服务,所以在初始化Linux时,也需要对系统进行一些调整,减少安全隐患。

3.3.2 Linux系统加固建议

Linux加固的内容很多,笔者从以下几个维度进行介绍:账号管理、SSH安全、密码设置、History安全、日志安全。

1.账号管理

对于Linux账号的管理,建议进行如下操作:

1)锁定或清除系统自带的一些不常用的用户,如games、news等。

2)限制root的远程访问,管理员通过普通账号远程登录,然后通过su命令切换到root账户:


sed -i 's/^[#]\{0,1\}PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config

2.SSH安全

SSH登录是管理Linux最常见的方式,因此对SSH加固非常重要,建议在终端操作以下命令,避免因为操作失误导致可能无法连入系统。

1)指定SSH协议为2:


sed -i 's/^[#]\{0,1\}Protocol.*/Protocol 2/' /etc/ssh/sshd_config,

重启SSH服务:


service sshd start


/bin/systemctl start sshd.service

以下与SSH相关的操作都需要重启服务,故省略重启SSH服务操作。

2)更改SSH默认端口(例如改为2222,需要注意selinux状态,可以使用setenforce 0命令临时关闭selinux,否则报错,不关闭则需要同时更改selinux的SSHD的端口)。


sed -i 's/^[#]\{0,1\}Port.*/Port 2222/g' /etc/ssh/sshd_config

3)尽量不将SSH端口开放到公网。

4)如果可以,尽量使用证书或双因素认证,以提高登录安全性。启用密钥认证(密钥要设置密码),前提是要有一个sudo权限的普通用户,且要注意以下两点:

.ssh目录的权限必须是700,如下所示:

.ssh/authorized_keys文件权限必须是600,如下所示:

再通过下面两条命令将密码登录更改为证书登录即可:


sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/'g /etc/ssh/sshd_config
sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config

3.密码设置

密码也是Linux安全中重要的组成部分,因此需要对密码的复杂度、有效期等进行设置:

(1)启用密码复杂度设置

修改/etc/pam.d/system-auth-ac文件,使用“#”注释掉,"password requisitepam_pwquality.so retry=3 authtok_type=",新增:


password requisitepam_cracklib.so try_first_pass retry=5 minlen=8 ucredit=-1

如下所示:

即为password加载pam_cracklib.so模块,后接模块参数,常用参数为:

·retry=N:改变重新输入密码的次数。

·difok=N:设置允许的新、旧密码相同字符的个数。

·minlen=N:密码最小长度。

·ucredit=N:密码中至少有多少个大写字符,-N代表至少N个,以下类似。

·lcredit=N:密码中至少有多少个小写字符。

·dcredit=N:密码中至少有多少个数字。

·ocredit=N:密码中至少有多少个其他的字符。

·try_first_pass:后面的模块尝试使用为之前模块输入的密码。

·local_users_only:只在本地/etc/passwd文件中的用户。

其余参数,请使用man pam_cracklib命令查看说明。

(2)启用密码有效期

修改/etc/login.defs中如下内容:


PASS_MAX_DAYS   99999
PASS_MIN_DAYS   0
PASS_MIN_LEN    8
PASS_WARN_AGE   7

分别将密码最长过期时间、密码最短过期时间、密码最小长度、密码过期提前警告天数修改为合适数值即可。

4.History安全

History里记录着用户的所有操作信息,对History进行加固有助于在出现问题时方便地进行溯源,因此也需要进行设置,具体步骤如下。

1)增加HISTTIMEFORMAT命令记录历史到环境变量:


echo "export HISTTIMEFORMAT=\"%F %T \"" >> /etc/profile

2)记录所有用户的操作:


export PROMPT_COMMAND='{ date +"[$(who am i | tr -s [[:blank:]] | cut
-d" " -f1,2,5)-> ${USER}] $( history 1 | { read num cmd; }; })" ; } >>
/var/log/audit/UserAudit.log'

注意:UserAudit.log中其他用户权限位要设置读写权限。

使用readonly PROMPT_COMMAND命令使PROMPT_COMMAND只读。

3)增加HISTSIZE命令记录行数。编辑/etc/profile并在文件最后增加或修改:


export HISTSIZE=5000

然后执行:


source /etc/profile

5.日志安全

日志保存着重要的记录,因此对于日志,在尽可能在本地保存的同时,增加远程保存机制,并进行校验,以保证日志的可用性、完整性。更多关于日志的介绍,请参考第6章。

由于关于Linux加固在网上已经有太多资料,所以笔者仅挑选以上几个自认为重要的地方介绍,其他内容不再赘述。

3.3.3 bash安全设置

当黑客入侵时,一般会清空命令历史记录,以便被发现后无法溯源。这里介绍一下如何重新编译bash并记录操作命令到本地,同时同步到rsyslog。从bash-4.1开始,bash原生支持操作日志通过syslog外发,该配置项在config-top.h文件中定义,但默认是关闭的,需要取消#define SYSLOG_HISTORY的注释,开启syslog转发。

下载bash最新稳定版并解压:


[root@localhost ~]# wget -c https://ftp.gnu.org/gnu/bash/bash-4.4.18.tar.gz
[root@localhost ~]# tar zxf bash-4.4.18.tar.gz
[root@localhost ~]# cd bash-4.4.18/

修改源代码。共计需要修改两处源码,第一处为bashhist.c,需要修改771行和776行,修改内容如下所示:


771 syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d PPID=%d SID=%d
UID=%d User=%s CMD=%s", getpid(), getppid(), getsid(getpid()), current_
user.uid, current_user.user_name, line);

776 syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d
PPID=%d SID=%d UID=%d User=%s CMD=%s", getpid(), getppid(), getsid(getpid
()), current_user.uid, current_user.user_name, trunc);

部分uoming信息说明如下:

·PID:进程号

·PPID:父进程号

·SID:session ID

·User:用户名

·CMD:执行的命令

其中PID表示当前执行Linux命令的bash进程ID,使用函数getpid()获取;PPID表示当前执行Linux命令的bash父进程ID,使用函数getppid()获取;SID表示当前会话ID,使用函数getsid(getpid())获取;UID表示执行命令用户的ID,用current_user.uid表示;User表示执行命令的用户名,用current_user.user_name表示;CMD表示执行的历史命令内容。

说一下父进程,一个正常登录的bash,父进程应该是操作系统,或者bash本身,或者SSHD。当一个bash进程的父进程是Java,或者是PHP、Python时很可能就有问题了。

第二处:是修改config-top.h。将116行的注释删除,如下所示:


#define SYSLOG_HISTORY

将118行的#define SYSLOG_FACILITY LOG_USER改为#define SYSLOG_FACILITY LOG_LOCAL6,编译并安装,如下所示:


[root@localhost bash-4.4.18]# ./configure --prefix=/usr/local/bash-4.4.18
--enable-net-redirections --enable-readline
[root@localhost bash-4.4.18]# make -j8
[root@localhost bash-4.4.18]# make install
[root@localhost bash-4.4.18]# cd /usr/local/
[root@localhost local]# ln -s bash-4.4.18 bash

有两个注意事项:

1)-enable-readline,前提是系统中要安装readline readline-devel。

2)-net-redirections,表示允许使用/dev/tcp/ip/port这样的方式连接。

然后修改rsyslog:


[root@localhost ~]# yum install rsyslog  (如有rsyslog服务可以省略)
[root@localhost ~]# vim /etc/rsyslog.conf

增加如下内容:


local6.* /var/log/bash.log
local6.* @@remote-rsyslog-server:514

重启rsyslog,这样命令记录就不会丢失。

最后替换用户登录shell:


[root@localhost ~]# chsh -s /usr/local/bash/bin/bash $username

关于syslog的介绍,也请参考第6章。

3.3.4 Linux经典漏洞介绍

Linux系统也有很多经典漏洞,下面简单介绍一下:

·Heartbleed(心脏滴血):OpenSSL Heartbleed模块存在一个BUG,问题存在于ssl/dl_both.c文件中的心跳部分,当攻击者构造一个特殊的数据包,采用的数据超过用户心跳包中的数据限制,会导致memcpy函数把SSLv3记录之后的数据直接输出。该漏洞导致攻击者可以远程读取存在漏洞版本的OpenSSL服务器内存中多达64KB的数据。此漏洞影响力较大,互联网中绝大多数网站均受到这个漏洞的影响。

·Shellshock(破壳漏洞):又称Bashdoor,是在UNIX中广泛使用的Bash shell中的一个安全漏洞,首次于2014年9月24日公开。许多互联网守护进程,如网页服务器,使用bash来处理某些命令,从而允许攻击者在易受攻击的bash版本上执行任意代码。这可使攻击者在未授权的情况下访问计算机系统。该漏洞会影响目前主流的Linux和Mac OSX操作系统平台,包括但不限于Redhat、CentOS、Ubuntu、Debian、Fedora、Amazon Linux、OS X 10.10等平台。

·DirtyCow(脏牛漏洞):Linux内核的内存子系统在处理写时拷贝(Copy-on-Write,COW)时存在竞争漏洞,导致只读内存页可被篡改或写入。一个低权限的本地用户能够利用此漏洞获取只读内存映射的写入权限。通过写入系统重要的敏感文件,可获取整个系统的最高权限。