Zumpyx's Blog

Linux System Hardening

linuxhardeningblue-team

  • Physical Security
  • Filesystem Encryption
  • Firewall Configuration
  • Remote Access
  • Software and Services
  • Updates and Upgrades
  • Logs

Physical Security

物理安全,如果入侵者能够物理访问您的电脑,则可以轻松移除磁盘驱动器并将其带走。这是一种简单的攻击,需要很少的技术技能。

因此,考虑到硬盘可以被取走,其中的数据则为重点保护对象。可以考虑添加 GRUB 密码,grub2-mkpasswd-pbkdf2 会提示您输入密码两次并为您生成哈希值。根据 Linux 发行版将生成的哈希添加到适当的配置文件中。此配置将防止未经授权的用户重置您的 root 密码。它将要求用户提供密码才能通过 GRUB 访问高级引导配置,包括使用 root 访问权限登录

root@AttackBox# grub2-mkpasswd-pbkdf2 Enter password: Reenter password: PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.534B77859C13DCF094E90B926E26C586F5DC9D00687853487C4BB1500D57EC29E2D6D07A586262E093DCBDFF4B3552742A25700BAB6B76A8206B3BFCB273EEB4.4BA1447590EA8451CD224AA1C5F8623FE85D23F6D34E2026E3F08C5AA79282DB65B330BAB4944E9374EC51BF11EFF418EDA5D66FF4D7AAA86F662F793B92DA61

需要注意的是 GRUB 添加密码不适用于使用云服务提供商部署的系统

Filesystem Partitioning and Encryption

文件系统分区和加密

许多 Linux 发行版都附带 LUKS(Linux 统一密钥设置)当使用 LUKS 加密分区时,磁盘布局将如下图所示: Pasted-image-20231120135217.png

下面是一个加密 USB 闪存的真实示例,该闪存最初在 /dev/sdb1 处有一个 NTFS 格式的分区。

root@AttackBox# user@TryHackMe$ sudo lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sdb           8:16   1  14.3G  0 disk 
└─sdb1        8:17   1  14.3G  0 part /run/media/strategos/Strategos
[...]

user@TryHackMe$ sudo blkid
[...]
/dev/sdb1: LABEL="Strategos" BLOCK_SIZE="512" UUID="59402B4A4E12CD06" TYPE="ntfs"

user@TryHackMe$ sudo cryptsetup -y -v luksFormat /dev/sdb1
WARNING: Device /dev/sdb1 already contains a 'ntfs' superblock signature.

WARNING!
========
This will overwrite data on /dev/sdb1 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sdb1: 
Verify passphrase: 
Existing 'ntfs' superblock signature on device /dev/sdb1 will be wiped.
Existing 'dos' partition signature on device /dev/sdb1 will be wiped.
Key slot 0 created.
Command successful.

user@TryHackMe$ sudo cryptsetup luksOpen /dev/sdb1 EDCdrive

user@TryHackMe$ sudo mkfs.ext4 /dev/mapper/EDCdrive -L "Strategos USB"
mke2fs 1.46.5 (30-Dec-2021)
[...]
Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

user@TryHackMe$ sudo mount /dev/mapper/EDCdrive /media/secure-USB

如果您想检查 LUKS 设置,可以发出命令 cryptsetup luksDump /dev/sdb1 。在下面的终端输出中,我们可以看到加密磁盘的UUID。我们还可以看到使用的密码是 aes-xts-plain64 。至于密钥,PBKDF2 使用 SHA256 和提供的盐进行 194180 次迭代。

root@AttackBox# sudo cryptsetup luksDump /dev/sdb1
LUKS header information
Version:        2
Epoch:          3
Metadata area:  16384 [bytes]
Keyslots area:  16744448 [bytes]
UUID:           41199bad-d753-4dce-9284-0a81d27acc95
Label:          (no label)
Subsystem:      (no subsystem)
Flags:          (no flags)

Data segments:
  0: crypt
    offset: 16777216 [bytes]
    length: (whole device)
    cipher: aes-xts-plain64
    sector: 512 [bytes]

Keyslots:
  0: luks2
    Key:        512 bits
    Priority:   normal
    Cipher:     aes-xts-plain64
    Cipher key: 512 bits
    PBKDF:      argon2id
    Time cost:  4
    Memory:     965922
    Threads:    4
    Salt:       bd 45 40 96 27 93 cd fa 50 60 f4 28 d4 d8 b2 bd 
                58 69 72 72 35 2f 26 9c a8 14 ef 91 04 b2 dc cd 
    AF stripes: 4000
    AF hash:    sha256
    Area offset:32768 [bytes]
    Area length:258048 [bytes]
    Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
    Hash:       sha256
    Iterations: 194180
    Salt:       6e e1 70 a4 3f d6 71 44 c8 e6 84 4d 99 51 7d c9 
                49 66 bf 37 61 b8 c3 d2 4e aa f7 25 27 e2 b3 8a 
    Digest:     c1 87 99 a1 d1 7a 05 8a ca cd 13 74 f0 33 ef 3a 
                98 c9 d7 a8 70 93 e2 ac 07 0f 2a 5c 89 f1 18 1d 
  • 安装 cryptsetup-luks.
apt install cryptsetup
yum install cryptsetup-luks
dnf install cryptsetup-luks
  • 使用 fdisk -llsblk, blkid 确认分区名称,有必要可以使用 fdisk 创建分区
  • 设置 LUKS 加密分区: cryptsetup -y -v luksFormat /dev/sdb1
  • 创建一个映射来访问分区: cryptsetup luksOpen /dev/sdb1 EDCdrive
  • 确认映射详细信息: ls -l /dev/mapper/EDCdrive and cryptsetup -v status EDCdrive
  • 用零覆盖现有数据: dd if=/dev/zero of=/dev/mapper/EDCdrive
  • 格式化分区: mkfs.ext4 /dev/mapper/EDCdrive -L "Strategos USB"
  • 挂载: mount /dev/mapper/EDCdrive /media/secure-USB

Firewall

目前的Linux防火墙都是状态防火墙;它们跟踪正在进行的连接,并根据 IP 和 TCP/UDP 标头中的特定字段以及数据包是否是正在进行的连接的一部分来限制数据包

iptables

iptables 提供用户空间命令行工具来使用 netfilter 挂钩配置数据包过滤规则集。为了过滤流量,iptables 有以下默认链:

  • Input: 适用于传入防火墙的数据包。
  • Output: 适用于从防火墙发出的数据包。
  • Forward 适用于通过系统路由的数据包。

假设我们希望能够远程访问系统上的 SSH 服务器。为了使 SSH 服务器能够与外界通信,我们需要两件事:

  1. 接受目标 TCP 端口 22 的传入数据包。
  2. 接受来源 TCP 端口 22 的传出数据包。

对应 iptables 命令

$ iptables -A INPUT -p tcp --dport 22 -j ACCEPT
$ iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT

假设您只想允许流向本地 SSH 服务器的流量并阻止其他所有内容。在这种情况下,您需要再添加两条规则来设置防火墙的默认行为:

$ iptables -A INPUT -j DROP     阻止 previous 规则中不允许的所有传入流量
$ iptables -A OUTPUT -j DROP    阻止 previous 规则中不允许的所有传出流量

规则需要按以下顺序应用

$ iptables -A INPUT -p tcp --dport 22 -j ACCEPT 
$ iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT 
$ iptables -A INPUT -j DROP 
$ iptables -A OUTPUT -j DROP

在实践中,在应用新规则之前应刷新(删除)以前的规则,可以使用 iptables -F 实现

nftables

nftables 在内核 3.13 及更高版本中受支持,相对于 iptables 添加了各种改进,特别是在可扩展性和性能方面。

与 iptables 不同,nftables 开始时没有表或链。在添加规则之前,我们需要添加必要的表和链。首先,我们将创建一个表 fwfilter

$ nft add table fwfilter

在我们新创建的表 fwfilter 中,我们将分别为传入和传出数据包添加一个输入链和一个输出链。

$ nft add chain fwfilter fwinput { type filter hook input priority 0 \; }
$ nft add chain fwfilter fwoutput { type filter hook output priority 0 \; }

上面两个命令向表 fwfilter 添加两条链

  • fwinput 是输入链,类型为 filter 应用于输入挂钩
  • fwoutput 是输出链,类型为 filter 适用于输出挂钩

添加规则以允许 SSH 流量,以下两条规则分别添加到表 fwfilter 的链 fwinput 和 fwoutput 中:

$ nft add fwfilter fwinput tcp dport 22 accept
$ nft add fwfilter fwoutput tcp sport 22 accept

检查表的状态

root@AttackBox# sudo nft list table fwfilter
table ip fwfilter {
    chain fwinput {
        type filter hook input priority filter;
        tcp dport 22 accept
    }

    chain fwoutput {
        type filter hook output priority filter;
        tcp sport 22 accept
    }
}

UFW

在 Linux 上配置防火墙是一个繁琐且容易出错的过程。但是可以通过 UI 界面来简化工作! UFW 主打一个简单

Protecting Against Password Sniffing/Guessing

防止密码嗅探、猜测

远程访问使用加密协议,开启 SSH 私钥验证,关闭密码验证 vim /etc/ssh/sshd_config

PubkeyAuthentication yes
PasswordAuthentication no

Securing User Accounts

  1. 使用 sudo
  2. 禁用 root
  3. 使用强密码策略
  4. 禁用未使用的帐户

禁用 root 和未使用的账户,可以将 /etc/passwd 文件中对应用户的 shell 改为 /sbin/nologin

root:x:0:0:root:/root:/sbin/nologin
michael:x:1000:1000:Michael:/home/michael:/sbin/nologin

RedHat/Fedora: /etc/security/pwquality.conf Debian/Ubuntu: /etc/pam.d/common-password

root@AttackBox# sudo cat /etc/security/pwquality.conf

difok=5
minlen=10
minclass=3
retry=2

Software and Services

软件和服务

  1. 禁用不必要的服务
  2. 阻止不需要的网络端口
  3. 避免遗留协议,telent 与 ftp/tftp 服务应当升级为 ssh/sftp 服务
  4. 删除标识字符串,连接远程服务器时,一般会回复版本号,应当避免这种泄露

tomcat 隐藏版本号

vim org/apache/catalina/util/ServerInfo.properties

server.info=Apache Tomcat

Nginx 隐藏版本号

vim /usr/local/nginx/conf/nginx.conf

http { 
	include       mime.types;
	default_type  application/octet-stream;
	server_tokens off;          // 添加此行内容

Apache 隐藏版本号

vim /etc/apache2/conf-enabled/security.conf

25 ServerTokens Prod
36 ServerSignature Off

修改 sshd 版本号

$ strings /usr/sbin/sshd | grep OpenSSH_
$ sed -i 's/OpenSSH_5.3/OpenSSH_9.9/g' /usr/sbin/sshd

Update and Upgrade Policies

更新和升级策略,及时更新系统与内核

$ uname -a

Audit and Log Configuration

审计和日志配置

/var/log/messages - Linux 系统的通用日志 /var/log/auth.log - 列出所有身份验证尝试的日志文件(基于 Debian 的系统) /var/log/secure - 列出所有身份验证尝试的日志文件(基于 Red Hat 和 Fedora 的系统) /var/log/utmp - 访问日志,包含当前登录系统的用户信息 /var/log/wtmp - 访问日志,包含所有登录和退出系统的用户的信息 /var/log/kern.log - 包含来自内核的消息的日志文件 /var/log/boot.log - 包含启动消息和启动信息的日志文件

新事件一般会附加到日志文件最后,可以使用 tail 查看

Redis 无密码

vim /etc/redis/redis.conf

requirepass [There is password]

默认的 SNMP Agent PUBLIC community 字符串

如果攻击者能够猜测 PUBLIC 社区字符串,他们就能够从远程设备读取 SNMP 数据(取决于安装的 MIB)。这些信息可能包括系统时间、IP 地址、接口、运行的进程等。

  • 修复方案 确定检测到的团体字符串是否为私有团体字符串。确定公共社区字符串是否暴露敏感信息。如果不使用 SNMP 服务,请禁用它或更改默认社区字符串。 vim /etc/snmp/snmpd.conf 将 71 行与 72 行左右的 Public 改为其他字符串
71 rocommunity  public default -V systemonly
72 rocommunity6  public default -V systemonly

Nginx Root 权限运行

可导致被用于提权

vim /etc/nginx/nginx.conf

user www-data;

SSH 弱密码算法

SSH 协议可以免受 LogJam 攻击,可以强制客户使用椭圆曲线 Diffie-Hellman vim /etc/ssh/sshd_config

KexAlgorithms [email protected]
  • 加固项 /etc/ssh/sshd_config
# Ciphers
删除 3des-cbc,aes128-cbc,aes256-cbc

# kexalgorithms
删除 hellman-group1-sha1
保留 diffie-hellman-group14-sha1

# macs
删除 hmac-md5-96

可以选择生成新的 Diffie-Hellman 组

ssh-keygen -G moduli-2048.candidates -b 2048
ssh-keygen -T moduli-2048 -f moduli-2048.candidates

FTP 匿名登录

关闭 FTP 匿名登录

vim /etc/vsftpd.conf

anonymous_enable=NO

Sudo

禁止赋予非管理员用户所有权限,需要特殊权限应当如下赋予

$ sudo addgroup netadmin
$ sudo visudo -f /etc/sudoers.d/networking
---------------------------------------------
%netadmin ALL=NOPASSWD: /usr/bin/ss

$ sudo usermod -aG netadmin netboy

公开的数据库端口

服务器端口应当监听 127.0.0.1 而不是 0.0.0.0

mysql

vim /etc/mysql/mysql.conf.d/mysqld.cnf

31 bind-address            = 127.0.0.1

Redis

vim /etc/redis/redis.conf

69 bind 127.0.0.1