GNU/Linux 安全 tips

Table of Contents

1. 说明

本文总结一些 GNU/Linux 安全相关的通用技能。

开源不意味着安全,不过一旦爆光出漏洞,会有全世界的贡献协助快速修复漏洞。

2. 基本安全原则

  • 最小化安装
  • 最小化服务
  • 使用加密传输,如 FTP -> SFTP、HTTP -> HTTPS、Telnet -> SSH、SNMP v1/v2 -> SNMP v3
  • 重要数据也加密存储
  • 不直接使用 root 帐号,原因:1) 防止 root 帐号被泄露;2) 需要 root 时再使用 sudo,便于审计用多种验证方式,如指纹、OTP
  • 防火墙
  • 日志监控

3. GNU/Linux 发行版选择

一个发行版要做到安全和稳定,并且软件包丰富,是需要投入大量的人力,这不是一般小组织可以搞定的。所以无论是作为服务器系统,或是个人桌面,都得优先选用成熟的发行版。

可以从很多角度判断一个系统是否成熟,例如:

  • 社区活跃度
  • 是否有商业公司的支持
  • 用户量
  • 发行版对待安全的态度
  • 更新频率,有些是半年发布一个版本,有些是滚动更新,有些甚至连发行周期都不知道

推荐的发型版:

  • 红帽系列:Fedora、RHEL/CentOS
  • Debian
  • SUSE/openSUSE
  • Arch Linux,推荐基于 Arch 的 Manjaro

成熟的发行版有集中的包管理,可以通过系统自带的包管理器对软件和系统升级。Windows软件通常是从三方网站下载安装。

4. 磁盘分区

4.1. 任何用户可写的目录,挂载到独立的分区上

  • /tmp 独立为一个分区,并且禁止执行程序。因为任何用户都可以在这里读写。比如 GNU/Linux 存在一个本地提权漏洞,黑客可以将 Exploit 代码放在 /tmp 下编译并执行。可以重新挂载 /tmp 并设置成不可执行文件:
mount -o remount,noexec /tmp

并在 /etc/fstab 中设置,让下次启动也生效:

/dev/sdb1 /tmp ext2 defaults,noexec 0 0
  • /var/tmp 和 /tmp 设置一样,因为 /var/tmp 也可以让任何用户读写。
  • 另外用户可随意读写的目录挂载到其他目录中,也可以防止用户写过大的文件影响到根分区。

5. 端口

  • 谨慎监听 0.0.0.0。
  • 无需外网访问、只需内网访问的端口,监听内网地址。
  • 外网和内网都不需要访问的端口,监听 127.0.0.1。
  • 开发环境监听端口需谨慎,因为开发中的程序不可靠、不安全,并且带有太多调试信息,只监听 127.0.0.1。

6. 系统配置

6.1. 软件设置

  • 生产服务器尽量避免安装 GCC、Clang 等 C 源码编译器。因为安装 Rootkit 或者用 Exploit 提权,都需要编译代码。
  • 主流发行版的软件源中包含官方源,因为出现重大漏洞后,可以及时获得官方修复补丁。
  • 同类产品,优先选用安全等级较高的,比如 OpenSSL 近年来爆出太多漏洞,可考虑用 LibreSSL 代替:
$ wget http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.2.0.tar.gz
$ tar xvf libressl-2.2.0.tar.gz
$ cd libressl-2.2.0/
$ ./configure
$ make && sudo make install
$ ldconfig

6.2. lshell——受限制的 shell

只允许某个用户、某个用户组运行指定命令、进入指定目录、限制 PATH 变量等。官网:https://github.com/ghantoos/lshell

示例,只允许 test1 用户运行 ls、pwd 命令,只能访问 /etc 和 /tmp 目录。

安装后,改变要受到限制用户的默认 shell:

$ chsh test1 -s `which lshell`

然后追加以下内容到 /etc/lshell.conf

[test1]
allowed    :['ls', 'pwd']
path    :['/etc', '/tmp']
aliases         : {'ls':'ls --color'}

7. 文件安全

7.1. 特权文件

以下命令助你找到系统中的特权文件:

sudo find / -perm -4000

该去掉 s 标志位的程序可去掉,尽量保留最少。

8. 帐号安全

  • 多帐号、权限分离,让不同的进程以不同的身份运行,每个服务拥有自己的帐号,每个系统用户也有自己的帐号。
  • 帐号强密码。误使用弱口令(如:123456)。
  • 定期巡查 /etc/shadow 哪些帐号被设置了密码,警惕陌生帐号。

8.1. 环境变量

如果想环境变量应用到系统每个账户上,可把环境变量写在 /etc/profile中。

如果不希望用户修改环境变量,可用 readonly 将变量设为只读。如:

export TMOUT=100
readonly TMOUT

8.1.1. HISTSIZE

HISTSIZE 指定保存命令历史数目。

生产服务器上应设置小一点的值,以免管理员操作服务器的历史记录泄露敏感信息。不过我的桌面系统里设置的值却很大,因为这会便于我更高效地工作。

8.1.2. TMOUT

TMOUT指定用户空闲多少秒后断开会话。个人桌面系统不建议设置此变量。

8.2. 配置 /etc/login.defs

  • PASS_MAX_DAYS:密码有效期
  • PASS_MIN_LEN:密码最小长度

8.3. sudo

su 提供普通用户切换到 root,或其他用户身份。如果多个用户使用 su,就必须为这些用户提供 root 密码。为了防止 root 密码泄露,以及一些控制能力,所以建议使用 sudo。

sudo 配置文件路径:/etc/sudo.conf。

  • 单独存放 sudo 日志,便于日志分析。配置中加上:
Defaults logfile=/var/log/sudo.log

例,查看密码错误日志:

fgrep 'incorrect password attempts' /var/log.sudo.log
  • 配置保护路径,防止环境变量被修改:
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

8.4. /bin/false 并不完美

如果要禁止某个帐号登录系统,通常会把帐号的 shell 改成 /bin/false,如:

sudo usermod -s /bin/false xiaoming

即便帐号被泄露,也无法登录系统,这种设置看上去很安全。如,192.168.77.132 这台机器上 test 帐号配置如下:

test:x:1002:1003::/home/test:/bin/false

不能登录 shell,但我们可以做端口转发,本地监听 4899 端口来做转发:

ssh -qTfnN -D 4899 [email protected]

比如 192.168.77.132 的 80 端口未对外开放,但通过这个隧道我们就能成功访问到:

$ proxychains4 curl localhost/test.php

9. OpenSSH

服务端默认配置文件:/etc/ssh/sshd_config

  • 帐号登录使用证书认证,禁用密码登录:PasswordAuthentication no。一定要先确保能够用证书登录后,再设置,不然下次就登不上服务器了
  • 禁止空密码:PermitEmptyPasswords no
  • 限制允许/禁止登录的帐号,参考 man sshd_config 中 DenyUsers、AllowUsers、DenyGroups 和 AllowGroups 四个值
  • 禁止 root 帐号登录:PermitRootLogin no
  • ssh 登录系统后,可执行 /etc/ssh/sshrc 里的命令,如下,一个启动ssh会话后自动发邮件的命令:
echo "${SSH_CLIENT}登录了${USER}" | mail -s "黑客来了" [email protected]

10. 其他

10.1. 关注安全通告

关注主流安全咨询网站,以便及时获得跟系统切身相关的安全信息。

也可订阅相关发行版安全相关的邮件列表,如:

等等。