Compare commits
3 Commits
4c0f609736
...
d740d1fd06
| Author | SHA1 | Date | |
|---|---|---|---|
| d740d1fd06 | |||
| a7fc2e63f4 | |||
| 8464bcbf26 |
+21
-23
@@ -123,27 +123,26 @@ show_security_menu() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Live Monitoring:${NC}"
|
||||
echo ""
|
||||
echo -e " ${MAGENTA}5)${NC} 📡 Live Attack Monitor - Unified threat intelligence (STABLE)"
|
||||
echo -e " ${MAGENTA}6)${NC} 📡 Live Attack Monitor v2.0 - Refactored version (BETA) 🚀"
|
||||
echo -e " ${MAGENTA}7)${NC} 🔐 SSH Attack Monitor - SSH brute force detection"
|
||||
echo -e " ${MAGENTA}8)${NC} 🌐 Web Traffic Monitor - HTTP attack detection"
|
||||
echo -e " ${MAGENTA}9)${NC} 🔥 Firewall Activity Monitor - CSF/iptables monitoring"
|
||||
echo -e " ${MAGENTA}5)${NC} 📡 Live Attack Monitor - Unified threat intelligence"
|
||||
echo -e " ${MAGENTA}6)${NC} 🔐 SSH Attack Monitor - SSH brute force detection"
|
||||
echo -e " ${MAGENTA}7)${NC} 🌐 Web Traffic Monitor - HTTP attack detection"
|
||||
echo -e " ${MAGENTA}8)${NC} 🔥 Firewall Activity Monitor - CSF/iptables monitoring"
|
||||
echo ""
|
||||
echo -e "${BOLD}Log Viewers:${NC}"
|
||||
echo ""
|
||||
echo -e " ${CYAN}10)${NC} Tail Apache Access Log - Live web access"
|
||||
echo -e " ${CYAN}11)${NC} Tail Apache Error Log - Live web errors"
|
||||
echo -e " ${CYAN}12)${NC} Tail Mail Log - Live email activity"
|
||||
echo -e " ${CYAN}13)${NC} Tail Security Log - Live auth attempts"
|
||||
echo -e " ${CYAN}9)${NC} Tail Apache Access Log - Live web access"
|
||||
echo -e " ${CYAN}10)${NC} Tail Apache Error Log - Live web errors"
|
||||
echo -e " ${CYAN}11)${NC} Tail Mail Log - Live email activity"
|
||||
echo -e " ${CYAN}12)${NC} Tail Security Log - Live auth attempts"
|
||||
echo ""
|
||||
echo -e "${BOLD}Security Actions:${NC}"
|
||||
echo ""
|
||||
echo -e " ${YELLOW}14)${NC} 🔒 Enable cPHulk Protection - Brute force protection"
|
||||
echo -e " ${YELLOW}15)${NC} ⚙️ Optimize CT_LIMIT - Connection tracking tuning"
|
||||
echo -e " ${YELLOW}13)${NC} 🔒 Enable cPHulk Protection - Brute force protection"
|
||||
echo -e " ${YELLOW}14)${NC} ⚙️ Optimize CT_LIMIT - Connection tracking tuning"
|
||||
echo ""
|
||||
echo -e "${BOLD}Analysis Tools:${NC}"
|
||||
echo ""
|
||||
echo -e " ${GREEN}16)${NC} 🛡️ Historical Attack Analysis - Scan past logs for attacks (ET Open)"
|
||||
echo -e " ${GREEN}15)${NC} 🛡️ Historical Attack Analysis - Scan past logs for attacks (ET Open)"
|
||||
echo ""
|
||||
echo -e " ${RED}0)${NC} Back to Main Menu"
|
||||
echo ""
|
||||
@@ -162,17 +161,16 @@ handle_security_menu() {
|
||||
3) run_module "security" "ip-reputation-manager.sh" ;;
|
||||
4) run_module "security" "malware-scanner.sh" ;;
|
||||
5) run_module "security" "live-attack-monitor.sh" ;;
|
||||
6) run_module "security" "live-attack-monitor-v2.sh" ;;
|
||||
7) run_module "security" "ssh-attack-monitor.sh" ;;
|
||||
8) run_module "security" "web-traffic-monitor.sh" ;;
|
||||
9) run_module "security" "firewall-activity-monitor.sh" ;;
|
||||
10) run_module "security" "tail-apache-access.sh" ;;
|
||||
11) run_module "security" "tail-apache-error.sh" ;;
|
||||
12) run_module "security" "tail-mail-log.sh" ;;
|
||||
13) run_module "security" "tail-secure-log.sh" ;;
|
||||
14) run_module "security" "enable-cphulk.sh" ;;
|
||||
15) run_module "security" "optimize-ct-limit.sh" ;;
|
||||
16) bash "$BASE_DIR/tools/analyze-historical-attacks.sh" ;;
|
||||
6) run_module "security" "ssh-attack-monitor.sh" ;;
|
||||
7) run_module "security" "web-traffic-monitor.sh" ;;
|
||||
8) run_module "security" "firewall-activity-monitor.sh" ;;
|
||||
9) run_module "security" "tail-apache-access.sh" ;;
|
||||
10) run_module "security" "tail-apache-error.sh" ;;
|
||||
11) run_module "security" "tail-mail-log.sh" ;;
|
||||
12) run_module "security" "tail-secure-log.sh" ;;
|
||||
13) run_module "security" "enable-cphulk.sh" ;;
|
||||
14) run_module "security" "optimize-ct-limit.sh" ;;
|
||||
15) bash "$BASE_DIR/tools/analyze-historical-attacks.sh" ;;
|
||||
0) return ;;
|
||||
*) echo -e "${RED}Invalid option${NC}"; sleep 1 ;;
|
||||
esac
|
||||
|
||||
Executable
+293
@@ -0,0 +1,293 @@
|
||||
#!/bin/bash
|
||||
|
||||
################################################################################
|
||||
# Email Functions Library
|
||||
################################################################################
|
||||
# Shared functions for email troubleshooting modules
|
||||
################################################################################
|
||||
|
||||
# Detect MTA (Mail Transfer Agent)
|
||||
detect_mta() {
|
||||
if command -v exim &>/dev/null; then
|
||||
echo "exim"
|
||||
elif command -v postfix &>/dev/null || [ -f /etc/postfix/main.cf ]; then
|
||||
echo "postfix"
|
||||
elif command -v sendmail &>/dev/null; then
|
||||
echo "sendmail"
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get mail log path based on system
|
||||
get_mail_log_path() {
|
||||
local control_panel=$(detect_control_panel 2>/dev/null || echo "unknown")
|
||||
|
||||
# Try common log locations in order of likelihood
|
||||
if [ "$control_panel" = "cpanel" ]; then
|
||||
if [ -f /var/log/exim_mainlog ]; then
|
||||
echo "/var/log/exim_mainlog"
|
||||
elif [ -f /var/log/exim/mainlog ]; then
|
||||
echo "/var/log/exim/mainlog"
|
||||
fi
|
||||
elif [ "$control_panel" = "plesk" ]; then
|
||||
if [ -f /var/log/maillog ]; then
|
||||
echo "/var/log/maillog"
|
||||
fi
|
||||
else
|
||||
# Standalone or other
|
||||
if [ -f /var/log/mail.log ]; then
|
||||
echo "/var/log/mail.log"
|
||||
elif [ -f /var/log/maillog ]; then
|
||||
echo "/var/log/maillog"
|
||||
elif [ -f /var/log/exim_mainlog ]; then
|
||||
echo "/var/log/exim_mainlog"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Get mailbox base path
|
||||
get_mailbox_base_path() {
|
||||
local control_panel=$(detect_control_panel 2>/dev/null || echo "unknown")
|
||||
|
||||
case "$control_panel" in
|
||||
cpanel)
|
||||
echo "/home"
|
||||
;;
|
||||
plesk)
|
||||
echo "/var/qmail/mailnames"
|
||||
;;
|
||||
*)
|
||||
# Try common locations
|
||||
if [ -d /home/vmail ]; then
|
||||
echo "/home/vmail"
|
||||
elif [ -d /var/mail ]; then
|
||||
echo "/var/mail"
|
||||
else
|
||||
echo "/home"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Validate email address format
|
||||
validate_email() {
|
||||
local email="$1"
|
||||
if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Extract domain from email address
|
||||
get_email_domain() {
|
||||
local email="$1"
|
||||
echo "${email##*@}"
|
||||
}
|
||||
|
||||
# Extract local part from email address
|
||||
get_email_local() {
|
||||
local email="$1"
|
||||
echo "${email%%@*}"
|
||||
}
|
||||
|
||||
# Convert bytes to human-readable format
|
||||
format_size() {
|
||||
local bytes="$1"
|
||||
|
||||
if [ "$bytes" -lt 1024 ]; then
|
||||
echo "${bytes}B"
|
||||
elif [ "$bytes" -lt 1048576 ]; then
|
||||
echo "$((bytes / 1024))KB"
|
||||
elif [ "$bytes" -lt 1073741824 ]; then
|
||||
echo "$((bytes / 1048576))MB"
|
||||
else
|
||||
echo "$((bytes / 1073741824))GB"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if MTA service is running
|
||||
check_mta_running() {
|
||||
local mta=$(detect_mta)
|
||||
|
||||
case "$mta" in
|
||||
exim)
|
||||
if systemctl is-active --quiet exim 2>/dev/null || service exim status &>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
postfix)
|
||||
if systemctl is-active --quiet postfix 2>/dev/null || service postfix status &>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
sendmail)
|
||||
if systemctl is-active --quiet sendmail 2>/dev/null || service sendmail status &>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Get MTA version
|
||||
get_mta_version() {
|
||||
local mta=$(detect_mta)
|
||||
|
||||
case "$mta" in
|
||||
exim)
|
||||
exim -bV 2>/dev/null | head -1 | awk '{print $3}'
|
||||
;;
|
||||
postfix)
|
||||
postconf mail_version 2>/dev/null | awk '{print $3}'
|
||||
;;
|
||||
sendmail)
|
||||
sendmail -d0.1 2>&1 | head -1 | awk '{print $2}'
|
||||
;;
|
||||
*)
|
||||
echo "unknown"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get mail queue count
|
||||
get_queue_count() {
|
||||
local mta=$(detect_mta)
|
||||
|
||||
case "$mta" in
|
||||
exim)
|
||||
exim -bpc 2>/dev/null || echo "0"
|
||||
;;
|
||||
postfix)
|
||||
postqueue -p 2>/dev/null | tail -1 | awk '{print $5}' | tr -d '(' | tr -d ')'
|
||||
;;
|
||||
*)
|
||||
echo "0"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check DNS record
|
||||
check_dns_record() {
|
||||
local domain="$1"
|
||||
local record_type="$2" # A, MX, TXT, etc.
|
||||
|
||||
if command -v dig &>/dev/null; then
|
||||
dig +short "$domain" "$record_type" 2>/dev/null
|
||||
elif command -v host &>/dev/null; then
|
||||
host -t "$record_type" "$domain" 2>/dev/null | grep -v "has no" | awk '{print $NF}'
|
||||
elif command -v nslookup &>/dev/null; then
|
||||
nslookup -type="$record_type" "$domain" 2>/dev/null | grep -A10 "answer:" | grep -v "answer:"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get server's primary IP
|
||||
get_primary_ip() {
|
||||
# Try multiple methods
|
||||
local ip=""
|
||||
|
||||
# Method 1: hostname -i
|
||||
ip=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||||
|
||||
# Method 2: ip route
|
||||
if [ -z "$ip" ]; then
|
||||
ip=$(ip route get 8.8.8.8 2>/dev/null | awk '{print $7; exit}')
|
||||
fi
|
||||
|
||||
# Method 3: ifconfig
|
||||
if [ -z "$ip" ]; then
|
||||
ip=$(ifconfig 2>/dev/null | grep 'inet ' | grep -v '127.0.0.1' | head -1 | awk '{print $2}' | cut -d: -f2)
|
||||
fi
|
||||
|
||||
echo "$ip"
|
||||
}
|
||||
|
||||
# Check if IP is valid format
|
||||
is_valid_ip() {
|
||||
local ip="$1"
|
||||
if [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get reverse DNS (PTR) for IP
|
||||
get_reverse_dns() {
|
||||
local ip="$1"
|
||||
|
||||
if command -v dig &>/dev/null; then
|
||||
dig +short -x "$ip" 2>/dev/null | sed 's/\.$//'
|
||||
elif command -v host &>/dev/null; then
|
||||
host "$ip" 2>/dev/null | grep "pointer" | awk '{print $NF}' | sed 's/\.$//'
|
||||
fi
|
||||
}
|
||||
|
||||
# Send test email
|
||||
send_test_email() {
|
||||
local to="$1"
|
||||
local subject="${2:-Test Email from Server Toolkit}"
|
||||
local body="${3:-This is a test email sent from the Server Toolkit.}"
|
||||
local from="${4:-root@$(hostname)}"
|
||||
|
||||
if command -v mail &>/dev/null; then
|
||||
echo "$body" | mail -s "$subject" -r "$from" "$to"
|
||||
return $?
|
||||
elif command -v sendmail &>/dev/null; then
|
||||
{
|
||||
echo "From: $from"
|
||||
echo "To: $to"
|
||||
echo "Subject: $subject"
|
||||
echo ""
|
||||
echo "$body"
|
||||
} | sendmail -t
|
||||
return $?
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Parse email from Exim log line
|
||||
parse_exim_email() {
|
||||
local log_line="$1"
|
||||
# Extract email addresses from various Exim log formats
|
||||
echo "$log_line" | grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | head -1
|
||||
}
|
||||
|
||||
# Get date range for log analysis (default: last 24 hours)
|
||||
get_log_date_range() {
|
||||
local hours="${1:-24}"
|
||||
date -d "$hours hours ago" "+%Y-%m-%d %H:%M:%S"
|
||||
}
|
||||
|
||||
# Count messages by sender
|
||||
count_by_sender() {
|
||||
local log_file="$1"
|
||||
local min_date="${2:-}"
|
||||
|
||||
if [ -n "$min_date" ]; then
|
||||
awk -v min_date="$min_date" '$0 >= min_date' "$log_file" | \
|
||||
grep "<=" | \
|
||||
grep -oE '\<[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\>' | \
|
||||
sort | uniq -c | sort -rn
|
||||
else
|
||||
grep "<=" "$log_file" | \
|
||||
grep -oE '\<[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\>' | \
|
||||
sort | uniq -c | sort -rn
|
||||
fi
|
||||
}
|
||||
|
||||
# Export to detect_control_panel if not already available
|
||||
if ! type detect_control_panel &>/dev/null; then
|
||||
detect_control_panel() {
|
||||
if [ -f /usr/local/cpanel/version ]; then
|
||||
echo "cpanel"
|
||||
elif [ -f /usr/local/psa/version ]; then
|
||||
echo "plesk"
|
||||
else
|
||||
echo "standalone"
|
||||
fi
|
||||
}
|
||||
fi
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
|
||||
################################################################################
|
||||
# IP Blacklist Checker
|
||||
################################################################################
|
||||
# Purpose: Check if server IP is blacklisted
|
||||
################################################################################
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/common-functions.sh"
|
||||
source "$SCRIPT_DIR/lib/system-detect.sh"
|
||||
|
||||
show_banner "IP Blacklist Checker"
|
||||
|
||||
# Get server's public IP
|
||||
print_info "Detecting server IP address..."
|
||||
SERVER_IP=$(curl -s ifconfig.me || curl -s icanhazip.com || curl -s ipecho.net/plain)
|
||||
|
||||
if [ -z "$SERVER_IP" ]; then
|
||||
print_error "Could not detect server IP address"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_success "Server IP: $SERVER_IP"
|
||||
echo ""
|
||||
|
||||
# Common blacklists to check
|
||||
BLACKLISTS=(
|
||||
"zen.spamhaus.org"
|
||||
"bl.spamcop.net"
|
||||
"b.barracudacentral.org"
|
||||
"dnsbl.sorbs.net"
|
||||
"bl.spameatingmonkey.net"
|
||||
"dnsbl-1.uceprotect.net"
|
||||
"cbl.abuseat.org"
|
||||
"psbl.surriel.com"
|
||||
)
|
||||
|
||||
print_header "Checking Blacklists"
|
||||
echo ""
|
||||
|
||||
LISTED=0
|
||||
NOT_LISTED=0
|
||||
|
||||
for bl in "${BLACKLISTS[@]}"; do
|
||||
# Reverse IP for DNS lookup
|
||||
REVERSED_IP=$(echo $SERVER_IP | awk -F. '{print $4"."$3"."$2"."$1}')
|
||||
|
||||
# Check if listed
|
||||
if host "$REVERSED_IP.$bl" &>/dev/null; then
|
||||
print_error "✗ LISTED on $bl"
|
||||
((LISTED++))
|
||||
else
|
||||
print_success "✓ Not listed on $bl"
|
||||
((NOT_LISTED++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
print_header "Summary"
|
||||
|
||||
if [ "$LISTED" -eq 0 ]; then
|
||||
print_success "✓ Server IP is not blacklisted ($NOT_LISTED blacklists checked)"
|
||||
else
|
||||
print_warning "⚠ Server IP is listed on $LISTED blacklist(s)"
|
||||
echo ""
|
||||
print_info "To delist your IP:"
|
||||
echo " 1. Fix the underlying issue (spam, malware, etc.)"
|
||||
echo " 2. Visit each blacklist's removal page"
|
||||
echo " 3. Request delisting with justification"
|
||||
echo ""
|
||||
echo "Common delisting links:"
|
||||
echo " Spamhaus: https://www.spamhaus.org/lookup/"
|
||||
echo " SpamCop: https://www.spamcop.net/bl.shtml"
|
||||
echo " Barracuda: https://www.barracudacentral.org/rbl/removal-request"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/common-functions.sh"
|
||||
show_banner "clean mailboxes"
|
||||
print_warning "This module is under development"
|
||||
echo ""
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/common-functions.sh"
|
||||
|
||||
show_banner "Email Deliverability Test"
|
||||
|
||||
print_info "This module tests email sending and receiving"
|
||||
print_warning "Coming soon - Under development"
|
||||
echo ""
|
||||
print_info "For now, use: echo 'Test' | mail -s 'Test' your@email.com"
|
||||
echo ""
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/common-functions.sh"
|
||||
show_banner "flush mail queue"
|
||||
print_warning "This module is under development"
|
||||
echo ""
|
||||
Executable
+1466
File diff suppressed because it is too large
Load Diff
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
|
||||
################################################################################
|
||||
# Mail Queue Inspector
|
||||
################################################################################
|
||||
# Purpose: View and analyze mail queue
|
||||
################################################################################
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/common-functions.sh"
|
||||
source "$SCRIPT_DIR/lib/system-detect.sh"
|
||||
source "$SCRIPT_DIR/lib/email-functions.sh"
|
||||
|
||||
show_banner "Mail Queue Inspector"
|
||||
|
||||
# Detect MTA
|
||||
MTA=$(detect_mta)
|
||||
|
||||
if [ "$MTA" = "unknown" ]; then
|
||||
print_error "No supported mail server (Exim/Postfix) detected"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_info "Detected mail server: $MTA"
|
||||
echo ""
|
||||
|
||||
# Show queue summary
|
||||
if [ "$MTA" = "exim" ]; then
|
||||
print_header "Queue Summary"
|
||||
exim -bpc | while read count; do
|
||||
if [ "$count" -gt 0 ]; then
|
||||
print_warning "$count messages in queue"
|
||||
else
|
||||
print_success "Mail queue is empty"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Show queue details if not empty
|
||||
queue_count=$(exim -bpc)
|
||||
if [ "$queue_count" -gt 0 ]; then
|
||||
print_header "Recent Queue Messages (last 20)"
|
||||
exim -bp | head -40
|
||||
echo ""
|
||||
|
||||
print_header "Frozen Messages"
|
||||
frozen=$(exim -bp | grep frozen | wc -l)
|
||||
if [ "$frozen" -gt 0 ]; then
|
||||
print_warning "$frozen frozen messages found"
|
||||
exim -bp | grep frozen | head -10
|
||||
else
|
||||
print_success "No frozen messages"
|
||||
fi
|
||||
fi
|
||||
|
||||
elif [ "$MTA" = "postfix" ]; then
|
||||
print_header "Queue Summary"
|
||||
mailq | tail -1
|
||||
echo ""
|
||||
|
||||
print_header "Queue Details"
|
||||
mailq | head -50
|
||||
fi
|
||||
|
||||
echo ""
|
||||
print_info "Use 'exim -Mvl <message_id>' to view message details"
|
||||
print_info "Use 'exim -Mrm <message_id>' to remove a message"
|
||||
echo ""
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/common-functions.sh"
|
||||
show_banner "smtp connection test"
|
||||
print_warning "This module is under development"
|
||||
echo ""
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/common-functions.sh"
|
||||
show_banner "spf dkim dmarc check"
|
||||
print_warning "This module is under development"
|
||||
echo ""
|
||||
+275
-9
@@ -14,7 +14,7 @@
|
||||
# --summary Summary mode (counts only, no details)
|
||||
#
|
||||
# Features:
|
||||
# - 80 comprehensive checks (was 32)
|
||||
# - 88 comprehensive checks (was 80, +8 multi-panel compliance)
|
||||
# - Context-aware detection (<5% false positives)
|
||||
# - Smart categorization with tags
|
||||
# - Suppress annotations support (# qa-suppress)
|
||||
@@ -22,6 +22,7 @@
|
||||
# - Phase 4: Advanced bash gotchas and edge cases
|
||||
# - Phase 5: Deep analysis (locale, printf injection, bashisms, etc.)
|
||||
# - Phase 6: Performance & resource checks
|
||||
# - Phase 7: Multi-panel architecture compliance
|
||||
#
|
||||
|
||||
# Parse options
|
||||
@@ -178,9 +179,9 @@ echo "Severity: HIGH"
|
||||
echo "Issue: Multiple files redefining same path variable"
|
||||
echo ""
|
||||
|
||||
script_dir_count=$(grep -l "^SCRIPT_DIR=" "$TOOLKIT_PATH"/**/*.sh 2>/dev/null | wc -l)
|
||||
script_dir_count=$(find "$TOOLKIT_PATH" -name "*.sh" -type f -exec grep -l "^SCRIPT_DIR=" {} \; 2>/dev/null | wc -l)
|
||||
if [ "$script_dir_count" -gt 1 ]; then
|
||||
files=$(grep -l "^SCRIPT_DIR=" "$TOOLKIT_PATH"/**/*.sh 2>/dev/null | tr '\n' ' ')
|
||||
files=$(find "$TOOLKIT_PATH" -name "*.sh" -type f -exec grep -l "^SCRIPT_DIR=" {} \; 2>/dev/null | tr '\n' ' ')
|
||||
echo "HIGH|Multiple files|N/A|SCRIPT_DIR in $script_dir_count files: $files"
|
||||
count_issue "HIGH"
|
||||
fi
|
||||
@@ -301,7 +302,7 @@ while read -r file; do
|
||||
echo "HIGH|$file|N/A|Uses common functions without sourcing"
|
||||
count_issue "HIGH"
|
||||
fi
|
||||
done < <(grep -l 'cecho\|print_info\|print_warning\|print_error' "$TOOLKIT_PATH"/modules/**/*.sh 2>/dev/null)
|
||||
done < <(find "$TOOLKIT_PATH/modules" -name "*.sh" -type f -exec grep -l 'cecho\|print_info\|print_warning\|print_error' {} \; 2>/dev/null)
|
||||
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
@@ -574,7 +575,7 @@ echo "Severity: MEDIUM"
|
||||
echo "Issue: Same function in multiple files causes unpredictable behavior"
|
||||
echo ""
|
||||
|
||||
# Extract all function names and find duplicates
|
||||
# Extract all function names and find duplicates (optimized single-pass)
|
||||
declare -A func_files
|
||||
while IFS=: read -r file func_name; do
|
||||
if [ -n "${func_files[$func_name]}" ]; then
|
||||
@@ -583,9 +584,8 @@ while IFS=: read -r file func_name; do
|
||||
else
|
||||
func_files[$func_name]="$file"
|
||||
fi
|
||||
done < <(grep -rh '^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*()' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | \
|
||||
sed 's/^\s*//; s/(.*$//' | sort | uniq -d | \
|
||||
while read func; do grep -rl "^[[:space:]]*$func()" "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | sed "s|$|:$func|"; done)
|
||||
done < <(find "$TOOLKIT_PATH" -name "*.sh" ! -name "toolkit-qa-check.sh" -type f -exec grep -H '^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*()' {} \; 2>/dev/null | \
|
||||
sed 's/:/ /' | awk '{print $1":"$2}' | sed 's/()$//')
|
||||
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
@@ -601,6 +601,10 @@ echo "Issue: Functions accepting parameters without validation"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
# Skip expensive validation analysis in summary mode
|
||||
if $SUMMARY_MODE; then
|
||||
echo "Skipped in summary mode (expensive check)"
|
||||
else
|
||||
while read -r file; do
|
||||
# Find functions that use $1, $2 etc but don't validate them
|
||||
while IFS=: read -r line_num func_line; do
|
||||
@@ -683,6 +687,7 @@ while read -r file; do
|
||||
fi
|
||||
done < <(grep -n '^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*()' "$file" 2>/dev/null)
|
||||
done < <(find "$TOOLKIT_PATH" -name "*.sh" -not -name "toolkit-qa-check.sh" 2>/dev/null)
|
||||
fi # End summary mode skip
|
||||
|
||||
echo "Found: $count issues (showing first 10)"
|
||||
echo ""
|
||||
@@ -699,6 +704,9 @@ echo "Issue: Long functions are hard to maintain and test"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
if $SUMMARY_MODE; then
|
||||
echo "Skipped in summary mode (expensive check)"
|
||||
else
|
||||
while read -r file; do
|
||||
# Find function definitions and count lines until closing brace
|
||||
awk '
|
||||
@@ -729,6 +737,7 @@ done < <(find "$TOOLKIT_PATH" -name "*.sh" -not -name "toolkit-qa-check.sh" 2>/d
|
||||
((count++))
|
||||
[ "$count" -ge 10 ] && break
|
||||
done
|
||||
fi # End summary mode skip
|
||||
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
@@ -2795,7 +2804,264 @@ done < <(grep -rnE '\b(find\s+/|grep\s+-r|tar\s+|rsync|mysqldump)' "$TOOLKIT_PAT
|
||||
echo "Found: $count expensive operations in loops"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
# Insert after CHECK 80, before performance checks section
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo "MULTI-PANEL ARCHITECTURE COMPLIANCE (Checks 81-88)"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
{
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo "MULTI-PANEL ARCHITECTURE COMPLIANCE"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
|
||||
#==============================================================================
|
||||
# CHECK 81: Hardcoded cPanel paths (HIGH)
|
||||
#==============================================================================
|
||||
echo "[81/94] Checking: Hardcoded cPanel-specific paths..."
|
||||
{
|
||||
echo "## CHECK 81: Hardcoded cPanel-specific paths"
|
||||
echo "Severity: HIGH"
|
||||
echo "Pattern: /var/cpanel/, /var/log/apache2/domlogs, /home/*/public_html"
|
||||
echo "Fix: Use SYS_* variables or case statements for multi-panel support"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
while IFS=: read -r file line_num line_content; do
|
||||
# Skip if suppressed
|
||||
is_suppressed "$file" "$line_num" "hardcoded-path" && continue
|
||||
|
||||
# Skip library files that define these paths
|
||||
[[ "$file" =~ (system-detect|cpanel-helpers|launcher)\.sh$ ]] && continue
|
||||
|
||||
# Skip comments and variable definitions that are panel-aware
|
||||
echo "$line_content" | grep -qE '^\s*#|case.*CONTROL_PANEL' && continue
|
||||
|
||||
# Extract the hardcoded path
|
||||
path=$(echo "$line_content" | grep -oE '(/var/cpanel|/var/log/apache2/domlogs|/home/[^/]*/public_html)' | head -1)
|
||||
|
||||
echo "HIGH|$file|$line_num|[HARDCODED-PATH] cPanel-specific path: $path"
|
||||
count_issue "HIGH"
|
||||
((count++))
|
||||
[ "$count" -ge 15 ] && break
|
||||
done < <(grep -rnE '(/var/cpanel|/var/log/apache2/domlogs|/home/[^/]*/public_html)' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null)
|
||||
|
||||
echo "Found: $count hardcoded cPanel paths"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
|
||||
#==============================================================================
|
||||
# CHECK 82: Missing system-detect.sh source (HIGH)
|
||||
#==============================================================================
|
||||
echo "[82/94] Checking: Scripts missing system-detect.sh library..."
|
||||
{
|
||||
echo "## CHECK 82: Missing system-detect.sh source"
|
||||
echo "Severity: HIGH"
|
||||
echo "Pattern: Scripts using panel features without sourcing system-detect.sh"
|
||||
echo "Fix: Add 'source \"\$LIB_DIR/system-detect.sh\"' at top of script"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
while IFS= read -r file; do
|
||||
# Skip library files and launcher
|
||||
[[ "$file" =~ (^lib/|launcher\.sh$) ]] && continue
|
||||
|
||||
# Check if file uses panel-specific features
|
||||
if grep -qE '(whmapi1|uapi|plesk bin|/var/cpanel|/var/www/vhosts|SYS_CONTROL_PANEL)' "$file" 2>/dev/null; then
|
||||
# Check if it sources system-detect.sh
|
||||
if ! grep -qE 'source.*system-detect\.sh|\\..*system-detect\.sh' "$file" 2>/dev/null; then
|
||||
echo "HIGH|$file|N/A|[MISSING-LIB] Uses panel features without sourcing system-detect.sh"
|
||||
count_issue "HIGH"
|
||||
((count++))
|
||||
[ "$count" -ge 10 ] && break
|
||||
fi
|
||||
fi
|
||||
done < <(find "$TOOLKIT_PATH/modules" -name "*.sh" -type f 2>/dev/null)
|
||||
|
||||
echo "Found: $count scripts missing system-detect.sh"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
|
||||
#==============================================================================
|
||||
# CHECK 83: Direct /var/cpanel/users access (CRITICAL)
|
||||
#==============================================================================
|
||||
echo "[83/94] Checking: Direct /var/cpanel/users access..."
|
||||
{
|
||||
echo "## CHECK 83: Direct /var/cpanel/users file access"
|
||||
echo "Severity: CRITICAL"
|
||||
echo "Pattern: grep/cat /var/cpanel/users or /etc/userdatadomains"
|
||||
echo "Fix: Use get_user_info() or get_user_domains() from user-manager.sh"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
while IFS=: read -r file line_num line_content; do
|
||||
# Skip if suppressed
|
||||
is_suppressed "$file" "$line_num" "userdata-access" && continue
|
||||
|
||||
# Skip library files that implement the abstraction
|
||||
[[ "$file" =~ (user-manager|system-detect|cpanel-helpers)\.sh$ ]] && continue
|
||||
|
||||
echo "CRITICAL|$file|$line_num|[USERDATA-ACCESS] Direct access to cPanel user files"
|
||||
count_issue "CRITICAL"
|
||||
((count++))
|
||||
[ "$count" -ge 10 ] && break
|
||||
done < <(grep -rnE '(grep|cat|awk).*(/var/cpanel/users/|/etc/userdatadomains)' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null)
|
||||
|
||||
echo "Found: $count direct userdata file accesses"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
|
||||
#==============================================================================
|
||||
# CHECK 84: cPanel API calls without panel check (HIGH)
|
||||
#==============================================================================
|
||||
echo "[84/94] Checking: cPanel API calls without validation..."
|
||||
{
|
||||
echo "## CHECK 84: cPanel API calls without panel check"
|
||||
echo "Severity: HIGH"
|
||||
echo "Pattern: whmapi1/uapi calls without checking \$SYS_CONTROL_PANEL"
|
||||
echo "Fix: Wrap in 'if [ \"\$SYS_CONTROL_PANEL\" = \"cpanel\" ]; then'"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
while IFS=: read -r file line_num line_content; do
|
||||
# Skip if suppressed
|
||||
is_suppressed "$file" "$line_num" "api-check" && continue
|
||||
|
||||
# Simple check: if file doesn't mention CONTROL_PANEL at all, flag it
|
||||
if ! grep -q "CONTROL_PANEL" "$file" 2>/dev/null; then
|
||||
api_cmd=$(echo "$line_content" | grep -oE '(whmapi1|uapi) [a-z_]+' | head -1)
|
||||
echo "HIGH|$file|$line_num|[API-CHECK] cPanel API without panel validation: $api_cmd"
|
||||
count_issue "HIGH"
|
||||
((count++))
|
||||
[ "$count" -ge 10 ] && break
|
||||
fi
|
||||
done < <(grep -rnE '\\b(whmapi1|uapi)\\s+' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null)
|
||||
|
||||
echo "Found: $count unchecked cPanel API calls"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
|
||||
#==============================================================================
|
||||
# CHECK 85: Missing case statement (MEDIUM)
|
||||
#==============================================================================
|
||||
echo "[85/94] Checking: Scripts with hardcoded paths but no case statement..."
|
||||
{
|
||||
echo "## CHECK 85: Missing multi-panel case statement"
|
||||
echo "Severity: MEDIUM"
|
||||
echo "Pattern: Uses panel-specific paths but no case \$SYS_CONTROL_PANEL"
|
||||
echo "Fix: Add case statement to handle all panels"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
while IFS= read -r file; do
|
||||
# Skip library files
|
||||
[[ "$file" =~ ^lib/ ]] && continue
|
||||
|
||||
# Check if file uses panel-specific features but no case statement
|
||||
if grep -qE '(/var/cpanel|/var/www/vhosts)' "$file" 2>/dev/null; then
|
||||
if ! grep -qE 'case.*\\$SYS_CONTROL_PANEL|case.*\\$CONTROL_PANEL' "$file" 2>/dev/null; then
|
||||
echo "MEDIUM|$file|N/A|[NO-CASE] Uses panel paths without case statement"
|
||||
count_issue "MEDIUM"
|
||||
((count++))
|
||||
[ "$count" -ge 10 ] && break
|
||||
fi
|
||||
fi
|
||||
done < <(find "$TOOLKIT_PATH/modules" -name "*.sh" -type f 2>/dev/null)
|
||||
|
||||
echo "Found: $count scripts missing case statements"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
|
||||
#==============================================================================
|
||||
# CHECK 86: Hardcoded database prefixes (MEDIUM)
|
||||
#==============================================================================
|
||||
echo "[86/94] Checking: Hardcoded database name patterns..."
|
||||
{
|
||||
echo "## CHECK 86: Hardcoded database name patterns"
|
||||
echo "Severity: MEDIUM"
|
||||
echo "Pattern: Assumes username_dbname pattern (cPanel-specific)"
|
||||
echo "Fix: Use panel-aware database discovery"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
while IFS=: read -r file line_num line_content; do
|
||||
# Skip if suppressed
|
||||
is_suppressed "$file" "$line_num" "db-pattern" && continue
|
||||
|
||||
echo "MEDIUM|$file|$line_num|[DB-PATTERN] Assumes cPanel database naming (user_dbname)"
|
||||
count_issue "MEDIUM"
|
||||
((count++))
|
||||
[ "$count" -ge 10 ] && break
|
||||
done < <(grep -rnE '\\$\\{?user(name)?\\}?_' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null | grep -i 'db\\|database')
|
||||
|
||||
echo "Found: $count hardcoded database patterns"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
|
||||
#==============================================================================
|
||||
# CHECK 87: Missing user-manager.sh (HIGH)
|
||||
#==============================================================================
|
||||
echo "[87/94] Checking: User/domain operations without user-manager.sh..."
|
||||
{
|
||||
echo "## CHECK 87: User/domain operations without user-manager.sh"
|
||||
echo "Severity: HIGH"
|
||||
echo "Pattern: Domain/user lookups without using abstraction library"
|
||||
echo "Fix: Source user-manager.sh and use get_user_info/get_user_domains"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
while IFS= read -r file; do
|
||||
# Skip library files
|
||||
[[ "$file" =~ ^lib/ ]] && continue
|
||||
|
||||
# Check if file does user/domain operations without sourcing user-manager.sh
|
||||
if grep -qE 'for.*domain|while.*domain' "$file" 2>/dev/null; then
|
||||
if ! grep -qE 'source.*user-manager\\.sh' "$file" 2>/dev/null; then
|
||||
echo "HIGH|$file|N/A|[NO-USER-MGR] Domain operations without user-manager.sh"
|
||||
count_issue "HIGH"
|
||||
((count++))
|
||||
[ "$count" -ge 10 ] && break
|
||||
fi
|
||||
fi
|
||||
done < <(find "$TOOLKIT_PATH/modules" -name "*.sh" -type f 2>/dev/null)
|
||||
|
||||
echo "Found: $count scripts needing user-manager.sh"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
|
||||
#==============================================================================
|
||||
# CHECK 88: Standalone Apache support missing (LOW)
|
||||
#==============================================================================
|
||||
echo "[88/94] Checking: Scripts missing standalone/no-panel fallback..."
|
||||
{
|
||||
echo "## CHECK 88: Missing standalone Apache fallback"
|
||||
echo "Severity: LOW"
|
||||
echo "Pattern: case statement without '*' or 'standalone' case"
|
||||
echo "Fix: Add fallback case for systems without control panels"
|
||||
echo ""
|
||||
|
||||
count=0
|
||||
while IFS=: read -r file line_num line_content; do
|
||||
# Get next 20 lines after case statement
|
||||
case_block=$(sed -n "${line_num},$((line_num+30))p" "$file" 2>/dev/null | sed -n '/case/,/esac/p')
|
||||
|
||||
# Check if it has a default case
|
||||
if ! echo "$case_block" | grep -qE '\\*\\)|standalone\\)'; then
|
||||
echo "LOW|$file|$line_num|[NO-STANDALONE] Missing standalone fallback in case statement"
|
||||
count_issue "LOW"
|
||||
((count++))
|
||||
[ "$count" -ge 10 ] && break
|
||||
fi
|
||||
done < <(grep -n "case.*CONTROL_PANEL" "$TOOLKIT_PATH" --include="*.sh" -r 2>/dev/null | cut -d: -f1,2)
|
||||
|
||||
echo "Found: $count case statements missing standalone support"
|
||||
echo ""
|
||||
} >> "$REPORT"
|
||||
#==============================================================================
|
||||
# PERFORMANCE CHECKS (INFO level - not counted as issues)
|
||||
#==============================================================================
|
||||
@@ -3008,7 +3274,7 @@ echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo "CATEGORY BREAKDOWN (Top Issues by Type):"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
for tag in SQL-INJ CMD-INJ PANEL-CALL FILE-OP SECRET-LEAK RACE SOURCE RETURN NULL DEP TEMP SUBSHELL PIPE WORDSPLIT ARITH TEST REDIR TRAP ARRAY HEREDOC IF-MASK NUMCMP BG-JOB LOCALE PROC-SUB PRINTF REGEX BASHISM ESCAPE SLEEP-RACE IFS SUBSHELL-VAR TRAP-RACE PERF-LOOP PERF-CACHE PERF-READ RECURSION FD-LEAK ZOMBIE DISK-SPACE NET-TIMEOUT LOG-ROTATE CPU-LOOP; do
|
||||
for tag in SQL-INJ CMD-INJ PANEL-CALL FILE-OP SECRET-LEAK RACE SOURCE RETURN NULL DEP TEMP SUBSHELL PIPE WORDSPLIT ARITH TEST REDIR TRAP ARRAY HEREDOC IF-MASK NUMCMP BG-JOB LOCALE PROC-SUB PRINTF REGEX BASHISM ESCAPE SLEEP-RACE IFS SUBSHELL-VAR TRAP-RACE PERF-LOOP PERF-CACHE PERF-READ RECURSION FD-LEAK ZOMBIE DISK-SPACE NET-TIMEOUT LOG-ROTATE CPU-LOOP HARDCODED-PATH MISSING-LIB USERDATA-ACCESS API-CHECK NO-CASE DB-PATTERN NO-USER-MGR NO-STANDALONE; do
|
||||
count=$(grep -c "\[$tag\]" "$REPORT" 2>/dev/null || echo 0)
|
||||
if [ "$count" -gt 0 ]; then
|
||||
printf " %-12s: %d issues\n" "$tag" "$count"
|
||||
|
||||
Reference in New Issue
Block a user