The script checks CIS recommendations from Sections 1 to 7, including system setup, services, networking, firewall configuration, access control, logging, and file permissions.
Requirements:
Script must run as root because many system files and settings require elevated permissions.
Output should be written to a log file and a JSON file for reporting.
Each check should show one of the following results:
- PASS – configuration is correct
- FAIL – configuration does not meet CIS recommendation
- MANUAL – requires manual verification
1. Initial Setup:
The script verifies that important security packages are installed and running.
Examples:
The script verifies that important security packages are installed and running.
Examples:
- AIDE for file integrity monitoring
- Chrony for time synchronization
2.Services
Checks that unnecessary services are disabled. These services can increase the attack surface if they are not required.
Examples checked:
Checks that unnecessary services are disabled. These services can increase the attack surface if they are not required.
Examples checked:
- autofs
- avahi-daemon
- telnet
- vsftpd
- rpcbind
- snmpd
3.Network Security
Validates kernel network parameters using sysctl settings.
These settings help protect the system against common network attacks.
Examples:
Validates kernel network parameters using sysctl settings.
These settings help protect the system against common network attacks.
Examples:
- IP forwarding disabled
- ICMP redirect protection
- TCP SYN cookies enabled
- Source route protection
4.Firewall
Ensures that firewall protection is enabled.
Checks include:
Ensures that firewall protection is enabled.
Checks include:
- nftables package installed
- firewalld service enabled
5.Access Control
Validates secure configuration of user access and SSH settings.
Checks include:
Validates secure configuration of user access and SSH settings.
Checks include:
- sudo package installed
- SSH configuration file permissions
- Root login disabled via SSH
- MaxAuthTries configured
- ClientAliveInterval configured
6.Logging and Auditing
Ensures logging and auditing services are available.
Checks include:
Ensures logging and auditing services are available.
Checks include:
- audit package installed
- auditd service enabled
- rsyslog service enabled
7.File Permissions
Checks permissions for critical system files.
Files verified:
Checks permissions for critical system files.
Files verified:
- /etc/passwd
- /etc/shadow
- /etc/group
- /etc/gshadow
- world-writable files on the system
- existence of home directories for regular users
- SUID files (manual review required)
Output:
The script generates two reports:
Log file
/var/log/cis_rhel9_report.log
Contains human-readable scan results.
The script generates two reports:
Log file
/var/log/cis_rhel9_report.log
Contains human-readable scan results.
JSON report
/var/log/cis_rhel9_report.json
Can be used for integration with monitoring tools or automation systems.
Summary:
After the scan completes, the script prints a summary showing:
- number of passed checks
- number of failed checks
- number of manual checks required
Usage:
Script:
-------------------------------------------------------------------------------------------------------------------------
#!/bin/bash
# Enterprise CIS RHEL 9 Compliance Scanner
# Sections CIS 1–7 Coverage
# Output: Log + JSON
# Author: adminCtrlX
# --------------------------
# ROOT CHECK
if [ "$EUID" -ne 0 ]; then
echo "Error: Run this script as root (sudo)."
exit 1
fi
# --------------------------
# CONFIG & FILES
# --------------------------
REPORT="/var/log/cis_rhel9_report.log"
JSON="/var/log/cis_rhel9_report.json"
COL_WIDTH=50
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Initialize Files
> $REPORT
echo "[" > $JSON
PASS=0
FAIL=0
MANUAL=0
FIRST_ENTRY=true
# --------------------------
# LOGGER FUNCTIONS
# --------------------------
log_json() {
local check="$1"
local status="$2"
if [ "$FIRST_ENTRY" = true ]; then
echo " {\"check\":\"$check\", \"status\":\"$status\"}" >> $JSON
FIRST_ENTRY=false
else
# Prepend comma to the previous line to ensure valid JSON array
sed -i '$ s/$/ ,/' $JSON
echo " {\"check\":\"$check\", \"status\":\"$status\"}" >> $JSON
fi
}
pass() {
printf "${GREEN}[PASS]${NC} %-${COL_WIDTH}s\n" "$1" | tee -a $REPORT
log_json "$1" "PASS"
((PASS++))
}
fail() {
printf "${RED}[FAIL]${NC} %-${COL_WIDTH}s\n" "$1" | tee -a $REPORT
log_json "$1" "FAIL"
((FAIL++))
}
manual() {
printf "${YELLOW}[WARN]${NC} %-${COL_WIDTH}s\n" "$1" | tee -a $REPORT
log_json "$1" "MANUAL"
((MANUAL++))
}
# --------------------------
# FUNCTIONS
# --------------------------
check_pkg() {
rpm -q "$1" &>/dev/null && pass "Package $1 is installed" || fail "Package $1 is missing"
}
check_service_disabled() {
if systemctl is-enabled "$1" 2>/dev/null | grep -q 'enabled'; then
fail "Service $1 should be disabled"
else
pass "Service $1 is disabled/not found"
fi
}
check_service_enabled() {
systemctl is-enabled "$1" &>/dev/null && pass "Service $1 is enabled" || fail "Service $1 is NOT enabled"
}
check_perm() {
[ ! -e "$1" ] && { fail "$1 missing"; return; }
local current=$(stat -c "%a" "$1")
# Matches exact or more restrictive permissions
[ "$current" -le "$2" ] && pass "$1 perm is $current (<= $2)" || fail "$1 perm is $current (expected $2)"
}
check_sysctl() {
local val=$(sysctl -n "$1" 2>/dev/null)
[ "$val" = "$2" ] && pass "Sysctl $1 is $2" || fail "Sysctl $1 is $val (expected $2)"
}
# --------------------------
# EXECUTION
# --------------------------
echo -e "${BLUE}Starting CIS RHEL 9 Compliance Scan...${NC}\n"
# SECTION 1: INITIAL SETUP
echo -e "${BLUE}--- SECTION 1: INITIAL SETUP ---${NC}"
check_pkg aide
check_pkg chrony
check_service_enabled chronyd
manual "Confirm System Registration (subscription-manager status)"
# SECTION 2: SERVICES
echo -e "${BLUE}--- SECTION 2: SERVICES ---${NC}"
for s in autofs avahi-daemon dhcpd dnsmasq smb vsftpd telnet tftp rpcbind nfs-server snmpd; do
check_service_disabled "$s"
done
check_service_enabled crond
# SECTION 3: NETWORK
echo -e "${BLUE}--- SECTION 3: NETWORK ---${NC}"
check_service_disabled bluetooth
check_sysctl net.ipv4.ip_forward 0
check_sysctl net.ipv4.conf.all.send_redirects 0
check_sysctl net.ipv4.icmp_ignore_bogus_error_responses 1
check_sysctl net.ipv4.tcp_syncookies 1
# SECTION 4: FIREWALL
echo -e "${BLUE}--- SECTION 4: FIREWALL ---${NC}"
check_pkg nftables
check_service_enabled firewalld
# SECTION 5: ACCESS CONTROL
echo -e "${BLUE}--- SECTION 5: ACCESS CONTROL ---${NC}"
check_pkg sudo
SSH_CONF="/etc/ssh/sshd_config"
if [ -f "$SSH_CONF" ]; then
check_perm "$SSH_CONF" 600
grep -Ei "^\s*PermitRootLogin\s+no" "$SSH_CONF" >/dev/null && pass "SSH: Root login disabled" || fail "SSH: Root login enabled"
grep -Ei "^\s*MaxAuthTries\s+[0-4]" "$SSH_CONF" >/dev/null && pass "SSH: MaxAuthTries compliant" || fail "SSH: MaxAuthTries > 4"
else
fail "SSH config not found"
fi
# Password Policy
grep -E "^PASS_MAX_DAYS\s+[0-9]+" /etc/login.defs | awk '{if($2<=365) exit 0; else exit 1}' && pass "Pass Max Days <= 365" || fail "Pass Max Days > 365"
# SECTION 6: LOGGING
echo -e "${BLUE}--- SECTION 6: LOGGING ---${NC}"
check_pkg audit
check_service_enabled auditd
check_pkg rsyslog
# SECTION 7: SYSTEM PERMISSIONS
echo -e "${BLUE}--- SECTION 7: SYSTEM PERMISSIONS ---${NC}"
check_perm /etc/passwd 644
check_perm /etc/shadow 600
check_perm /etc/group 644
check_perm /etc/gshadow 600
# World Writable Check
WW_FILES=$(find / -xdev -type f -perm -0002 2>/dev/null | wc -l)
[ "$WW_FILES" -eq 0 ] && pass "No world-writable files" || fail "$WW_FILES world-writable files found"
# --------------------------
# FINISH
# --------------------------
echo "]" >> $JSON
echo -e "\n${BLUE}===== SCAN SUMMARY =====${NC}"
echo -e "${GREEN}PASS: $PASS${NC}"
echo -e "${RED}FAIL: $FAIL${NC}"
echo -e "${YELLOW}MANUAL: $MANUAL${NC}"
echo "--------------------------"
echo "Detailed Logs: $REPORT"
echo "JSON Export: $JSON"
-------------------------------------------------------------------------------------------------------------------------
Run the script with root privileges:
$ sudo ./cis_rhel9_scan.sh
The results can then be reviewed to identify security gaps and plan remediation actions.
Run the script with root privileges:
$ sudo ./cis_rhel9_scan.sh
The results can then be reviewed to identify security gaps and plan remediation actions.
No comments:
Post a Comment