Files
audit-web/audit_check_script/audit_cis_centos_v202.sh
T
2026-08-26 14:11:37 +07:00

1728 lines
66 KiB
Bash

#!/bin/bash
############################################################################
SCRIPT_VERSION="2.0.2"
# Colors for output (optional)
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
############################################################################
# HELPER FUNCTIONS
############################################################################
# Function to output result in JSON format
output_result() {
local check_id="$1"
local check_name="$2"
local status="$3"
echo "{\"${check_id}. ${check_name}\" : \"${status}\"}"
}
# Function to check if module is disabled
check_module_disabled() {
local module="$1"
local module_underscore="${module//-/_}"
# Check if module is loaded
if lsmod | grep -qw "$module_underscore"; then
return 1
fi
# Check if module is set to install /bin/true or /bin/false
if modprobe -n -v "$module" 2>/dev/null | grep -qE "^[[:space:]]*install[[:space:]]+(/bin/(true|false)|${module}[[:space:]]+/bin/(true|false))"; then
return 0
fi
# Check if module is blacklisted
if grep -s -h -qE "^[[:space:]]*blacklist[[:space:]]+${module}([[:space:]]|$)" /etc/modprobe.d/*.conf 2>/dev/null; then
return 0
fi
# Check kernel cmdline
if grep -qw "modprobe.blacklist=${module}" /proc/cmdline 2>/dev/null; then
return 0
fi
return 1
}
# Function to check mount option
check_mount_option() {
local mount_point="$1"
local option="$2"
if ! findmnt --kernel "$mount_point" >/dev/null 2>&1; then
return 0 # Not mounted, considered PASSED
fi
if findmnt --kernel "$mount_point" | grep -q "$option" && \
grep -E "\s+${mount_point}\s+.*${option}" /etc/fstab >/dev/null 2>&1; then
return 0
fi
return 1
}
# Function to check service status
check_service_disabled() {
local service="$1"
if systemctl is-enabled "$service" 2>/dev/null | grep -q "^enabled"; then
return 1
fi
if systemctl is-active "$service" 2>/dev/null | grep -q "^active"; then
return 1
fi
return 0
}
# Function to check package installed
check_package_installed() {
local package="$1"
rpm -qa "$package" 2>/dev/null | grep -q .
}
# Function to check package not installed
check_package_not_installed() {
local package="$1"
! rpm -qa "$package" 2>/dev/null | grep -q .
}
# Function to check file permissions
check_file_perms() {
local file="$1"
local expected_mode="$2"
local expected_uid="$3"
local expected_gid="$4"
if [ ! -e "$file" ]; then
return 0
fi
local actual=$(stat -c "%a:%u:%g" "$file" 2>/dev/null)
if echo "$actual" | grep -qP "^${expected_mode}:${expected_uid}:${expected_gid}$"; then
return 0
fi
return 1
}
# Function to check sysctl parameter
check_sysctl() {
local param="$1"
local expected="$2"
local current=$(sysctl -n "$param" 2>/dev/null)
if [ "$current" = "$expected" ]; then
# Also check persistent config
if grep -qE "^[[:space:]]*${param}[[:space:]]*=[[:space:]]*${expected}" /etc/sysctl.conf /etc/sysctl.d/*.conf 2>/dev/null; then
return 0
fi
fi
return 1
}
# Function to log failed check details
log_failed() {
local recommendation="$1"
echo "######################################"
echo "# Khuyến nghị:"
echo "$recommendation"
echo "######################################"
}
############################################################################
# SYSTEM INFORMATION
############################################################################
echo "============================================================================"
echo " THÔNG TIN HỆ THỐNG"
echo "============================================================================"
echo ""
echo "Script Version: $SCRIPT_VERSION"
echo ""
echo "--- Thông tin cơ bản ---"
echo "Operating System: $(cat /etc/system-release 2>/dev/null || cat /etc/redhat-release 2>/dev/null || cat /etc/os-release 2>/dev/null | grep PRETTY_NAME | cut -d= -f2 | tr -d '\"')"
echo "Kernel Version: $(uname -r)"
echo "Architecture: $(uname -m)"
echo "Hostname: $(hostname)"
echo "FQDN: $(hostname -f 2>/dev/null || echo 'N/A')"
echo "IP Address: $(hostname -I 2>/dev/null | awk '{print $1}')"
echo "All IP Addresses: $(hostname -I 2>/dev/null | tr ' ' ', ' | sed 's/,$//')"
echo "Audit Time: $(date +"%Y-%m-%d %H:%M:%S")"
echo "Timezone: $(timedatectl 2>/dev/null | grep 'Time zone' | awk '{print $3}' || date +%Z)"
echo "Uptime: $(uptime -p 2>/dev/null || uptime | awk -F'up ' '{print $2}' | awk -F',' '{print $1, $2}')"
echo ""
echo "--- Thông tin CPU ---"
echo "CPU Model: $(grep 'model name' /proc/cpuinfo 2>/dev/null | head -1 | cut -d: -f2 | sed 's/^[ \t]*//')"
echo "CPU Cores: $(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo)"
echo "CPU Architecture: $(lscpu 2>/dev/null | grep 'Architecture' | awk '{print $2}' || uname -p)"
echo ""
echo "--- Thông tin Memory ---"
echo "Total Memory: $(free -h 2>/dev/null | awk '/^Mem:/{print $2}' || grep MemTotal /proc/meminfo | awk '{print $2/1024/1024 " GB"}')"
echo "Used Memory: $(free -h 2>/dev/null | awk '/^Mem:/{print $3}')"
echo "Free Memory: $(free -h 2>/dev/null | awk '/^Mem:/{print $4}')"
echo "Swap Total: $(free -h 2>/dev/null | awk '/^Swap:/{print $2}')"
echo ""
echo "--- Thông tin Disk ---"
echo "Disk Usage:"
df -h / /home /var /tmp 2>/dev/null | grep -v "^Filesystem" | awk '{printf " %-20s %s used of %s (%s)\n", $6, $3, $2, $5}'
echo ""
echo "--- Thông tin Network Interfaces ---"
echo "Primary Interface: $(ip route 2>/dev/null | grep default | awk '{print $5}' | head -1)"
echo "MAC Address: $(ip link 2>/dev/null | grep -A1 "$(ip route | grep default | awk '{print $5}' | head -1)" | grep ether | awk '{print $2}')"
echo "Default Gateway: $(ip route 2>/dev/null | grep default | awk '{print $3}' | head -1)"
echo "DNS Servers: $(grep nameserver /etc/resolv.conf 2>/dev/null | awk '{print $2}' | tr '\n' ', ' | sed 's/,$//')"
echo ""
echo "--- Thông tin bổ sung ---"
echo "SELinux Status: $(getenforce 2>/dev/null || echo 'Not installed')"
echo "Firewall: $(systemctl is-active firewalld 2>/dev/null || echo 'inactive') (firewalld) / $(systemctl is-active iptables 2>/dev/null || echo 'inactive') (iptables)"
echo "Last Boot: $(who -b 2>/dev/null | awk '{print $3, $4}')"
echo "Current Users: $(who 2>/dev/null | wc -l)"
echo "Load Average: $(cat /proc/loadavg 2>/dev/null | awk '{print $1, $2, $3}')"
echo ""
echo "============================================================================"
# Detect CentOS version
CENTOS_VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/system-release 2>/dev/null | head -1 | cut -d. -f1)
echo "CentOS Version Detected: $CENTOS_VERSION"
# Check IPv6 status
IPV6_ENABLED=0
if [ -f /proc/net/if_inet6 ] && [ -s /proc/net/if_inet6 ]; then
if ip -6 addr show 2>/dev/null | grep -q "inet6" && \
ip -6 addr show 2>/dev/null | grep "inet6" | grep -vq "::1/128"; then
IPV6_ENABLED=1
echo "IPv6 Status: ENABLED"
else
echo "IPv6 Status: DISABLED (no IPv6 addresses assigned)"
fi
else
echo "IPv6 Status: DISABLED (kernel support not available)"
fi
echo "############################################################################"
############################################################################
# 1. INITIAL SETUP
############################################################################
echo ""
echo "=== 1. Thiết lập ban đầu ==="
echo ""
############################################################################
# 1.1 Filesystem Configuration
############################################################################
echo "--- 1.1. Cấu hình filesystem ---"
# 1.1.1 Disable unused filesystems
FILESYSTEMS=("cramfs" "freevxfs" "hfs" "hfsplus" "jffs2" "squashfs" "udf" "usb-storage")
FS_NAMES=("cramfs filesystem" "freevxfs filesystem" "hfs filesystem" "hfsplus filesystem" "jffs2 filesystem" "squashfs filesystem" "udf filesystem" "usb-storage filesystem")
for i in "${!FILESYSTEMS[@]}"; do
fs="${FILESYSTEMS[$i]}"
fs_name="${FS_NAMES[$i]}"
check_num="1.1.1.$((i+1))"
check_name="Cấu hình vô hiệu hoá ${fs_name}"
if check_module_disabled "$fs"; then
output_result "$check_num" "$check_name" "PASSED"
else
output_result "$check_num" "$check_name" "FAILED"
log_failed "# Thêm vào /etc/modprobe.d/filesystem.conf:
# install ${fs} /bin/true
# blacklist ${fs}
# Gỡ module nếu đang nạp: rmmod ${fs}"
fi
done
# 1.1.2 /tmp partition options
echo ""
echo "--- 1.1.2. Cấu hình phân vùng /tmp ---"
TMP_OPTIONS=("nodev" "nosuid" "noexec")
for i in "${!TMP_OPTIONS[@]}"; do
opt="${TMP_OPTIONS[$i]}"
check_num="1.1.2.$((i+1))"
check_name="Cấu hình tuỳ chọn ${opt} cho phân vùng /tmp"
if check_mount_option "/tmp" "$opt"; then
output_result "$check_num" "$check_name" "PASSED"
else
output_result "$check_num" "$check_name" "FAILED"
fi
done
# 1.1.3 /var/tmp partition options
echo ""
echo "--- 1.1.3. Cấu hình phân vùng /var/tmp ---"
for i in "${!TMP_OPTIONS[@]}"; do
opt="${TMP_OPTIONS[$i]}"
check_num="1.1.3.$((i+1))"
check_name="Cấu hình tuỳ chọn ${opt} cho phân vùng /var/tmp"
if check_mount_option "/var/tmp" "$opt"; then
output_result "$check_num" "$check_name" "PASSED"
else
output_result "$check_num" "$check_name" "FAILED"
fi
done
# 1.1.4 /home partition options
echo ""
echo "--- 1.1.4. Cấu hình phân vùng /home ---"
HOME_OPTIONS=("nodev" "nosuid")
for i in "${!HOME_OPTIONS[@]}"; do
opt="${HOME_OPTIONS[$i]}"
check_num="1.1.4.$((i+1))"
check_name="Cấu hình tuỳ chọn ${opt} cho phân vùng /home"
if check_mount_option "/home" "$opt"; then
output_result "$check_num" "$check_name" "PASSED"
else
output_result "$check_num" "$check_name" "FAILED"
fi
done
# 1.1.5 /dev/shm partition options
echo ""
echo "--- 1.1.5. Cấu hình phân vùng /dev/shm ---"
for i in "${!TMP_OPTIONS[@]}"; do
opt="${TMP_OPTIONS[$i]}"
check_num="1.1.5.$((i+1))"
check_name="Cấu hình tuỳ chọn ${opt} cho phân vùng /dev/shm"
if check_mount_option "/dev/shm" "$opt"; then
output_result "$check_num" "$check_name" "PASSED"
else
output_result "$check_num" "$check_name" "FAILED"
fi
done
############################################################################
# 1.2 Software Updates
############################################################################
echo ""
echo "--- 1.2. Cấu hình cập nhật phần mềm ---"
# 1.2.1 GPG Check
gpg_failed=0
if grep -qP "^gpgcheck\h*=\h*[^1]" /etc/yum.repos.d/*.repo 2>/dev/null; then
gpg_failed=1
fi
if grep -qP "^gpgcheck\h*=\h*[^1]" /etc/yum.conf 2>/dev/null; then
gpg_failed=1
fi
if [ $gpg_failed -eq 0 ]; then
output_result "1.2.1" "Cấu hình kích hoạt gpgcheck" "PASSED"
else
output_result "1.2.1" "Cấu hình kích hoạt gpgcheck" "FAILED"
fi
############################################################################
# 1.3 Filesystem Integrity
############################################################################
echo ""
echo "--- 1.3. Kiểm tra tính toàn vẹn của filesystem ---"
# 1.3.1 AIDE installed
if check_package_installed "aide"; then
output_result "1.3.1" "Kiểm tra cài đặt AIDE" "PASSED"
else
output_result "1.3.1" "Kiểm tra cài đặt AIDE" "FAILED"
fi
# 1.3.2 AIDE cron job
if check_package_installed "aide" && { \
(crontab -l 2>/dev/null | grep -Eq '^\s*[^#].*\baide\b.*--check') || \
grep -rsEq '^\s*[^#].*\baide\b.*--check' /etc/cron* /var/spool/cron 2>/dev/null || \
systemctl is-enabled aidecheck.timer 2>/dev/null | grep -q "^enabled" || \
systemctl is-enabled aide-check.timer 2>/dev/null | grep -q "^enabled"; }; then
output_result "1.3.2" "Cấu hình kiểm tra tính toàn vẹn của filesystem" "PASSED"
else
output_result "1.3.2" "Cấu hình kiểm tra tính toàn vẹn của filesystem" "FAILED"
fi
############################################################################
# 1.4 Secure Boot Settings
############################################################################
echo ""
echo "--- 1.4. Cấu hình khởi động an toàn ---"
# 1.4.1 Bootloader permissions
grubdir=$(dirname "$(find /boot -type f \( -name 'grubenv' -o -name 'grub.conf' -o -name 'grub.cfg' \) -exec grep -Pl '^\h*(kernelopts=|linux|kernel)' {} \; 2>/dev/null | head -1)" 2>/dev/null)
grub_perms_ok=1
for f in "$grubdir/grub.cfg" "$grubdir/grubenv" "$grubdir/user.cfg"; do
if [ -f "$f" ]; then
perms=$(stat -c "%a:%u:%g" "$f" 2>/dev/null)
if ! echo "$perms" | grep -qP '^[0-7]00:0:0$'; then
grub_perms_ok=0
fi
fi
done
if [ $grub_perms_ok -eq 1 ]; then
output_result "1.4.1" "Phân quyền đối với file cấu hình bootloader" "PASSED"
else
output_result "1.4.1" "Phân quyền đối với file cấu hình bootloader" "FAILED"
fi
# 1.4.2 Rescue mode authentication
rescue_ok=0
if [ "$CENTOS_VERSION" -ge 8 ] 2>/dev/null; then
if grep -Er "^ExecStart.*/systemd-sulogin-shell" /usr/lib/systemd/system/rescue.service /etc/systemd/system/rescue.service.d 2>/dev/null | grep -q .; then
rescue_ok=1
fi
else
if grep -q "/sbin/sulogin" /usr/lib/systemd/system/rescue.service 2>/dev/null && \
grep -q "/sbin/sulogin" /usr/lib/systemd/system/emergency.service 2>/dev/null; then
rescue_ok=1
fi
fi
if [ $rescue_ok -eq 1 ]; then
output_result "1.4.2" "Cấu hình xác thực khi truy cập rescue mode" "PASSED"
else
output_result "1.4.2" "Cấu hình xác thực khi truy cập rescue mode" "FAILED"
fi
# 1.4.3 Single user mode (CentOS 6 only)
if [ "$CENTOS_VERSION" -eq 6 ] 2>/dev/null; then
if grep "^SINGLE" /etc/sysconfig/init 2>/dev/null | grep -q "/sbin/sulogin"; then
output_result "1.4.3" "Cấu hình xác thực khi truy cập single user mode" "PASSED"
else
output_result "1.4.3" "Cấu hình xác thực khi truy cập single user mode" "FAILED"
fi
else
output_result "1.4.3" "Cấu hình xác thực khi truy cập single user mode" "PASSED"
fi
# 1.4.4 Interactive boot (CentOS 6 only)
if [ "$CENTOS_VERSION" -eq 6 ] 2>/dev/null; then
if grep "^PROMPT" /etc/sysconfig/init 2>/dev/null | grep -q "no"; then
output_result "1.4.4" "Cấu hình vô hiệu hoá interactive boot" "PASSED"
else
output_result "1.4.4" "Cấu hình vô hiệu hoá interactive boot" "FAILED"
fi
else
output_result "1.4.4" "Cấu hình vô hiệu hoá interactive boot" "PASSED"
fi
############################################################################
# 1.5 Additional Process Hardening
############################################################################
echo ""
echo "--- 1.5. Additional Process Hardening ---"
# 1.5.1 Core dumps
core_dump_ok=1
if ! grep -qP "^\h*\*\s+hard\s+core\s+0" /etc/security/limits.conf /etc/security/limits.d/*.conf 2>/dev/null; then
core_dump_ok=0
fi
if ! sysctl fs.suid_dumpable 2>/dev/null | grep -q "= 0"; then
core_dump_ok=0
fi
if [ $core_dump_ok -eq 1 ]; then
output_result "1.5.1" "Cấu hình vô hiệu hoá core dump" "PASSED"
else
output_result "1.5.1" "Cấu hình vô hiệu hoá core dump" "FAILED"
fi
# 1.5.2 ASLR
if check_sysctl "kernel.randomize_va_space" "2"; then
output_result "1.5.2" "Cấu hình kích hoạt ASLR (address space layout randomization)" "PASSED"
else
output_result "1.5.2" "Cấu hình kích hoạt ASLR (address space layout randomization)" "FAILED"
fi
# 1.5.3 Prelink
if check_package_not_installed "prelink"; then
output_result "1.5.3" "Cấu hình vô hiệu hoá prelink" "PASSED"
else
output_result "1.5.3" "Cấu hình vô hiệu hoá prelink" "FAILED"
fi
############################################################################
# 1.6 Warning Banners
############################################################################
echo ""
echo "--- 1.6. Kiểm soát nội dung cảnh báo ---"
# Function to check banner content
check_banner_content() {
local file="$1"
local os_name=$(grep '^ID=' /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"')
if [ ! -f "$file" ]; then
return 0
fi
if grep -Ei "(\\\\v|\\\\r|\\\\m|\\\\s|${os_name})" "$file" 2>/dev/null | grep -q .; then
return 1
fi
return 0
}
# 1.6.1 MOTD content
if check_banner_content "/etc/motd"; then
output_result "1.6.1" "Kiểm soát nội dung motd (Message Of The Day)" "PASSED"
else
output_result "1.6.1" "Kiểm soát nội dung motd (Message Of The Day)" "FAILED"
fi
# 1.6.2 /etc/issue content
if check_banner_content "/etc/issue"; then
output_result "1.6.2" "Kiểm soát nội dung thông báo khi đăng nhập" "PASSED"
else
output_result "1.6.2" "Kiểm soát nội dung thông báo khi đăng nhập" "FAILED"
fi
# 1.6.3 /etc/issue.net content
if check_banner_content "/etc/issue.net"; then
output_result "1.6.3" "Kiểm soát nội dung thông báo khi đăng nhập từ xa" "PASSED"
else
output_result "1.6.3" "Kiểm soát nội dung thông báo khi đăng nhập từ xa" "FAILED"
fi
# 1.6.4-1.6.6 File permissions
BANNER_FILES=("/etc/motd" "/etc/issue" "/etc/issue.net")
BANNER_CHECKS=("1.6.4" "1.6.5" "1.6.6")
BANNER_NAMES=("Cấu hình phân quyền đối với file /etc/motd" "Cấu hình phân quyền đối với file /etc/issue" "Cấu hình phân quyền đối với file /etc/issue.net")
for i in "${!BANNER_FILES[@]}"; do
file="${BANNER_FILES[$i]}"
check_num="${BANNER_CHECKS[$i]}"
check_name="${BANNER_NAMES[$i]}"
if [ ! -f "$file" ] || stat -c "%a:%u:%g" "$file" 2>/dev/null | grep -qP "^[0-6][0-4][0-4]:0:0$"; then
output_result "$check_num" "$check_name" "PASSED"
else
output_result "$check_num" "$check_name" "FAILED"
fi
done
# 1.6.7 GNOME banner
gnome_ok=1
if ! systemctl get-default 2>/dev/null | grep -q "multi-user.target"; then
# GUI is default, check GNOME settings
if [ ! -f /etc/dconf/profile/gdm ] || \
! grep -qP "^\h*user-db:user" /etc/dconf/profile/gdm 2>/dev/null || \
! grep -qP "^\h*system-db:gdm" /etc/dconf/profile/gdm 2>/dev/null || \
! grep -qP "^\h*banner-message-enable=true" /etc/dconf/db/gdm.d/* 2>/dev/null; then
gnome_ok=0
fi
fi
if [ $gnome_ok -eq 1 ]; then
output_result "1.6.7" "Kiểm soát nội dung thông báo khi truy cập GNOME" "PASSED"
else
output_result "1.6.7" "Kiểm soát nội dung thông báo khi truy cập GNOME" "FAILED"
fi
############################################################################
# 2. SERVICES
############################################################################
echo ""
echo "=== 2. Service ==="
echo ""
############################################################################
# 2.1 Time Synchronization
############################################################################
echo "--- 2.1. Cấu hình Time Synchronization ---"
# Count active NTP services
ntp_count=0
chrony_active=0
ntp_active=0
if systemctl is-active chrony 2>/dev/null | grep -q "^active"; then
chrony_active=1
((ntp_count++))
fi
if systemctl is-active ntpd 2>/dev/null | grep -q "^active" || \
systemctl is-active ntp 2>/dev/null | grep -q "^active"; then
ntp_active=1
((ntp_count++))
fi
# 2.1.1 Chrony
if [ $ntp_count -gt 1 ]; then
output_result "2.1.1" "Cấu hình sử dụng chrony" "FAILED"
echo "# Cảnh báo: Nhiều dịch vụ NTP đang chạy đồng thời"
elif [ $chrony_active -eq 1 ]; then
if grep -Eq '^\s*(server|pool)\s+\S+' /etc/chrony.conf 2>/dev/null; then
output_result "2.1.1" "Cấu hình sử dụng chrony" "PASSED"
else
output_result "2.1.1" "Cấu hình sử dụng chrony" "FAILED"
fi
elif [ $ntp_active -eq 0 ]; then
output_result "2.1.1" "Cấu hình sử dụng chrony" "FAILED"
else
output_result "2.1.1" "Cấu hình sử dụng chrony" "PASSED"
fi
# 2.1.2 NTP
if [ $ntp_count -gt 1 ]; then
output_result "2.1.2" "Cấu hình sử dụng NTP" "FAILED"
elif [ $ntp_active -eq 1 ]; then
if grep -Eq '^\s*(server|pool)\s+\S+' /etc/ntp.conf 2>/dev/null; then
output_result "2.1.2" "Cấu hình sử dụng NTP" "PASSED"
else
output_result "2.1.2" "Cấu hình sử dụng NTP" "FAILED"
fi
elif [ $chrony_active -eq 0 ]; then
output_result "2.1.2" "Cấu hình sử dụng NTP" "FAILED"
else
output_result "2.1.2" "Cấu hình sử dụng NTP" "PASSED"
fi
############################################################################
# 2.2 Special Purpose Services
############################################################################
echo ""
echo "--- 2.2. Các Service với mục đích riêng biệt ---"
# Service checks array: service_name:package_name:check_id:check_name
declare -a SERVICES=(
"xinetd:xinetd:2.2.1:Cấu hình vô hiệu hoá xinetd services"
"autofs:autofs:2.2.9:Cấu hình vô hiệu hoá autofs services"
"avahi-daemon:avahi:2.2.11:Cấu hình vô hiệu hoá avahi daemon services"
"cups:cups:2.2.12:Cấu hình vô hiệu hoá cups services"
"dhcpd:dhcp-server:2.2.13:Cấu hình vô hiệu hoá dhcp server services"
"slapd:openldap-servers:2.2.14:Cấu hình vô hiệu hoá ldap server services"
"named:bind:2.2.15:Cấu hình vô hiệu hoá dns server services"
"dnsmasq:dnsmasq:2.2.16:Cấu hình vô hiệu hoá dnsmasq services"
"vsftpd:vsftpd:2.2.17:Cấu hình vô hiệu hoá ftp server services"
"tftp:tftp-server:2.2.18:Cấu hình vô hiệu hoá tftp server services"
"httpd:httpd:2.2.19:Cấu hình vô hiệu hoá web server services"
"dovecot:dovecot:2.2.20:Cấu hình vô hiệu hoá imap and pop3 server services"
"smb:samba:2.2.21:Cấu hình vô hiệu hoá samba file server services"
"squid:squid:2.2.22:Cấu hình vô hiệu hoá web proxy server services"
"snmpd:net-snmp:2.2.23:Cấu hình vô hiệu hoá snmp services"
"ypserv:ypserv:2.2.24:Cấu hình vô hiệu hoá nis server services"
"telnet.socket:telnet-server:2.2.25:Cấu hình vô hiệu hoá telnet server services"
"nfs-server:nfs-utils:2.2.27:Cấu hình vô hiệu hoá network file system services"
"rpcbind:rpcbind:2.2.28:Cấu hình vô hiệu hoá rpcbind services"
"rsyncd:rsync:2.2.29:Cấu hình vô hiệu hoá rsync services"
)
for service_info in "${SERVICES[@]}"; do
IFS=':' read -r service_name package_name check_id check_name <<< "$service_info"
service_ok=1
# Check if package is installed
if check_package_installed "$package_name"; then
# Check if service is enabled or active
if ! check_service_disabled "$service_name"; then
service_ok=0
fi
fi
if [ $service_ok -eq 1 ]; then
output_result "$check_id" "$check_name" "PASSED"
else
output_result "$check_id" "$check_name" "FAILED"
fi
done
# 2.2.2-2.2.8 xinetd services (CentOS 6 only)
if [ "$CENTOS_VERSION" -eq 6 ] 2>/dev/null; then
XINETD_SERVICES=(
"chargen-dgram:chargen-stream:2.2.2:Cấu hình vô hiệu hoá chargen services"
"daytime-dgram:daytime-stream:2.2.3:Cấu hình vô hiệu hoá daytime services"
"discard-dgram:discard-stream:2.2.4:Cấu hình vô hiệu hoá discard services"
"echo-dgram:echo-stream:2.2.5:Cấu hình vô hiệu hoá echo services"
"time-dgram:time-stream:2.2.6:Cấu hình vô hiệu hoá time services"
"rexec:rlogin:rsh:2.2.7:Cấu hình vô hiệu hoá rsh server"
"talk::2.2.8:Cấu hình vô hiệu hoá talk server"
)
for svc_info in "${XINETD_SERVICES[@]}"; do
IFS=':' read -r svc1 svc2 svc3 check_id check_name <<< "$svc_info"
xinetd_ok=1
for svc in $svc1 $svc2 $svc3; do
[ -z "$svc" ] && continue
if ! chkconfig --list 2>/dev/null | grep -q "${svc}:.*off"; then
xinetd_ok=0
fi
done
if [ $xinetd_ok -eq 1 ]; then
output_result "$check_id" "$check_name" "PASSED"
else
output_result "$check_id" "$check_name" "FAILED"
fi
done
else
# For CentOS 7+, these services don't exist
for check_id in "2.2.2" "2.2.3" "2.2.4" "2.2.5" "2.2.6" "2.2.7" "2.2.8"; do
case $check_id in
"2.2.2") output_result "$check_id" "Cấu hình vô hiệu hoá chargen services" "PASSED" ;;
"2.2.3") output_result "$check_id" "Cấu hình vô hiệu hoá daytime services" "PASSED" ;;
"2.2.4") output_result "$check_id" "Cấu hình vô hiệu hoá discard services" "PASSED" ;;
"2.2.5") output_result "$check_id" "Cấu hình vô hiệu hoá echo services" "PASSED" ;;
"2.2.6") output_result "$check_id" "Cấu hình vô hiệu hoá time services" "PASSED" ;;
"2.2.7") output_result "$check_id" "Cấu hình vô hiệu hoá rsh server" "PASSED" ;;
"2.2.8") output_result "$check_id" "Cấu hình vô hiệu hoá talk server" "PASSED" ;;
esac
done
fi
# 2.2.10 X Window
if rpm -qa xorg-x11-server* 2>/dev/null | grep -q . || \
systemctl get-default 2>/dev/null | grep -q "graphical.target"; then
output_result "2.2.10" "Cấu hình vô hiệu hoá X window server services" "FAILED"
else
output_result "2.2.10" "Cấu hình vô hiệu hoá X window server services" "PASSED"
fi
# 2.2.26 Mail Transfer Agent
if ss -lntu 2>/dev/null | grep -E ':25\s' | grep -qv '127.0.0.1\|::1'; then
output_result "2.2.26" "Cấu hình mail transfer agents sang chế độ local-only" "FAILED"
else
output_result "2.2.26" "Cấu hình mail transfer agents sang chế độ local-only" "PASSED"
fi
############################################################################
# 2.3 Service Clients
############################################################################
echo ""
echo "--- 2.3. Service Clients ---"
CLIENT_PACKAGES=(
"ypbind:2.3.1:Cấu hình vô hiệu hoá NIS Client"
"rsh:2.3.2:Cấu hình vô hiệu hoá rsh client"
"talk:2.3.3:Cấu hình vô hiệu hoá talk client"
"telnet:2.3.4:Cấu hình vô hiệu hoá telnet client"
"openldap-clients:2.3.5:Cấu hình vô hiệu hoá LDAP client"
"ftp:2.3.6:Cấu hình vô hiệu hoá ftp client"
"tftp:2.3.7:Cấu hình vô hiệu hoá tftp client"
)
for pkg_info in "${CLIENT_PACKAGES[@]}"; do
IFS=':' read -r package check_id check_name <<< "$pkg_info"
if check_package_not_installed "$package"; then
output_result "$check_id" "$check_name" "PASSED"
else
output_result "$check_id" "$check_name" "FAILED"
fi
done
############################################################################
# 3. NETWORK CONFIGURATION
############################################################################
echo ""
echo "=== 3. Cấu hình mạng ==="
echo ""
############################################################################
# 3.1 Network Parameters (Host Only)
############################################################################
echo "--- 3.1. Tham số cấu hình mạng (Host Only) ---"
# 3.1.1 IP Forwarding
ipv4_forward=$(sysctl -n net.ipv4.ip_forward 2>/dev/null)
ipv6_forward=$(sysctl -n net.ipv6.conf.all.forwarding 2>/dev/null)
if [ "$ipv4_forward" = "0" ] && ([ "${IPV6_ENABLED:-0}" -eq 0 ] || [ "$ipv6_forward" = "0" ]); then
output_result "3.1.1" "Cấu hình vô hiệu hoá IP forwarding" "PASSED"
else
output_result "3.1.1" "Cấu hình vô hiệu hoá IP forwarding" "FAILED"
fi
# 3.1.2 Packet Redirect
send_redirects_all=$(sysctl -n net.ipv4.conf.all.send_redirects 2>/dev/null)
send_redirects_default=$(sysctl -n net.ipv4.conf.default.send_redirects 2>/dev/null)
if [ "$send_redirects_all" = "0" ] && [ "$send_redirects_default" = "0" ]; then
output_result "3.1.2" "Cấu hình vô hiệu hoá tính năng chuyển hướng gói tin (packet redirect)" "PASSED"
else
output_result "3.1.2" "Cấu hình vô hiệu hoá tính năng chuyển hướng gói tin (packet redirect)" "FAILED"
fi
############################################################################
# 3.2 Network Parameters (Host and Router)
############################################################################
echo ""
echo "--- 3.2. Tham số cấu hình mạng (Host và Router) ---"
# 3.2.1 Source Routed Packets
src_route_all=$(sysctl -n net.ipv4.conf.all.accept_source_route 2>/dev/null)
src_route_default=$(sysctl -n net.ipv4.conf.default.accept_source_route 2>/dev/null)
if [ "$src_route_all" = "0" ] && [ "$src_route_default" = "0" ]; then
output_result "3.2.1" "Cấu hình từ chối các gói tin với nguồn được định tuyến trước" "PASSED"
else
output_result "3.2.1" "Cấu hình từ chối các gói tin với nguồn được định tuyến trước" "FAILED"
fi
# 3.2.2 ICMP Redirects
icmp_redirect_all=$(sysctl -n net.ipv4.conf.all.accept_redirects 2>/dev/null)
icmp_redirect_default=$(sysctl -n net.ipv4.conf.default.accept_redirects 2>/dev/null)
if [ "$icmp_redirect_all" = "0" ] && [ "$icmp_redirect_default" = "0" ]; then
output_result "3.2.2" "Cấu hình từ chối các ICMP redirect message" "PASSED"
else
output_result "3.2.2" "Cấu hình từ chối các ICMP redirect message" "FAILED"
fi
# 3.2.3 Secure ICMP Redirects
secure_redirect_all=$(sysctl -n net.ipv4.conf.all.secure_redirects 2>/dev/null)
secure_redirect_default=$(sysctl -n net.ipv4.conf.default.secure_redirects 2>/dev/null)
if [ "$secure_redirect_all" = "0" ] && [ "$secure_redirect_default" = "0" ]; then
output_result "3.2.3" "Cấu hình từ chối các secure ICMP redirect message" "PASSED"
else
output_result "3.2.3" "Cấu hình từ chối các secure ICMP redirect message" "FAILED"
fi
# 3.2.4 ICMP Broadcast
icmp_echo_ignore=$(sysctl -n net.ipv4.icmp_echo_ignore_broadcasts 2>/dev/null)
if [ "$icmp_echo_ignore" = "1" ]; then
output_result "3.2.4" "Cấu hình từ chối các gói tin ICMP request broadcast" "PASSED"
else
output_result "3.2.4" "Cấu hình từ chối các gói tin ICMP request broadcast" "FAILED"
fi
# 3.2.5 Bogus ICMP Responses
icmp_ignore_bogus=$(sysctl -n net.ipv4.icmp_ignore_bogus_error_responses 2>/dev/null)
if [ "$icmp_ignore_bogus" = "1" ]; then
output_result "3.2.5" "Cấu hình bỏ qua phản hồi ICMP không hợp lệ" "PASSED"
else
output_result "3.2.5" "Cấu hình bỏ qua phản hồi ICMP không hợp lệ" "FAILED"
fi
# 3.2.6 Reverse Path Filtering
rp_filter_all=$(sysctl -n net.ipv4.conf.all.rp_filter 2>/dev/null)
rp_filter_default=$(sysctl -n net.ipv4.conf.default.rp_filter 2>/dev/null)
if [ "$rp_filter_all" = "1" ] && [ "$rp_filter_default" = "1" ]; then
output_result "3.2.6" "Cấu hình Reverse Path Filtering" "PASSED"
else
output_result "3.2.6" "Cấu hình Reverse Path Filtering" "FAILED"
fi
# 3.2.7 TCP SYN Cookies
tcp_syncookies=$(sysctl -n net.ipv4.tcp_syncookies 2>/dev/null)
if [ "$tcp_syncookies" = "1" ]; then
output_result "3.2.7" "Cấu hình TCP SYN Cookies" "PASSED"
else
output_result "3.2.7" "Cấu hình TCP SYN Cookies" "FAILED"
fi
############################################################################
# 3.4 Firewall Configuration
############################################################################
echo ""
echo "--- 3.4. Cấu hình Firewall ---"
# Detect which firewall is in use
FIREWALLD_ACTIVE=0
IPTABLES_ACTIVE=0
FIREWALLD_PASS=0
IPTABLES_PASS=0
if systemctl is-active firewalld 2>/dev/null | grep -q "^active"; then
FIREWALLD_ACTIVE=1
fi
if systemctl is-active iptables 2>/dev/null | grep -q "^active"; then
IPTABLES_ACTIVE=1
fi
# 3.4.1 Firewalld
echo "--- 3.4.1. Cấu hình firewalld ---"
# 3.4.1.1 Firewalld enabled
# Nếu 1 trong 2 loại firewall đang active → cả 2 mục "kích hoạt" đều PASSED
if [ $FIREWALLD_ACTIVE -eq 1 ] || [ $IPTABLES_ACTIVE -eq 1 ]; then
output_result "3.4.1.1" "Cấu hình kích hoạt firewalld" "PASSED"
if [ $FIREWALLD_ACTIVE -eq 1 ]; then
FIREWALLD_PASS=1
fi
if [ $IPTABLES_ACTIVE -eq 1 ]; then
IPTABLES_PASS=1
fi
else
output_result "3.4.1.1" "Cấu hình kích hoạt firewalld" "FAILED"
log_failed "# Kích hoạt firewalld:
# systemctl --now enable firewalld
# Hoặc kích hoạt iptables:
# systemctl --now enable iptables"
fi
# 3.4.1.3 Firewalld rules for open ports
if [ $IPTABLES_PASS -eq 1 ] && [ $FIREWALLD_PASS -eq 0 ]; then
# Iptables đang xử lý firewall → firewalld checks tự động PASSED
output_result "3.4.1.3" "Cấu hình firewalld rule cho tất cả các port và protocol đang mở" "PASSED"
elif [ $FIREWALLD_ACTIVE -eq 1 ]; then
# Check if there are rules configured
if firewall-cmd --list-all 2>/dev/null | grep -qE "(services:|ports:)"; then
output_result "3.4.1.3" "Cấu hình firewalld rule cho tất cả các port và protocol đang mở" "PASSED"
else
output_result "3.4.1.3" "Cấu hình firewalld rule cho tất cả các port và protocol đang mở" "FAILED"
fi
else
output_result "3.4.1.3" "Cấu hình firewalld rule cho tất cả các port và protocol đang mở" "FAILED"
fi
# 3.4.1.4 Default deny policy
if [ $IPTABLES_PASS -eq 1 ] && [ $FIREWALLD_PASS -eq 0 ]; then
# Iptables đang xử lý firewall → firewalld checks tự động PASSED
output_result "3.4.1.4" "Cấu hình chính sách từ chối mặc định cho firewalld" "PASSED"
elif [ $FIREWALLD_ACTIVE -eq 1 ]; then
# Kiểm tra default policy (target) của tất cả các zone đang active
# Dùng --list-all-zones để parse active zone + target trong một lần gọi
# Với mỗi zone active, target phải là DROP hoặc REJECT
fw_default_deny=$(firewall-cmd --list-all-zones 2>/dev/null | awk '
/\(active\)/ { in_active=1; next }
/^[^ \t]/ && !/\(active\)/ { in_active=0 }
in_active && /target:/ {
t = $2
gsub(/%%/, "", t)
if (t != "DROP" && t != "REJECT") bad=1
}
END { print (bad ? "0" : "1") }
')
# --- DEBUG INFO ---
echo "DEBUG [3.4.1.4]: FIREWALLD_ACTIVE=[$FIREWALLD_ACTIVE]" >&2
echo "DEBUG [3.4.1.4]: fw_default_deny=[$fw_default_deny]" >&2
# ------------------
if [ "$fw_default_deny" = "1" ]; then
output_result "3.4.1.4" "Cấu hình chính sách từ chối mặc định cho firewalld" "PASSED"
else
output_result "3.4.1.4" "Cấu hình chính sách từ chối mặc định cho firewalld" "FAILED"
fi
else
output_result "3.4.1.4" "Cấu hình chính sách từ chối mặc định cho firewalld" "FAILED"
fi
# 3.4.2 Iptables
echo ""
echo "--- 3.4.2. Iptables ---"
# 3.4.2.1 Iptables enabled
if [ $IPTABLES_ACTIVE -eq 1 ] || [ $FIREWALLD_ACTIVE -eq 1 ]; then
output_result "3.4.2.1" "Cấu hình kích hoạt Iptables" "PASSED"
else
output_result "3.4.2.1" "Cấu hình kích hoạt Iptables" "FAILED"
fi
# 3.4.2.3 Loopback traffic
if [ $FIREWALLD_PASS -eq 1 ] && [ $IPTABLES_PASS -eq 0 ]; then
# Firewalld đang xử lý firewall → iptables checks tự động PASSED
output_result "3.4.2.3" "Cấu hình iptables loopback traffic" "PASSED"
else
lo_input=$(iptables -L INPUT -v -n 2>/dev/null | grep -E "ACCEPT.*lo.*0.0.0.0/0.*0.0.0.0/0")
lo_output=$(iptables -L OUTPUT -v -n 2>/dev/null | grep -E "ACCEPT.*lo.*0.0.0.0/0.*0.0.0.0/0")
lo_drop=$(iptables -L INPUT -v -n 2>/dev/null | grep -E "DROP.*127.0.0.0/8")
if [ -n "$lo_input" ] && [ -n "$lo_output" ] && [ -n "$lo_drop" ]; then
output_result "3.4.2.3" "Cấu hình iptables loopback traffic" "PASSED"
else
output_result "3.4.2.3" "Cấu hình iptables loopback traffic" "FAILED"
fi
fi
# 3.4.2.4 Iptables rules for open ports
if [ $FIREWALLD_PASS -eq 1 ] && [ $IPTABLES_PASS -eq 0 ]; then
# Firewalld đang xử lý firewall → iptables checks tự động PASSED
output_result "3.4.2.4" "Cấu hình iptables rule cho tất cả các port và protocol đang mở" "PASSED"
else
if iptables -L -n 2>/dev/null | grep -qE "(ACCEPT|DROP|REJECT)"; then
output_result "3.4.2.4" "Cấu hình iptables rule cho tất cả các port và protocol đang mở" "PASSED"
else
output_result "3.4.2.4" "Cấu hình iptables rule cho tất cả các port và protocol đang mở" "FAILED"
fi
fi
# 3.4.2.5 Default deny policy
if [ $FIREWALLD_PASS -eq 1 ] && [ $IPTABLES_PASS -eq 0 ]; then
# Firewalld đang xử lý firewall → iptables checks tự động PASSED
output_result "3.4.2.5" "Cấu hình chính sách từ chối mặc định cho iptables" "PASSED"
else
input_policy=$(iptables -L INPUT 2>/dev/null | head -1 | grep -oE "(ACCEPT|DROP|REJECT)")
forward_policy=$(iptables -L FORWARD 2>/dev/null | head -1 | grep -oE "(ACCEPT|DROP|REJECT)")
output_policy=$(iptables -L OUTPUT 2>/dev/null | head -1 | grep -oE "(ACCEPT|DROP|REJECT)")
if [ "$input_policy" = "DROP" ] || [ "$input_policy" = "REJECT" ]; then
if [ "$forward_policy" = "DROP" ] || [ "$forward_policy" = "REJECT" ]; then
output_result "3.4.2.5" "Cấu hình chính sách từ chối mặc định cho iptables" "PASSED"
else
output_result "3.4.2.5" "Cấu hình chính sách từ chối mặc định cho iptables" "FAILED"
fi
else
output_result "3.4.2.5" "Cấu hình chính sách từ chối mặc định cho iptables" "FAILED"
fi
fi
############################################################################
# 4. LOGGING AND AUDITING
############################################################################
echo ""
echo "=== 4. Logging và Auditing ==="
echo ""
############################################################################
# 4.1 Configure Logging
############################################################################
echo "--- 4.1. Cấu hình logging ---"
echo "--- 4.1.1. Cấu hình rsyslog ---"
# 4.1.1.1 rsyslog enabled
if systemctl is-enabled rsyslog 2>/dev/null | grep -q "enabled"; then
output_result "4.1.1.1" "Cấu hình kích hoạt rsyslog service" "PASSED"
else
output_result "4.1.1.1" "Cấu hình kích hoạt rsyslog service" "FAILED"
fi
# 4.1.1.2 rsyslog file permissions
rsyslog_perms_ok=1
if grep -q '^\$FileCreateMode' /etc/rsyslog.conf 2>/dev/null; then
mode=$(grep '^\$FileCreateMode' /etc/rsyslog.conf | awk '{print $2}')
if [ "$mode" != "0640" ] && [ "$mode" != "0600" ]; then
rsyslog_perms_ok=0
fi
else
rsyslog_perms_ok=0
fi
if [ $rsyslog_perms_ok -eq 1 ]; then
output_result "4.1.1.2" "Phân quyền đối với file log sinh ra từ rsyslog" "PASSED"
else
output_result "4.1.1.2" "Phân quyền đối với file log sinh ra từ rsyslog" "FAILED"
fi
# 4.1.1.3 Remote logging
if grep -qE '^\s*\*\.\*\s+@' /etc/rsyslog.conf /etc/rsyslog.d/*.conf 2>/dev/null; then
output_result "4.1.1.3" "Cấu hình lưu trữ log sinh ra từ rsyslog tập trung" "PASSED"
else
output_result "4.1.1.3" "Cấu hình lưu trữ log sinh ra từ rsyslog tập trung" "FAILED"
fi
# 4.1.1.4 Log file permissions
log_perms_ok=1
for logfile in /var/log/messages /var/log/secure /var/log/maillog /var/log/cron /var/log/boot.log; do
if [ -f "$logfile" ]; then
perms=$(stat -c "%a" "$logfile" 2>/dev/null)
if [ "$perms" != "600" ] && [ "$perms" != "640" ]; then
log_perms_ok=0
fi
fi
done
if [ $log_perms_ok -eq 1 ]; then
output_result "4.1.1.4" "Phân quyền đối với tất cả các file log" "PASSED"
else
output_result "4.1.1.4" "Phân quyền đối với tất cả các file log" "FAILED"
fi
############################################################################
# 5. ACCESS, AUTHENTICATION AND AUTHORIZATION
############################################################################
echo ""
echo "=== 5. Cấu hình truy cập, xác thực và ủy quyền ==="
echo ""
############################################################################
# 5.1 Configure cron
############################################################################
echo "--- 5.1. Cấu hình cron ---"
# 5.1.1 Cron daemon enabled
if systemctl is-enabled crond 2>/dev/null | grep -q "enabled"; then
output_result "5.1.1" "Cấu hình kích hoạt cron daemon" "PASSED"
else
output_result "5.1.1" "Cấu hình kích hoạt cron daemon" "FAILED"
fi
# 5.1.2-5.1.7 Cron file permissions
CRON_FILES=(
"/etc/crontab:5.1.2:Cấu hình phân quyền cho file /etc/crontab"
"/etc/cron.hourly:5.1.3:Cấu hình phân quyền cho file /etc/cron.hourly"
"/etc/cron.daily:5.1.4:Cấu hình phân quyền cho file /etc/cron.daily"
"/etc/cron.weekly:5.1.5:Cấu hình phân quyền cho file /etc/cron.weekly"
"/etc/cron.monthly:5.1.6:Cấu hình phân quyền cho của file /etc/cron.monthly"
"/etc/cron.d:5.1.7:Cấu hình phân quyền cho file /etc/cron.d"
)
for cron_info in "${CRON_FILES[@]}"; do
IFS=':' read -r file check_id check_name <<< "$cron_info"
if [ -e "$file" ]; then
perms=$(stat -c "%a:%u:%g" "$file" 2>/dev/null)
if echo "$perms" | grep -qP "^[0-7]00:0:0$"; then
output_result "$check_id" "$check_name" "PASSED"
else
output_result "$check_id" "$check_name" "FAILED"
fi
else
output_result "$check_id" "$check_name" "PASSED"
fi
done
# 5.1.8 at/cron restricted
if [ -f /etc/cron.allow ] && [ ! -f /etc/cron.deny ]; then
if [ -f /etc/at.allow ] && [ ! -f /etc/at.deny ]; then
output_result "5.1.8" "Cấu hình at/cron hạn chế chỉ cho người dùng được ủy quyền" "PASSED"
else
output_result "5.1.8" "Cấu hình at/cron hạn chế chỉ cho người dùng được ủy quyền" "FAILED"
fi
else
output_result "5.1.8" "Cấu hình at/cron hạn chế chỉ cho người dùng được ủy quyền" "FAILED"
fi
############################################################################
# 5.2 SSH Server Configuration
############################################################################
echo ""
echo "--- 5.2. Cấu hình máy chủ SSH ---"
SSHD_CONFIG="/etc/ssh/sshd_config"
# Helper function to get SSH config value
get_ssh_config() {
local param="$1"
grep -iE "^\s*${param}\s+" "$SSHD_CONFIG" /etc/ssh/sshd_config.d/*.conf 2>/dev/null | tail -1 | awk '{print $2}'
}
# 5.2.1 sshd_config permissions
if stat -c "%a:%u:%g" "$SSHD_CONFIG" 2>/dev/null | grep -qP "^[0-6]00:0:0$"; then
output_result "5.2.1" "Cấu hình phân quyền cho file /etc/ssh/sshd_config" "PASSED"
else
output_result "5.2.1" "Cấu hình phân quyền cho file /etc/ssh/sshd_config" "FAILED"
fi
# 5.2.2 SSH private key permissions
ssh_priv_ok=1
for keyfile in /etc/ssh/ssh_host_*_key; do
if [ -f "$keyfile" ]; then
perms=$(stat -c "%a:%u:%g" "$keyfile" 2>/dev/null)
if ! echo "$perms" | grep -qP "^[0-6]00:0:0$"; then
ssh_priv_ok=0
fi
fi
done
if [ $ssh_priv_ok -eq 1 ]; then
output_result "5.2.2" "Cấu hình phân quyền cho các file SSH private host key" "PASSED"
else
output_result "5.2.2" "Cấu hình phân quyền cho các file SSH private host key" "FAILED"
fi
# 5.2.3 SSH public key permissions
ssh_pub_ok=1
for keyfile in /etc/ssh/ssh_host_*_key.pub; do
if [ -f "$keyfile" ]; then
perms=$(stat -c "%a:%u:%g" "$keyfile" 2>/dev/null)
if ! echo "$perms" | grep -qP "^[0-6][0-4][0-4]:0:0$"; then
ssh_pub_ok=0
fi
fi
done
if [ $ssh_pub_ok -eq 1 ]; then
output_result "5.2.3" "Cấu hình phân quyền cho các file SSH public host key" "PASSED"
else
output_result "5.2.3" "Cấu hình phân quyền cho các file SSH public host key" "FAILED"
fi
# 5.2.4 SSH access restriction
if grep -qiE "^\s*(AllowUsers|AllowGroups|DenyUsers|DenyGroups)\s+" "$SSHD_CONFIG" /etc/ssh/sshd_config.d/*.conf 2>/dev/null; then
output_result "5.2.4" "Cấu hình giới hạn truy cập cho máy chủ SSH" "PASSED"
else
output_result "5.2.4" "Cấu hình giới hạn truy cập cho máy chủ SSH" "FAILED"
fi
# 5.2.5 SSH LogLevel
loglevel=$(get_ssh_config "LogLevel")
if [ "$loglevel" = "INFO" ] || [ "$loglevel" = "VERBOSE" ]; then
output_result "5.2.5" "Cấu hình LogLevel cho máy chủ SSH" "PASSED"
else
output_result "5.2.5" "Cấu hình LogLevel cho máy chủ SSH" "FAILED"
fi
# 5.2.6 SSH PAM
usepam=$(get_ssh_config "UsePAM")
if [ "$usepam" = "yes" ]; then
output_result "5.2.6" "Cấu hình sử dụng SSH PAM" "PASSED"
else
output_result "5.2.6" "Cấu hình sử dụng SSH PAM" "FAILED"
fi
# 5.2.7 SSH root login
permitroot=$(get_ssh_config "PermitRootLogin")
if [ "$permitroot" = "no" ]; then
output_result "5.2.7" "Cấu hình vô hiệu hoá đăng nhập bằng root cho máy chủ SSH" "PASSED"
else
output_result "5.2.7" "Cấu hình vô hiệu hoá đăng nhập bằng root cho máy chủ SSH" "FAILED"
fi
# 5.2.8 SSH HostbasedAuthentication
hostbased=$(get_ssh_config "HostbasedAuthentication")
if [ "$hostbased" = "no" ]; then
output_result "5.2.8" "Cấu hình vô hiệu hoá HostbasedAuthentication cho máy chủ SSH" "PASSED"
else
output_result "5.2.8" "Cấu hình vô hiệu hoá HostbasedAuthentication cho máy chủ SSH" "FAILED"
fi
# 5.2.9 SSH PermitEmptyPasswords
emptypass=$(get_ssh_config "PermitEmptyPasswords")
if [ "$emptypass" = "no" ]; then
output_result "5.2.9" "Cấu hình vô hiệu hoá PermitEmptyPasswords cho máy chủ SSH" "PASSED"
else
output_result "5.2.9" "Cấu hình vô hiệu hoá PermitEmptyPasswords cho máy chủ SSH" "FAILED"
fi
# 5.2.10 SSH PermitUserEnvironment
userenv=$(get_ssh_config "PermitUserEnvironment")
if [ "$userenv" = "no" ]; then
output_result "5.2.10" "Cấu hình vô hiệu hoá PermitUserEnviroment cho máy chủ SSH" "PASSED"
else
output_result "5.2.10" "Cấu hình vô hiệu hoá PermitUserEnviroment cho máy chủ SSH" "FAILED"
fi
# 5.2.11 SSH IgnoreRhosts
ignorerhosts=$(get_ssh_config "IgnoreRhosts")
if [ "$ignorerhosts" = "yes" ]; then
output_result "5.2.11" "Cấu hình vô hiệu hoá IgnoreRhosts cho máy chủ SSH" "PASSED"
else
output_result "5.2.11" "Cấu hình vô hiệu hoá IgnoreRhosts cho máy chủ SSH" "FAILED"
fi
# 5.2.12 SSH X11Forwarding
x11forward=$(get_ssh_config "X11Forwarding")
if [ "$x11forward" = "no" ]; then
output_result "5.2.12" "Cấu hình vô hiệu hoá X11 Forwarding cho máy chủ SSH" "PASSED"
else
output_result "5.2.12" "Cấu hình vô hiệu hoá X11 Forwarding cho máy chủ SSH" "FAILED"
fi
# 5.2.13 SSH AllowTcpForwarding
tcpforward=$(get_ssh_config "AllowTcpForwarding")
if [ "$tcpforward" = "no" ]; then
output_result "5.2.13" "Cấu hình vô hiệu hoá SSH AllowTcpForwarding" "PASSED"
else
output_result "5.2.13" "Cấu hình vô hiệu hoá SSH AllowTcpForwarding" "FAILED"
fi
# 5.2.14 SSH Banner
banner=$(get_ssh_config "Banner")
if [ -n "$banner" ] && [ "$banner" != "none" ]; then
output_result "5.2.14" "Cấu hình cảnh báo SSH" "PASSED"
else
output_result "5.2.14" "Cấu hình cảnh báo SSH" "FAILED"
fi
# 5.2.15 SSH MaxAuthTries
maxauth=$(get_ssh_config "MaxAuthTries")
if [ -n "$maxauth" ] && [ "$maxauth" -le 4 ] 2>/dev/null; then
output_result "5.2.15" "Cấu hình SSH MaxAuthTries" "PASSED"
else
output_result "5.2.15" "Cấu hình SSH MaxAuthTries" "FAILED"
fi
# 5.2.16 SSH MaxStartups
maxstartups=$(get_ssh_config "MaxStartups")
if [ -n "$maxstartups" ]; then
output_result "5.2.16" "Cấu hình SSH MaxStartups" "PASSED"
else
output_result "5.2.16" "Cấu hình SSH MaxStartups" "FAILED"
fi
# 5.2.17 SSH MaxSessions
maxsessions=$(get_ssh_config "MaxSessions")
if [ -n "$maxsessions" ] && [ "$maxsessions" -le 10 ] 2>/dev/null; then
output_result "5.2.17" "Cấu hình SSH MaxSessions" "PASSED"
else
output_result "5.2.17" "Cấu hình SSH MaxSessions" "FAILED"
fi
# 5.2.18 SSH LoginGraceTime
logingrace=$(get_ssh_config "LoginGraceTime")
if [ -n "$logingrace" ] && [ "$logingrace" -le 60 ] 2>/dev/null; then
output_result "5.2.18" "Cấu hình SSH LoginGraceTime" "PASSED"
else
output_result "5.2.18" "Cấu hình SSH LoginGraceTime" "FAILED"
fi
# 5.2.19 SSH Idle Timeout
clientalive=$(get_ssh_config "ClientAliveInterval")
clientcount=$(get_ssh_config "ClientAliveCountMax")
if [ -n "$clientalive" ] && [ "$clientalive" -gt 0 ] 2>/dev/null; then
output_result "5.2.19" "Cấu hình khoảng thời gian chờ không hoạt động cho máy chủ SSH" "PASSED"
else
output_result "5.2.19" "Cấu hình khoảng thời gian chờ không hoạt động cho máy chủ SSH" "FAILED"
fi
# 5.2.20 SSH MAC algorithms
macs=$(get_ssh_config "MACs")
if [ -n "$macs" ]; then
output_result "5.2.20" "Cấu hình các thuật toán MAC được cho phép" "PASSED"
else
output_result "5.2.20" "Cấu hình các thuật toán MAC được cho phép" "FAILED"
fi
############################################################################
# 5.3 Configure PAM
############################################################################
echo ""
echo "--- 5.3. Cấu hình PAM ---"
# 5.3.1 Password creation requirements
if grep -qE "^\s*password\s+requisite\s+pam_pwquality.so" /etc/pam.d/system-auth /etc/pam.d/password-auth 2>/dev/null; then
if grep -qE "^\s*minlen\s*=\s*([8-9]|[1-9][0-9]+)" /etc/security/pwquality.conf 2>/dev/null; then
output_result "5.3.1" "Cấu hình điều kiện tạo mật khẩu" "PASSED"
else
output_result "5.3.1" "Cấu hình điều kiện tạo mật khẩu" "FAILED"
fi
else
output_result "5.3.1" "Cấu hình điều kiện tạo mật khẩu" "FAILED"
fi
# 5.3.2 Lockout for failed password attempts
if grep -qE "^\s*auth\s+required\s+pam_faillock.so" /etc/pam.d/system-auth /etc/pam.d/password-auth 2>/dev/null || \
grep -qE "^\s*auth\s+required\s+pam_tally2.so" /etc/pam.d/system-auth /etc/pam.d/password-auth 2>/dev/null; then
output_result "5.3.2" "Cấu hình khoá truy cập do nhiều lần nhập mật khẩu thất bại" "PASSED"
else
output_result "5.3.2" "Cấu hình khoá truy cập do nhiều lần nhập mật khẩu thất bại" "FAILED"
fi
# 5.3.3 Password reuse limitation
if grep -qE "^\s*password\s+(sufficient|required)\s+pam_unix.so.*remember=([5-9]|[1-9][0-9]+)" /etc/pam.d/system-auth 2>/dev/null; then
output_result "5.3.3" "Giới hạn việc sử dụng lại mật khẩu" "PASSED"
else
output_result "5.3.3" "Giới hạn việc sử dụng lại mật khẩu" "FAILED"
fi
# 5.3.4 Password hashing algorithm
if grep -qE "^\s*password\s+sufficient\s+pam_unix.so.*sha512" /etc/pam.d/system-auth 2>/dev/null; then
output_result "5.3.4" "Cấu hình thuật toán hash mật khẩu sang SHA-512" "PASSED"
else
output_result "5.3.4" "Cấu hình thuật toán hash mật khẩu sang SHA-512" "FAILED"
fi
############################################################################
# 5.4 User Accounts and Environment
############################################################################
echo ""
echo "--- 5.4. Cấu hình tài khoản người dùng và môi trường ---"
echo "--- 5.4.1. Cấu hình mật khẩu người dùng ---"
# 5.4.1.1 Password expiration
pass_max_days=$(grep "^PASS_MAX_DAYS" /etc/login.defs 2>/dev/null | awk '{print $2}')
if [ -n "$pass_max_days" ] && [ "$pass_max_days" -le 365 ] 2>/dev/null; then
output_result "5.4.1.1" "Cấu hình thời gian hết hạn sử dụng mật khẩu" "PASSED"
else
output_result "5.4.1.1" "Cấu hình thời gian hết hạn sử dụng mật khẩu" "FAILED"
fi
# 5.4.1.2 Minimum days between password changes
pass_min_days=$(grep "^PASS_MIN_DAYS" /etc/login.defs 2>/dev/null | awk '{print $2}')
if [ -n "$pass_min_days" ] && [ "$pass_min_days" -ge 1 ] 2>/dev/null; then
output_result "5.4.1.2" "Cấu hình thời gian tối thiểu giữa những lần thay đổi mật khẩu" "PASSED"
else
output_result "5.4.1.2" "Cấu hình thời gian tối thiểu giữa những lần thay đổi mật khẩu" "FAILED"
fi
# 5.4.1.3 Password expiration warning
pass_warn_age=$(grep "^PASS_WARN_AGE" /etc/login.defs 2>/dev/null | awk '{print $2}')
if [ -n "$pass_warn_age" ] && [ "$pass_warn_age" -ge 7 ] 2>/dev/null; then
output_result "5.4.1.3" "Cấu hình thời gian cảnh báo mật khẩu hết hạn" "PASSED"
else
output_result "5.4.1.3" "Cấu hình thời gian cảnh báo mật khẩu hết hạn" "FAILED"
fi
# 5.4.1.4 Inactive password lock
inactive=$(useradd -D 2>/dev/null | grep INACTIVE | cut -d= -f2)
if [ -n "$inactive" ] && [ "$inactive" -le 30 ] && [ "$inactive" -ge 0 ] 2>/dev/null; then
output_result "5.4.1.4" "Cấu hình thời gian khoá tài khoản không thay mật khẩu sau khi hết hạn" "PASSED"
else
output_result "5.4.1.4" "Cấu hình thời gian khoá tài khoản không thay mật khẩu sau khi hết hạn" "FAILED"
fi
# 5.4.1.5 Last password change date
today=$(date +%s)
today_days=$((today / 86400))
pass_change_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ "$pass" != "*" ] && [ "$pass" != "!" ] && [ "$pass" != "!!" ]; then
lastchange=$(chage -l "$user" 2>/dev/null | grep "Last password change" | cut -d: -f2 | xargs)
if [ "$lastchange" != "never" ] && [ -n "$lastchange" ]; then
change_date=$(date -d "$lastchange" +%s 2>/dev/null)
if [ -n "$change_date" ] && [ "$change_date" -gt "$today" ]; then
pass_change_ok=0
fi
fi
fi
done < /etc/shadow 2>/dev/null
if [ $pass_change_ok -eq 1 ]; then
output_result "5.4.1.5" "Đảm bảo thời gian thay đổi mật khẩu lần cuối hợp lệ" "PASSED"
else
output_result "5.4.1.5" "Đảm bảo thời gian thay đổi mật khẩu lần cuối hợp lệ" "FAILED"
fi
# 5.4.2 System accounts non-login
sys_accounts_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ "$uid" -lt 1000 ] && [ "$user" != "root" ]; then
if [ "$shell" != "/sbin/nologin" ] && [ "$shell" != "/usr/sbin/nologin" ] && [ "$shell" != "/bin/false" ]; then
sys_accounts_ok=0
fi
fi
done < /etc/passwd 2>/dev/null
if [ $sys_accounts_ok -eq 1 ]; then
output_result "5.4.2" "Cấu hình vô hiệu hoá đăng nhập bằng tài khoản hệ thống" "PASSED"
else
output_result "5.4.2" "Cấu hình vô hiệu hoá đăng nhập bằng tài khoản hệ thống" "FAILED"
fi
# 5.4.3 Default shell timeout
if grep -qE "^\s*TMOUT=([1-9][0-9]{0,2}|[1-8][0-9]{3}|900)" /etc/bashrc /etc/profile /etc/profile.d/*.sh 2>/dev/null; then
output_result "5.4.3" "Cấu hình shell timeout mặc định" "PASSED"
else
output_result "5.4.3" "Cấu hình shell timeout mặc định" "FAILED"
fi
# 5.4.4 Root default group
root_gid=$(grep "^root:" /etc/passwd | cut -d: -f4)
if [ "$root_gid" = "0" ]; then
output_result "5.4.4" "Cấu hình group mặc định của tài khoản root" "PASSED"
else
output_result "5.4.4" "Cấu hình group mặc định của tài khoản root" "FAILED"
fi
# 5.4.5 Default umask
if grep -qE "^\s*umask\s+0[2-7][2-7]" /etc/bashrc /etc/profile /etc/profile.d/*.sh 2>/dev/null; then
output_result "5.4.5" "Cấu hình user umask mặc định" "PASSED"
else
output_result "5.4.5" "Cấu hình user umask mặc định" "FAILED"
fi
# 5.4.6 Restrict su command
if grep -qE "^\s*auth\s+required\s+pam_wheel.so\s+use_uid" /etc/pam.d/su 2>/dev/null; then
output_result "5.4.6" "Cấu hình hạn chế truy cập cho câu lệnh su" "PASSED"
else
output_result "5.4.6" "Cấu hình hạn chế truy cập cho câu lệnh su" "FAILED"
fi
############################################################################
# 6. SYSTEM MAINTENANCE
############################################################################
echo ""
echo "=== 6. System Maintenance ==="
echo ""
############################################################################
# 6.1 System File Permissions
############################################################################
echo "--- 6.1. Quyền của file hệ thống ---"
# 6.1.1 Sticky bit on world-writable directories
sticky_ok=1
world_writable_dirs=$(df --local -P 2>/dev/null | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -type d -perm -0002 ! -perm -1000 2>/dev/null | head -1)
if [ -z "$world_writable_dirs" ]; then
output_result "6.1.1" "Cấu hình sticky bit cho tất cả các thư mục dùng chung" "PASSED"
else
output_result "6.1.1" "Cấu hình sticky bit cho tất cả các thư mục dùng chung" "FAILED"
fi
# 6.1.2-6.1.9 System file permissions
SYS_FILES=(
"/etc/passwd:644:0:0:6.1.2:Cấu hình phân quyền cho file /etc/passwd"
"/etc/shadow:0:0:0:6.1.3:Cấu hình phân quyền cho file /etc/shadow"
"/etc/group:644:0:0:6.1.4:Cấu hình phân quyền cho file /etc/group"
"/etc/gshadow:0:0:0:6.1.5:Cấu hình phân quyền cho file /etc/gshadow"
"/etc/passwd-:644:0:0:6.1.6:Cấu hình phân quyền cho file /etc/passwd-"
"/etc/shadow-:0:0:0:6.1.7:Cấu hình phân quyền cho file /etc/shadow-"
"/etc/group-:644:0:0:6.1.8:Cấu hình phân quyền cho file /etc/group-"
"/etc/gshadow-:0:0:0:6.1.9:Cấu hình phân quyền cho file /etc/gshadow-"
)
for file_info in "${SYS_FILES[@]}"; do
IFS=':' read -r file expected_mode expected_uid expected_gid check_id check_name <<< "$file_info"
if [ -f "$file" ]; then
actual=$(stat -c "%a:%u:%g" "$file" 2>/dev/null)
actual_mode=$(echo "$actual" | cut -d: -f1)
actual_uid=$(echo "$actual" | cut -d: -f2)
actual_gid=$(echo "$actual" | cut -d: -f3)
if [ "$actual_mode" -le "$expected_mode" ] 2>/dev/null && \
[ "$actual_uid" = "$expected_uid" ] && \
[ "$actual_gid" = "$expected_gid" ]; then
output_result "$check_id" "$check_name" "PASSED"
else
output_result "$check_id" "$check_name" "FAILED"
fi
else
output_result "$check_id" "$check_name" "PASSED"
fi
done
# 6.1.10 No world-writable files
world_writable=$(df --local -P 2>/dev/null | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -type f -perm -0002 2>/dev/null | head -1)
if [ -z "$world_writable" ]; then
output_result "6.1.10" "Đảm bảo không có file world-writable tồn tại" "PASSED"
else
output_result "6.1.10" "Đảm bảo không có file world-writable tồn tại" "FAILED"
fi
# 6.1.11 No unowned files
unowned=$(df --local -P 2>/dev/null | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -nouser 2>/dev/null | head -1)
if [ -z "$unowned" ]; then
output_result "6.1.11" "Đảm bảo các file hoặc thư mục không có chủ sở hữu không tồn tại" "PASSED"
else
output_result "6.1.11" "Đảm bảo các file hoặc thư mục không có chủ sở hữu không tồn tại" "FAILED"
fi
# 6.1.12 No ungrouped files
ungrouped=$(df --local -P 2>/dev/null | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -nogroup 2>/dev/null | head -1)
if [ -z "$ungrouped" ]; then
output_result "6.1.12" "Đảm bảo các file hoặc thư mục không có nhóm không tồn tại" "PASSED"
else
output_result "6.1.12" "Đảm bảo các file hoặc thư mục không có nhóm không tồn tại" "FAILED"
fi
############################################################################
# 6.2 User and Group Settings
############################################################################
echo ""
echo "--- 6.2. Thiết lập cho người dùng và nhóm ---"
# 6.2.1 No empty password fields
empty_pass=$(awk -F: '($2 == "") {print $1}' /etc/shadow 2>/dev/null)
if [ -z "$empty_pass" ]; then
output_result "6.2.1" "Đảm bảo trường mật khẩu không để trống" "PASSED"
else
output_result "6.2.1" "Đảm bảo trường mật khẩu không để trống" "FAILED"
fi
# 6.2.2 All groups in /etc/passwd exist in /etc/group
groups_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if ! grep -q "^[^:]*:[^:]*:${gid}:" /etc/group 2>/dev/null; then
groups_ok=0
fi
done < /etc/passwd 2>/dev/null
if [ $groups_ok -eq 1 ]; then
output_result "6.2.2" "Đảm bảo mọi nhóm trong file /etc/passwd tồn tại trong file /etc/group" "PASSED"
else
output_result "6.2.2" "Đảm bảo mọi nhóm trong file /etc/passwd tồn tại trong file /etc/group" "FAILED"
fi
# 6.2.3 No duplicate UIDs
dup_uids=$(cut -d: -f3 /etc/passwd 2>/dev/null | sort | uniq -d)
if [ -z "$dup_uids" ]; then
output_result "6.2.3" "Đảm bảo UID không bị lặp" "PASSED"
else
output_result "6.2.3" "Đảm bảo UID không bị lặp" "FAILED"
fi
# 6.2.4 No duplicate GIDs
dup_gids=$(cut -d: -f3 /etc/group 2>/dev/null | sort | uniq -d)
if [ -z "$dup_gids" ]; then
output_result "6.2.4" "Đảm bảo GID không bị lặp" "PASSED"
else
output_result "6.2.4" "Đảm bảo GID không bị lặp" "FAILED"
fi
# 6.2.5 No duplicate user names
dup_users=$(cut -d: -f1 /etc/passwd 2>/dev/null | sort | uniq -d)
if [ -z "$dup_users" ]; then
output_result "6.2.5" "Đảm bảo tên người dùng không bị lặp" "PASSED"
else
output_result "6.2.5" "Đảm bảo tên người dùng không bị lặp" "FAILED"
fi
# 6.2.6 No duplicate group names
dup_groups=$(cut -d: -f1 /etc/group 2>/dev/null | sort | uniq -d)
if [ -z "$dup_groups" ]; then
output_result "6.2.6" "Đảm bảo tên group không bị lặp" "PASSED"
else
output_result "6.2.6" "Đảm bảo tên group không bị lặp" "FAILED"
fi
# 6.2.7 Root PATH integrity
path_ok=1
oldIFS="$IFS"
IFS=':'
for p in $PATH; do
IFS="$oldIFS"
if [ "$p" = "." ] || [ "$p" = "" ]; then
path_ok=0
fi
if [ -d "$p" ]; then
perms=$(stat -c "%a" "$p" 2>/dev/null)
# Check if permissions end with 2, 3, 6, or 7 (group/other writable)
case "$perms" in
*[2367]) path_ok=0 ;;
esac
fi
done
IFS="$oldIFS"
if [ $path_ok -eq 1 ]; then
output_result "6.2.7" "Đảm bảo tính toàn vẹn cho biến môi trường PATH của root" "PASSED"
else
output_result "6.2.7" "Đảm bảo tính toàn vẹn cho biến môi trường PATH của root" "FAILED"
fi
# 6.2.8 Root is the only UID 0 account
uid0_count=$(awk -F: '($3 == 0) {print $1}' /etc/passwd 2>/dev/null | wc -l)
if [ "$uid0_count" -eq 1 ]; then
output_result "6.2.8" "Đảm bảo root là tài khoản duy nhất có UID là 0" "PASSED"
else
output_result "6.2.8" "Đảm bảo root là tài khoản duy nhất có UID là 0" "FAILED"
fi
# 6.2.9 All users have home directories
home_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ "$uid" -ge 1000 ] && [ "$shell" != "/sbin/nologin" ] && [ "$shell" != "/bin/false" ]; then
if [ ! -d "$home" ]; then
home_ok=0
fi
fi
done < /etc/passwd 2>/dev/null
if [ $home_ok -eq 1 ]; then
output_result "6.2.9" "Đảm bảo mọi người dùng đều tồn tại thư mục home" "PASSED"
else
output_result "6.2.9" "Đảm bảo mọi người dùng đều tồn tại thư mục home" "FAILED"
fi
# 6.2.10 Users own their home directories
home_owner_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ "$uid" -ge 1000 ] && [ -d "$home" ]; then
owner=$(stat -c "%U" "$home" 2>/dev/null)
if [ "$owner" != "$user" ]; then
home_owner_ok=0
fi
fi
done < /etc/passwd 2>/dev/null
if [ $home_owner_ok -eq 1 ]; then
output_result "6.2.10" "Đảm bảo người dùng sở hữu thư mục home của chính họ" "PASSED"
else
output_result "6.2.10" "Đảm bảo người dùng sở hữu thư mục home của chính họ" "FAILED"
fi
# 6.2.11 Home directory permissions
home_perms_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ "$uid" -ge 1000 ] && [ -d "$home" ]; then
perms=$(stat -c "%a" "$home" 2>/dev/null)
if [ "$perms" -gt 750 ] 2>/dev/null; then
home_perms_ok=0
fi
fi
done < /etc/passwd 2>/dev/null
if [ $home_perms_ok -eq 1 ]; then
output_result "6.2.11" "Đảm bảo quyền thư mục home của người dùng có mức bảo mật cao" "PASSED"
else
output_result "6.2.11" "Đảm bảo quyền thư mục home của người dùng có mức bảo mật cao" "FAILED"
fi
# 6.2.12 User dot files permissions
dot_files_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ "$uid" -ge 1000 ] && [ -d "$home" ]; then
for dotfile in "$home"/.*; do
if [ -f "$dotfile" ]; then
perms=$(stat -c "%a" "$dotfile" 2>/dev/null)
# Check if group or other has write permission
case "$perms" in
*[2367]|?[2367]?) dot_files_ok=0 ;;
esac
fi
done
fi
done < /etc/passwd 2>/dev/null
if [ $dot_files_ok -eq 1 ]; then
output_result "6.2.12" "Đảm bảo các file dot của người dùng không cấp quyền write cho group hoặc other" "PASSED"
else
output_result "6.2.12" "Đảm bảo các file dot của người dùng không cấp quyền write cho group hoặc other" "FAILED"
fi
# 6.2.13 No .forward files
forward_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ -f "$home/.forward" ]; then
forward_ok=0
fi
done < /etc/passwd 2>/dev/null
if [ $forward_ok -eq 1 ]; then
output_result "6.2.13" "Đảm bảo không người dùng nào có file .forward" "PASSED"
else
output_result "6.2.13" "Đảm bảo không người dùng nào có file .forward" "FAILED"
fi
# 6.2.14 No .netrc files
netrc_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ -f "$home/.netrc" ]; then
netrc_ok=0
fi
done < /etc/passwd 2>/dev/null
if [ $netrc_ok -eq 1 ]; then
output_result "6.2.14" "Đảm bảo không người dùng nào có file .netrc" "PASSED"
else
output_result "6.2.14" "Đảm bảo không người dùng nào có file .netrc" "FAILED"
fi
# 6.2.15 No .rhosts files
rhosts_ok=1
while IFS=: read -r user pass uid gid gecos home shell; do
if [ -f "$home/.rhosts" ]; then
rhosts_ok=0
fi
done < /etc/passwd 2>/dev/null
if [ $rhosts_ok -eq 1 ]; then
output_result "6.2.15" "Đảm bảo không người dùng nào có file .rhosts" "PASSED"
else
output_result "6.2.15" "Đảm bảo không người dùng nào có file .rhosts" "FAILED"
fi
############################################################################
# SUMMARY
############################################################################
echo ""
echo "############################################################################"
echo "# Audit completed at: $(date +"%Y-%m-%d %H:%M:%S")"
echo "############################################################################"