#!/bin/bash # # Attack Signature Auto-Updater # Downloads latest ET Open rules and extracts HTTP-level attack patterns # # Usage: bash update-attack-signatures.sh # Can be run manually or via cron (weekly recommended) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" LIB_DIR="$SCRIPT_DIR/../lib" BACKUP_DIR="$SCRIPT_DIR/../backups/signatures" TEMP_DIR="/tmp/et-rules-update-$$" # ET Open ruleset URL ET_RULES_URL="https://rules.emergingthreats.net/open/suricata-7.0.0/emerging.rules.tar.gz" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Log function log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Cleanup on exit cleanup() { [ -d "$TEMP_DIR" ] && rm -rf "$TEMP_DIR" } trap cleanup EXIT # Create directories mkdir -p "$BACKUP_DIR" "$TEMP_DIR" echo "========================================" echo "Attack Signature Auto-Updater" echo "Source: Emerging Threats Open Ruleset" echo "========================================" echo "" # Step 1: Backup current signatures log_info "Backing up current signatures..." if [ -f "$LIB_DIR/attack-signatures.sh" ]; then backup_file="$BACKUP_DIR/attack-signatures-$(date +%Y%m%d_%H%M%S).sh" cp "$LIB_DIR/attack-signatures.sh" "$backup_file" log_success "Backed up to: $backup_file" else log_warn "No existing signatures found (first run)" fi # Step 2: Download ET Open rules log_info "Downloading ET Open ruleset..." if wget -q "$ET_RULES_URL" -O "$TEMP_DIR/rules.tar.gz"; then log_success "Downloaded $(du -h "$TEMP_DIR/rules.tar.gz" | cut -f1)" else log_error "Failed to download ET Open rules" exit 1 fi # Step 3: Extract rules log_info "Extracting rules..." tar -xzf "$TEMP_DIR/rules.tar.gz" -C "$TEMP_DIR" 2>/dev/null if [ $? -eq 0 ]; then rule_count=$(find "$TEMP_DIR/rules" -name "*.rules" -type f 2>/dev/null | wc -l) log_success "Extracted $rule_count rule files" else log_error "Failed to extract rules" exit 1 fi # Step 4: Parse rules and generate new signature file log_info "Parsing rules and generating signatures..." cat > "$TEMP_DIR/attack-signatures-new.sh" << 'HEADER_EOF' #!/bin/bash # # Attack Signature Database # Auto-generated from Emerging Threats Open Ruleset (BSD License) # Source: https://rules.emergingthreats.net/ # Generated: $(date) # # Copyright (c) 2003-2025, Emerging Threats # All rights reserved. # Redistribution and use permitted under BSD license terms. # Initialize associative arrays for attack patterns declare -A ATTACK_SQLI # SQL Injection patterns declare -A ATTACK_XSS # Cross-Site Scripting declare -A ATTACK_CMD # Command Injection declare -A ATTACK_TRAVERSAL # Path Traversal declare -A ATTACK_INCLUSION # File Inclusion (LFI/RFI) declare -A ATTACK_WEBSHELL # Webshell detection declare -A ATTACK_CVE # Known CVE exploits declare -A ATTACK_UPLOAD # File upload attacks HEADER_EOF # Function to extract patterns from Suricata rules parse_et_rules() { local rules_dir="$1" local output_file="$2" echo "" >> "$output_file" echo "# ============================================================================" >> "$output_file" echo "# SQL INJECTION PATTERNS (auto-extracted from emerging-sql.rules)" >> "$output_file" echo "# ============================================================================" >> "$output_file" echo "" >> "$output_file" # Extract SQL injection patterns if [ -f "$rules_dir/emerging-sql.rules" ]; then local count=0 while IFS= read -r line; do # Skip comments and empty lines [[ "$line" =~ ^#.*$ ]] && continue [[ -z "$line" ]] && continue # Extract content patterns from rules if [[ "$line" =~ content:\"([^\"]+)\" ]]; then local pattern="${BASH_REMATCH[1]}" # Clean up Suricata-specific syntax pattern=$(echo "$pattern" | sed 's/|20|/ /g') # Replace |20| with space pattern=$(echo "$pattern" | sed 's/|0d 0a|/\\n/g') # Replace CRLF pattern=$(echo "$pattern" | sed 's/|[0-9a-f][0-9a-f]|//g') # Remove hex # Skip binary patterns (contain pipes) [[ "$pattern" =~ \| ]] && continue # Skip too short patterns [ "${#pattern}" -lt 3 ] && continue # Determine severity from rule priority local severity=80 if [[ "$line" =~ priority:1 ]]; then severity=90 elif [[ "$line" =~ priority:2 ]]; then severity=85 elif [[ "$line" =~ priority:3 ]]; then severity=75 fi # Extract description from msg field local description="SQL Injection" if [[ "$line" =~ msg:\"([^\"]+)\" ]]; then description="${BASH_REMATCH[1]}" fi # Generate pattern name local pattern_name="sqli_$(printf '%03d' $count)" # Output pattern echo "ATTACK_SQLI[\"$pattern_name\"]=\"$pattern|$severity|$description\"" >> "$output_file" count=$((count + 1)) [ $count -ge 20 ] && break # Limit to 20 patterns per category fi done < "$rules_dir/emerging-sql.rules" log_info " Extracted $count SQL injection patterns" fi echo "" >> "$output_file" echo "# ============================================================================" >> "$output_file" echo "# XSS PATTERNS (auto-extracted from emerging-web_server.rules)" >> "$output_file" echo "# ============================================================================" >> "$output_file" echo "" >> "$output_file" # Extract XSS patterns if [ -f "$rules_dir/emerging-web_server.rules" ]; then local count=0 while IFS= read -r line; do [[ "$line" =~ ^#.*$ ]] && continue [[ -z "$line" ]] && continue # Only process lines with XSS-related content if [[ "$line" =~ (script|xss|javascript|onerror|onload) ]] && [[ "$line" =~ content:\"([^\"]+)\" ]]; then local pattern="${BASH_REMATCH[1]}" # Clean up pattern=$(echo "$pattern" | sed 's/|20|/ /g') pattern=$(echo "$pattern" | sed 's/|[0-9a-f][0-9a-f]|//g') [[ "$pattern" =~ \| ]] && continue [ "${#pattern}" -lt 3 ] && continue local severity=75 [[ "$line" =~ priority:1 ]] && severity=85 [[ "$line" =~ priority:2 ]] && severity=80 local description="Cross-Site Scripting" if [[ "$line" =~ msg:\"([^\"]+)\" ]]; then description="${BASH_REMATCH[1]}" fi local pattern_name="xss_$(printf '%03d' $count)" echo "ATTACK_XSS[\"$pattern_name\"]=\"$pattern|$severity|$description\"" >> "$output_file" count=$((count + 1)) [ $count -ge 20 ] && break fi done < "$rules_dir/emerging-web_server.rules" log_info " Extracted $count XSS patterns" fi # Add fallback patterns if extraction yielded few results echo "" >> "$output_file" echo "# Fallback patterns (always included)" >> "$output_file" cat >> "$output_file" << 'FALLBACK_EOF' # Critical fallback patterns (in case extraction misses common attacks) ATTACK_SQLI["union_select"]="${ATTACK_SQLI["union_select"]:-union.*select|union.*all.*select|90|UNION SELECT injection}" ATTACK_XSS["script_tag"]="${ATTACK_XSS["script_tag"]:-|80|Script tag injection}" ATTACK_CMD["unix_cmd"]="${ATTACK_CMD["unix_cmd"]:-;cat |;ls |;wget |;curl |90|Unix command chaining}" ATTACK_TRAVERSAL["dotdot"]="${ATTACK_TRAVERSAL["dotdot"]:-\\.\\./|\\.\\.|%2e%2e|80|Directory traversal}" ATTACK_WEBSHELL["known_shells"]="${ATTACK_WEBSHELL["known_shells"]:-c99\\.php|r57\\.php|b374k|wso\\.php|95|Known webshell}" ATTACK_CVE["log4shell"]="${ATTACK_CVE["log4shell"]:-jndi:ldap://|jndi:rmi://|95|CVE-2021-44228 Log4Shell}" FALLBACK_EOF } # Parse the rules parse_et_rules "$TEMP_DIR/rules" "$TEMP_DIR/attack-signatures-new.sh" # Add helper functions (always included) cat >> "$TEMP_DIR/attack-signatures-new.sh" << 'HELPER_EOF' # ============================================================================ # HELPER FUNCTIONS # ============================================================================ # Check if request matches attack pattern in specific category check_attack_pattern() { local request="$1" local category="$2" local -n patterns="$category" for pattern_name in "${!patterns[@]}"; do local pattern_data="${patterns[$pattern_name]}" local regex="${pattern_data%%|*}" local temp="${pattern_data#*|}" local severity="${temp%%|*}" local description="${temp#*|}" if echo "$request" | grep -iEq "$regex"; then echo "$severity|$pattern_name|$description" return 0 fi done return 1 } # Get all matching patterns across all categories detect_all_attacks() { local request="$1" local matches=() local max_severity=0 local categories=("ATTACK_SQLI" "ATTACK_XSS" "ATTACK_CMD" "ATTACK_TRAVERSAL" "ATTACK_INCLUSION" "ATTACK_WEBSHELL" "ATTACK_CVE" "ATTACK_UPLOAD") for category in "${categories[@]}"; do local result=$(check_attack_pattern "$request" "$category") if [ -n "$result" ]; then local severity="${result%%|*}" local temp="${result#*|}" local pattern_name="${temp%%|*}" local description="${temp#*|}" matches+=("$severity|${category#ATTACK_}|$pattern_name|$description") [ "$severity" -gt "$max_severity" ] && max_severity="$severity" fi done if [ ${#matches[@]} -gt 0 ]; then echo "$max_severity|${#matches[@]}|${matches[*]}" return 0 fi return 1 } # Get attack category name (human-readable) get_category_name() { local category="$1" case "$category" in SQLI) echo "SQL Injection" ;; XSS) echo "Cross-Site Scripting" ;; CMD) echo "Command Injection" ;; TRAVERSAL) echo "Path Traversal" ;; INCLUSION) echo "File Inclusion" ;; WEBSHELL) echo "Webshell" ;; CVE) echo "CVE Exploit" ;; UPLOAD) echo "Malicious Upload" ;; *) echo "$category" ;; esac } HELPER_EOF # Step 5: Validate new signature file log_info "Validating new signature file..." if bash -n "$TEMP_DIR/attack-signatures-new.sh" 2>/dev/null; then log_success "Syntax check passed" else log_error "Syntax check failed - keeping old signatures" exit 1 fi # Step 6: Test that patterns work log_info "Testing pattern detection..." test_result=$(bash -c "source $TEMP_DIR/attack-signatures-new.sh && detect_all_attacks \"union select\" 2>/dev/null") if [ -n "$test_result" ]; then log_success "Pattern detection working" else log_warn "Pattern detection test failed - but file is valid, installing anyway" fi # Step 7: Install new signature file log_info "Installing new signatures..." cp "$TEMP_DIR/attack-signatures-new.sh" "$LIB_DIR/attack-signatures.sh" chmod 644 "$LIB_DIR/attack-signatures.sh" log_success "Installed to: $LIB_DIR/attack-signatures.sh" # Step 8: Show summary echo "" echo "========================================" echo "Update Complete!" echo "========================================" echo "" echo "Signature file: $LIB_DIR/attack-signatures.sh" echo "Backup saved to: $BACKUP_DIR/" echo "ET Rules source: $ET_RULES_URL" echo "Last updated: $(date)" echo "" echo "Changes will take effect when live-attack-monitor.sh is restarted." echo "" # Show pattern counts log_info "Pattern counts:" echo " SQL Injection: $(grep -c 'ATTACK_SQLI\[' "$LIB_DIR/attack-signatures.sh" || echo 0)" echo " XSS: $(grep -c 'ATTACK_XSS\[' "$LIB_DIR/attack-signatures.sh" || echo 0)" echo " Command Injection: $(grep -c 'ATTACK_CMD\[' "$LIB_DIR/attack-signatures.sh" || echo 0)" echo " Path Traversal: $(grep -c 'ATTACK_TRAVERSAL\[' "$LIB_DIR/attack-signatures.sh" || echo 0)" echo " File Inclusion: $(grep -c 'ATTACK_INCLUSION\[' "$LIB_DIR/attack-signatures.sh" || echo 0)" echo " Webshells: $(grep -c 'ATTACK_WEBSHELL\[' "$LIB_DIR/attack-signatures.sh" || echo 0)" echo " CVE Exploits: $(grep -c 'ATTACK_CVE\[' "$LIB_DIR/attack-signatures.sh" || echo 0)" echo " Upload Attacks: $(grep -c 'ATTACK_UPLOAD\[' "$LIB_DIR/attack-signatures.sh" || echo 0)" echo "" log_success "Signature update complete!"