From 1a7cfaf42f0c5e14798430858ac2a058290e463b Mon Sep 17 00:00:00 2001 From: Dave Fatkin Date: Sat, 14 Dec 2024 15:55:38 +0000 Subject: [PATCH 1/4] Check SSH config overrides Checks the base sshd_config file for the `Include` directive. Then checks each setting against the overrides first, then the base sshd_config. Will stop at the first instance of the setting found. --- vps-audit.sh | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/vps-audit.sh b/vps-audit.sh index f32d4e4..b57fa6c 100755 --- a/vps-audit.sh +++ b/vps-audit.sh @@ -110,22 +110,33 @@ else check_security "System Restart" "PASS" "No restart required" fi +# Check SSH config overrides +SSH_OVERRIDES=$(grep "^Include" /etc/ssh/sshd_config | awk '{print $2}') + # Check SSH root login -if grep -q "^PermitRootLogin.*no" /etc/ssh/sshd_config; then +SSH_ROOT=$(grep "^PermitRootLogin" $SSH_OVERRIDES /etc/ssh/sshd_config | head -1 | awk '{print $2}') +if [ -z "$SSH_ROOT" ]; then + SSH_ROOT="prohibit-password" +fi +if [ "$SSH_ROOT" = "no" ]; then check_security "SSH Root Login" "PASS" "Root login is properly disabled in SSH configuration" else check_security "SSH Root Login" "FAIL" "Root login is currently allowed - this is a security risk. Disable it in /etc/ssh/sshd_config" fi # Check SSH password authentication -if grep -q "^PasswordAuthentication.*no" /etc/ssh/sshd_config; then +SSH_PASSWORD=$(grep "^PasswordAuthentication" $SSH_OVERRIDES /etc/ssh/sshd_config | head -1 | awk '{print $2}') +if [ -z "$SSH_PASSWORD" ]; then + SSH_PASSWORD="yes" +fi +if [ "$SSH_PASSWORD" = "no" ]; then check_security "SSH Password Auth" "PASS" "Password authentication is disabled, key-based auth only" else check_security "SSH Password Auth" "FAIL" "Password authentication is enabled - consider using key-based authentication only" fi # Check SSH default port -SSH_PORT=$(grep "^Port" /etc/ssh/sshd_config | awk '{print $2}') +SSH_PORT=$(grep "^Port" $SSH_OVERRIDES /etc/ssh/sshd_config | head -1 | awk '{print $2}') if [ -z "$SSH_PORT" ]; then SSH_PORT="22" fi @@ -307,4 +318,4 @@ echo -e "Review $REPORT_FILE for detailed recommendations." # Add summary to report echo "================================" >> "$REPORT_FILE" echo "End of VPS Audit Report" >> "$REPORT_FILE" -echo "Please review all failed checks and implement the recommended fixes." >> "$REPORT_FILE" \ No newline at end of file +echo "Please review all failed checks and implement the recommended fixes." >> "$REPORT_FILE" From e52459b719a14ee13830dff62e1b6a18257a7dc3 Mon Sep 17 00:00:00 2001 From: Israel Abebe Date: Sat, 14 Dec 2024 23:00:34 +0300 Subject: [PATCH 2/4] handle cases where sshd_config.d override is missing --- vps-audit.sh | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/vps-audit.sh b/vps-audit.sh index b57fa6c..7380e6c 100755 --- a/vps-audit.sh +++ b/vps-audit.sh @@ -111,10 +111,14 @@ else fi # Check SSH config overrides -SSH_OVERRIDES=$(grep "^Include" /etc/ssh/sshd_config | awk '{print $2}') +SSH_CONFIG_OVERRIDES=$(grep "^Include" /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}') -# Check SSH root login -SSH_ROOT=$(grep "^PermitRootLogin" $SSH_OVERRIDES /etc/ssh/sshd_config | head -1 | awk '{print $2}') +# Check SSH root login (handle both main config and overrides if they exist) +if [ -n "$SSH_CONFIG_OVERRIDES" ] && [ -d "$(dirname "$SSH_CONFIG_OVERRIDES")" ]; then + SSH_ROOT=$(grep "^PermitRootLogin" $SSH_CONFIG_OVERRIDES /etc/ssh/sshd_config 2>/dev/null | head -1 | awk '{print $2}') +else + SSH_ROOT=$(grep "^PermitRootLogin" /etc/ssh/sshd_config 2>/dev/null | head -1 | awk '{print $2}') +fi if [ -z "$SSH_ROOT" ]; then SSH_ROOT="prohibit-password" fi @@ -124,8 +128,12 @@ else check_security "SSH Root Login" "FAIL" "Root login is currently allowed - this is a security risk. Disable it in /etc/ssh/sshd_config" fi -# Check SSH password authentication -SSH_PASSWORD=$(grep "^PasswordAuthentication" $SSH_OVERRIDES /etc/ssh/sshd_config | head -1 | awk '{print $2}') +# Check SSH password authentication (handle both main config and overrides if they exist) +if [ -n "$SSH_CONFIG_OVERRIDES" ] && [ -d "$(dirname "$SSH_CONFIG_OVERRIDES")" ]; then + SSH_PASSWORD=$(grep "^PasswordAuthentication" $SSH_CONFIG_OVERRIDES /etc/ssh/sshd_config 2>/dev/null | head -1 | awk '{print $2}') +else + SSH_PASSWORD=$(grep "^PasswordAuthentication" /etc/ssh/sshd_config 2>/dev/null | head -1 | awk '{print $2}') +fi if [ -z "$SSH_PASSWORD" ]; then SSH_PASSWORD="yes" fi @@ -136,7 +144,11 @@ else fi # Check SSH default port -SSH_PORT=$(grep "^Port" $SSH_OVERRIDES /etc/ssh/sshd_config | head -1 | awk '{print $2}') +if [ -n "$SSH_CONFIG_OVERRIDES" ] && [ -d "$(dirname "$SSH_CONFIG_OVERRIDES")" ]; then + SSH_PORT=$(grep "^Port" $SSH_CONFIG_OVERRIDES /etc/ssh/sshd_config 2>/dev/null | head -1 | awk '{print $2}') +else + SSH_PORT=$(grep "^Port" /etc/ssh/sshd_config 2>/dev/null | head -1 | awk '{print $2}') +fi if [ -z "$SSH_PORT" ]; then SSH_PORT="22" fi From 04f6bd9429097cfb7f9655d87309a29cbaf1323d Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 14 Dec 2024 12:59:44 -0800 Subject: [PATCH 3/4] Update vps-audit.sh Feature: Added support for ss when netstat is not present --- vps-audit.sh | 54 ++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/vps-audit.sh b/vps-audit.sh index f32d4e4..7bae848 100755 --- a/vps-audit.sh +++ b/vps-audit.sh @@ -188,21 +188,32 @@ else check_security "Running Services" "FAIL" "Too many services running ($SERVICES) - increases attack surface" fi -# Check ports -LISTENING_PORTS=$(netstat -tuln | grep LISTEN) -PORT_COUNT=$(echo "$LISTENING_PORTS" | wc -l) +# Check ports using netstat or ss +if command -v netstat >/dev/null 2>&1; then + LISTENING_PORTS=$(netstat -tuln | grep LISTEN | awk '{print $4}') +elif command -v ss >/dev/null 2>&1; then + LISTENING_PORTS=$(ss -tuln | grep LISTEN | awk '{print $5}') +else + check_security "Port Scanning" "FAIL" "Neither 'netstat' nor 'ss' is available on this system." + LISTENING_PORTS="" +fi -# Get list of internet-accessible ports, excluding those explicitly denied by UFW -PUBLIC_PORTS=$(netstat -tuln | grep LISTEN | \ - awk '$4 !~ /127.0.0.1|::1/ && ($4 ~ /0.0.0.0/ || $4 ~ /::/)' | \ - awk '{split($4, a, ":"); print a[length(a)]}' | sort -n | while read port; do - # Skip ports that are explicitly denied in UFW - if ! ufw status | grep -q "^$port.*DENY"; then - echo "$port" - fi - done | tr '\n' ',' | sed 's/,$//') +# Process LISTENING_PORTS to extract unique public ports +if [ -n "$LISTENING_PORTS" ]; then + PUBLIC_PORTS=$(echo "$LISTENING_PORTS" | awk -F':' '{print $NF}' | sort -n | uniq) + PORT_COUNT=$(echo "$PUBLIC_PORTS" | wc -w) + INTERNET_PORTS=$(echo "$PUBLIC_PORTS" | wc -w) -INTERNET_PORTS=$(echo "$PUBLIC_PORTS" | tr ',' '\n' | wc -l) + if [ "$PORT_COUNT" -lt 10 ] && [ "$INTERNET_PORTS" -lt 3 ]; then + check_security "Port Security" "PASS" "Good configuration (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS" + elif [ "$PORT_COUNT" -lt 20 ] && [ "$INTERNET_PORTS" -lt 5 ]; then + check_security "Port Security" "WARN" "Review recommended (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS" + else + check_security "Port Security" "FAIL" "High exposure (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS" + fi +else + check_security "Port Scanning" "WARN" "Port scanning failed due to missing tools. Ensure 'ss' or 'netstat' is installed." +fi # Function to format the message with proper indentation for the report file format_for_report() { @@ -210,21 +221,6 @@ format_for_report() { echo "$message" >> "$REPORT_FILE" } -# Evaluate security based on both total ports and internet-accessible ports -if [ "$PORT_COUNT" -lt 10 ] && [ "$INTERNET_PORTS" -lt 3 ]; then - RESULT="${GREEN}[PASS]${NC} Port Security ${GRAY}- Good configuration (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS${NC}" - echo -e "$RESULT" - format_for_report "[PASS] Port Security - Good configuration (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS" -elif [ "$PORT_COUNT" -lt 20 ] && [ "$INTERNET_PORTS" -lt 5 ]; then - RESULT="${YELLOW}[WARN]${NC} Port Security ${GRAY}- Review recommended (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS${NC}" - echo -e "$RESULT" - format_for_report "[WARN] Port Security - Review recommended (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS" -else - RESULT="${RED}[FAIL]${NC} Port Security ${GRAY}- High exposure (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS${NC}" - echo -e "$RESULT" - format_for_report "[FAIL] Port Security - High exposure (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS" -fi - # Check disk space usage DISK_TOTAL=$(df -h / | awk 'NR==2 {print $2}') DISK_USED=$(df -h / | awk 'NR==2 {print $3}') @@ -307,4 +303,4 @@ echo -e "Review $REPORT_FILE for detailed recommendations." # Add summary to report echo "================================" >> "$REPORT_FILE" echo "End of VPS Audit Report" >> "$REPORT_FILE" -echo "Please review all failed checks and implement the recommended fixes." >> "$REPORT_FILE" \ No newline at end of file +echo "Please review all failed checks and implement the recommended fixes." >> "$REPORT_FILE" From d215330cdd287cc9b14d825f903681b6146e82ab Mon Sep 17 00:00:00 2001 From: Israel Abebe Date: Sun, 15 Dec 2024 06:03:12 +0300 Subject: [PATCH 4/4] improve open ports formatting --- vps-audit.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vps-audit.sh b/vps-audit.sh index 7bae848..2c75f05 100755 --- a/vps-audit.sh +++ b/vps-audit.sh @@ -200,9 +200,9 @@ fi # Process LISTENING_PORTS to extract unique public ports if [ -n "$LISTENING_PORTS" ]; then - PUBLIC_PORTS=$(echo "$LISTENING_PORTS" | awk -F':' '{print $NF}' | sort -n | uniq) - PORT_COUNT=$(echo "$PUBLIC_PORTS" | wc -w) - INTERNET_PORTS=$(echo "$PUBLIC_PORTS" | wc -w) + PUBLIC_PORTS=$(echo "$LISTENING_PORTS" | awk -F':' '{print $NF}' | sort -n | uniq | tr '\n' ',' | sed 's/,$//') + PORT_COUNT=$(echo "$PUBLIC_PORTS" | tr ',' '\n' | wc -w) + INTERNET_PORTS=$(echo "$PUBLIC_PORTS" | tr ',' '\n' | wc -w) if [ "$PORT_COUNT" -lt 10 ] && [ "$INTERNET_PORTS" -lt 3 ]; then check_security "Port Security" "PASS" "Good configuration (Total: $PORT_COUNT, Public: $INTERNET_PORTS accessible ports): $PUBLIC_PORTS"