#!/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 -q "$package" >/dev/null 2>&1 || rpm -qa | grep -qi "^$package" } # Function to check package not installed check_package_not_installed() { local package="$1" ! (rpm -q "$package" >/dev/null 2>&1 || rpm -qa | grep -qi "^$package") } # 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 RHEL version RHEL_VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/system-release 2>/dev/null | head -1 | cut -d. -f1) echo "RHEL Version Detected: $RHEL_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.1.6 Disable automounting if check_package_not_installed "autofs" && check_service_disabled "autofs"; then output_result "1.1.6" "Cấu hình vô hiệu hoá automounting" "PASSED" else output_result "1.1.6" "Cấu hình vô hiệu hoá automounting" "FAILED" fi # 1.1.7 Disable USB storage if check_module_disabled "usb-storage"; then output_result "1.1.7" "Cấu hình vô hiệu hoá usb storage" "PASSED" else output_result "1.1.7" "Cấu hình vô hiệu hoá usb storage" "FAILED" fi ############################################################################ # 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 [ "$RHEL_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 (RHEL 6 only) if [ "$RHEL_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 (RHEL 6 only) if [ "$RHEL_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 chronyd 2>/dev/null | grep -q "^active" || \ 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 (RHEL 6 only) if [ "$RHEL_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 RHEL 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 # 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") } ') if [ $fw_default_deny -eq 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 -qE '^\s*\$FileCreateMode' /etc/rsyslog.conf /etc/rsyslog.d/*.conf 2>/dev/null; then mode=$(grep -hE '^\s*\$FileCreateMode' /etc/rsyslog.conf /etc/rsyslog.d/*.conf 2>/dev/null | tail -1 | awk '{print $2}' | tr -d '"') 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 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 -qE "^[0-7][0-5][0-5]: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") 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*(readonly\s+|export\s+|typeset\s+-r\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) 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 bad_home_owners=() while IFS=: read -r user pass uid gid gecos home shell; do if [ "$uid" -ge 1000 ] && [ "$user" != "nobody" ] && [ "$user" != "nfsnobody" ] && \ [ "$shell" != "/sbin/nologin" ] && [ "$shell" != "/usr/sbin/nologin" ] && [ "$shell" != "/bin/false" ] && \ [ -d "$home" ]; then owner=$(stat -c "%U" "$home" 2>/dev/null) if [ "$owner" != "$user" ]; then home_owner_ok=0 bad_home_owners+=("User '$user' có home '$home' thuộc sở hữu bởi '$owner'") 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" for msg in "${bad_home_owners[@]}"; do echo "# Cảnh báo: $msg" done 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 "############################################################################"