ecde6dfe0c
CRITICAL BUG FOUND: The live monitor was missing most attack detections due to a function name conflict between legacy and ET signature systems. Root Cause: 1. Legacy detect_all_attacks() in attack-patterns.sh - Returns: "SQL_INJECTION,XSS,RCE" - Used by update_ip_intelligence() at line 292 2. ET detect_all_attacks() in attack-signatures.sh - Returns: "max_severity||match_count||detailed_data" - OVERWRITES legacy function when sourced! 3. Source Order (live-attack-monitor.sh): Line 23: source attack-patterns.sh (defines legacy function) Line 27: source attack-signatures.sh (OVERWRITES with ET version) Impact: When update_ip_intelligence() called detect_all_attacks(), it got ET's complex format instead of simple attack names, causing: - Parse failures (expecting "SQLI" but getting "90||2||90||SQLI||...") - Empty attack lists - No legacy attack detection in live monitor - Only ET detection via analyze_http_log_line() was working User Report: "is the live monitor missing anything any logic or anything from all of the signatures we imported" YES - it was missing ALL legacy pattern detection! Solution: Renamed ET function to avoid conflict: detect_all_attacks() → detect_all_attack_signatures() Changes Made: 1. lib/attack-signatures.sh (line 262): - Renamed: detect_all_attacks → detect_all_attack_signatures - Added comment explaining the rename reason 2. lib/http-attack-analyzer.sh (line 46): - Updated call: detect_all_attacks → detect_all_attack_signatures - This is the only legitimate caller of ET function Now Both Systems Work: ✅ Legacy detect_all_attacks() - returns "SQLI,XSS" ✅ ET detect_all_attack_signatures() - returns detailed ET data ✅ ET analyze_http_log_line() - main ET detection entry point Testing: - Legacy function: Returns "SQL_INJECTION,HTTP_SMUGGLING" ✅ - ET function: Returns "90||2||90||SQLI||union_select||..." ✅ - No more function overwriting ✅ This restores full attack detection in the live monitor!
314 lines
14 KiB
Bash
314 lines
14 KiB
Bash
#!/bin/bash
|
|
#
|
|
# Attack Signature Database
|
|
# Extracted from Emerging Threats Open Ruleset (BSD License)
|
|
# Source: https://rules.emergingthreats.net/
|
|
#
|
|
# Copyright (c) 2003-2025, Emerging Threats
|
|
# All rights reserved.
|
|
# Redistribution and use permitted under BSD license terms.
|
|
#
|
|
# This file contains attack pattern signatures for detecting web-based attacks
|
|
# in HTTP access logs. Patterns are extracted and adapted from ET Open rules.
|
|
|
|
# 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
|
|
|
|
# Pattern format: [category_name]="regex_pattern||severity||||description"
|
|
# Severity: 1-100 (higher = more dangerous)
|
|
# Note: Using || as delimiter to allow | in regex patterns
|
|
|
|
# ============================================================================
|
|
# SQL INJECTION PATTERNS (extracted from emerging-sql.rules)
|
|
# ============================================================================
|
|
|
|
# UNION-based SQL injection
|
|
ATTACK_SQLI["union_select"]="union.*select|union.*all.*select||90||UNION SELECT injection"
|
|
ATTACK_SQLI["union_from"]="union.*from|union.*all.*from||90||UNION FROM injection"
|
|
|
|
# Basic SQL injection attempts
|
|
ATTACK_SQLI["basic_sqli"]="' or '1'='1|' or 1=1--|';--||85||Basic SQL injection"
|
|
ATTACK_SQLI["basic_sqli2"]="\" or \"1\"=\"1|\" or 1=1--||85||Basic SQL injection (double quotes)"
|
|
ATTACK_SQLI["comment_bypass"]="--[[:space:]]|#[[:space:]]|/\*|\*/||75||SQL comment injection"
|
|
|
|
# Blind SQL injection
|
|
ATTACK_SQLI["blind_sqli"]="sleep\(|benchmark\(|waitfor.*delay||80||Blind SQL injection"
|
|
ATTACK_SQLI["time_based"]="pg_sleep\(|dbms_lock\.sleep||85||Time-based blind SQLi"
|
|
|
|
# Stacked queries
|
|
ATTACK_SQLI["stacked_query"]="';.*drop|';.*insert|';.*delete|';.*update||90||Stacked query injection"
|
|
ATTACK_SQLI["stacked_exec"]="';.*exec|';.*execute||85||Stacked execution injection"
|
|
|
|
# SQL functions abuse
|
|
ATTACK_SQLI["sqli_functions"]="concat\(|group_concat\(|load_file\(|into.*outfile||85||SQL function abuse"
|
|
ATTACK_SQLI["sqli_info"]="information_schema|mysql\.user|sys\.databases||90||Database metadata access"
|
|
|
|
# Boolean-based injection
|
|
ATTACK_SQLI["sqli_operators"]="and.*1=1|or.*1=1|xor.*1=1||70||Boolean-based injection"
|
|
ATTACK_SQLI["sqli_boolean"]="and.*true|or.*false|and.*null||80||Boolean logic injection"
|
|
|
|
# Encoded SQL injection
|
|
ATTACK_SQLI["sqli_hex"]="0x[0-9a-f]{8,}|char\(|ascii\(||75||Hex-encoded injection"
|
|
ATTACK_SQLI["sqli_encoded"]="%27%20or%20|%27%20union%20|%22%20or%20||80||URL-encoded SQL injection"
|
|
|
|
# ============================================================================
|
|
# CROSS-SITE SCRIPTING (XSS) PATTERNS (from emerging-web_server.rules)
|
|
# ============================================================================
|
|
|
|
# Script tag injection
|
|
ATTACK_XSS["script_tag"]="<script|</script>|<SCRIPT|</SCRIPT>||80||Script tag injection"
|
|
ATTACK_XSS["script_src"]="<script.*src=|<SCRIPT.*SRC=||85||External script injection"
|
|
|
|
# JavaScript protocol handlers
|
|
ATTACK_XSS["javascript_proto"]="javascript:|javascript%3a||75||JavaScript protocol handler"
|
|
ATTACK_XSS["vbscript_proto"]="vbscript:|vbscript%3a||75||VBScript protocol handler"
|
|
|
|
# Event handler injection
|
|
ATTACK_XSS["event_handler"]="onerror=|onload=|onclick=|onmouseover=||85||Event handler injection"
|
|
ATTACK_XSS["event_handler2"]="onmouseout=|onfocus=|onblur=|onchange=||80||Event handler injection"
|
|
ATTACK_XSS["event_handler3"]="onsubmit=|onkeydown=|onkeyup=|onkeypress=||80||Keyboard event injection"
|
|
|
|
# Encoded script tags
|
|
ATTACK_XSS["encoded_script"]="%3Cscript|%3C%2Fscript|%3C%73%63%72%69%70%74||80||URL-encoded script tag"
|
|
ATTACK_XSS["double_encoded"]="%253Cscript|%253C%252Fscript||85||Double-encoded script tag"
|
|
|
|
# IFrame injection
|
|
ATTACK_XSS["iframe_injection"]="<iframe|</iframe>|<IFRAME||75||IFrame injection"
|
|
ATTACK_XSS["iframe_src"]="<iframe.*src=|<IFRAME.*SRC=||80||External IFrame injection"
|
|
|
|
# Image-based XSS
|
|
ATTACK_XSS["img_onerror"]="<img.*onerror|<IMG.*onerror||85||Image tag with onerror"
|
|
ATTACK_XSS["img_javascript"]="<img.*javascript:|<IMG.*javascript:||85||Image with JavaScript"
|
|
|
|
# SVG-based XSS
|
|
ATTACK_XSS["svg_injection"]="<svg.*onload|<SVG.*onload||80||SVG-based XSS"
|
|
ATTACK_XSS["svg_script"]="<svg.*<script|<SVG.*<SCRIPT||85||SVG with embedded script"
|
|
|
|
# Data URI injection
|
|
ATTACK_XSS["data_uri"]="data:text/html|data:text/javascript||70||Data URI injection"
|
|
ATTACK_XSS["data_base64"]="data:.*base64||70||Base64 data URI injection"
|
|
|
|
# ============================================================================
|
|
# COMMAND INJECTION PATTERNS
|
|
# ============================================================================
|
|
|
|
# Basic command injection
|
|
ATTACK_CMD["basic_cmd"]="cmd=|exec=|system=|shell=|command=||85||Command parameter injection"
|
|
ATTACK_CMD["execute"]="execute=|run=|process=||90||Execute parameter injection"
|
|
|
|
# Unix command chaining
|
|
ATTACK_CMD["unix_cmd"]=";cat |;ls |;wget |;curl |;nc ||90||Unix command chaining"
|
|
ATTACK_CMD["unix_cmd2"]=";bash |;sh |;id |;whoami |;uname ||90||Unix shell commands"
|
|
ATTACK_CMD["unix_read"]=";head |;tail |;more |;less |;cat ||85||Unix file read commands"
|
|
|
|
# Windows command injection
|
|
ATTACK_CMD["windows_cmd"]="cmd\.exe|powershell|net\.exe|taskkill||85||Windows command injection"
|
|
ATTACK_CMD["windows_ps"]="powershell\.exe|pwsh|Start-Process||90||PowerShell injection"
|
|
|
|
# Command chaining operators
|
|
ATTACK_CMD["pipe_redirect"]="\||&&|\`|\\$\\(||90||Command chaining operators"
|
|
ATTACK_CMD["redirect"]=">[[:space:]]|>>[[:space:]]|<[[:space:]]||80||Shell redirection"
|
|
|
|
# Encoded commands
|
|
ATTACK_CMD["base64_cmd"]="echo.*\|.*base64|base64.*-d||75||Base64-encoded commands"
|
|
ATTACK_CMD["hex_cmd"]="\\x[0-9a-f]{2}||70||Hex-encoded commands"
|
|
|
|
# ============================================================================
|
|
# PATH TRAVERSAL PATTERNS
|
|
# ============================================================================
|
|
|
|
# Directory traversal
|
|
ATTACK_TRAVERSAL["dotdot"]="\\.\\./|\\.\\.|%2e%2e|%252e%252e||80||Directory traversal"
|
|
ATTACK_TRAVERSAL["dotdot_encoded"]="%%32%65|%%32%45|%c0%ae||85||Encoded directory traversal"
|
|
|
|
# Sensitive file access
|
|
ATTACK_TRAVERSAL["passwd"]="/etc/passwd|/etc/shadow|/etc/hosts||90||Unix password file access"
|
|
ATTACK_TRAVERSAL["windows_sys"]="c:\\\\windows\\\\|c:\\\\winnt\\\\|\\\\windows\\\\system32||85||Windows system file access"
|
|
ATTACK_TRAVERSAL["config_files"]="/etc/apache|/etc/nginx|/etc/mysql|httpd\.conf||85||Configuration file access"
|
|
|
|
# Double encoding
|
|
ATTACK_TRAVERSAL["double_encode"]="%252e%252e%252f|%c0%ae%c0%ae||85||Double-encoded traversal"
|
|
|
|
# Null byte injection
|
|
ATTACK_TRAVERSAL["null_byte"]="%00|\\0|\\x00||70||Null byte injection"
|
|
|
|
# ============================================================================
|
|
# FILE INCLUSION PATTERNS
|
|
# ============================================================================
|
|
|
|
# PHP wrapper abuse
|
|
ATTACK_INCLUSION["php_wrapper"]="php://filter|php://input|php://output||85||PHP filter wrapper"
|
|
ATTACK_INCLUSION["lfi_wrapper"]="file://|data://|expect://|zip://||85||Local file inclusion wrapper"
|
|
ATTACK_INCLUSION["phar_wrapper"]="phar://|rar://|ogg://||80||Archive wrapper abuse"
|
|
|
|
# Remote file inclusion
|
|
ATTACK_INCLUSION["rfi_http"]="http://.*\\.txt|https://.*\\.txt|ftp://.*\\.txt||90||Remote file inclusion"
|
|
ATTACK_INCLUSION["rfi_param"]="include=http|require=http|page=http||90||RFI via HTTP parameter"
|
|
|
|
# Log poisoning
|
|
ATTACK_INCLUSION["lfi_log"]="/var/log/apache|/var/log/nginx|access\.log|error\.log||80||Log file poisoning"
|
|
ATTACK_INCLUSION["lfi_proc"]="/proc/self/environ|/proc/self/fd||85||Process file inclusion"
|
|
|
|
# ============================================================================
|
|
# WEBSHELL PATTERNS (from emerging-web_server.rules)
|
|
# ============================================================================
|
|
|
|
# Known webshells
|
|
ATTACK_WEBSHELL["known_shells"]="c99\\.php|r57\\.php|b374k|wso\\.php||95||Known webshell filename"
|
|
ATTACK_WEBSHELL["known_shells2"]="shell\\.php|cmd\\.php|backdoor\\.php|webshell\\.php||95||Generic webshell filename"
|
|
ATTACK_WEBSHELL["china_shells"]="caidao|chopper|godzilla|behinder||95||Chinese webshell"
|
|
ATTACK_WEBSHELL["alfa_shell"]="alfa|alfanew|alfa-rex|alfacgiapi||95||Alfa Team webshell"
|
|
ATTACK_WEBSHELL["common_shells"]="mini\\.php|phpspy|antichat|idx|indoxploit||95||Common webshells"
|
|
ATTACK_WEBSHELL["suspicious_php"]="admin\\.php|wp-config\\.php|configuration\\.php.*\\?|index\\.php\\?||85||Suspicious PHP in wrong location"
|
|
|
|
# Upload script abuse
|
|
ATTACK_WEBSHELL["upload_shell"]="upload\\.php|uploader\\.php|file_upload\\.php||85||Upload script abuse"
|
|
ATTACK_WEBSHELL["filemanager"]="filemanager\\.php|elfinder|tinymce.*upload||80||File manager abuse"
|
|
|
|
# Obfuscated code patterns
|
|
ATTACK_WEBSHELL["obfuscated"]="eval\\(|base64_decode\\(|gzinflate\\(|str_rot13\\(||90||Obfuscated PHP code"
|
|
ATTACK_WEBSHELL["obfuscated2"]="assert\\(|preg_replace.*\\/e|create_function\\(||90||Dangerous PHP functions"
|
|
|
|
# Backdoor patterns
|
|
ATTACK_WEBSHELL["backdoor"]="backdoor|rootkit|c99shell|r57shell||95||Backdoor keywords"
|
|
ATTACK_WEBSHELL["webshell_param"]="cmd=|command=|exec=|passthru=||90||Webshell command parameter"
|
|
|
|
# ============================================================================
|
|
# KNOWN CVE EXPLOIT PATTERNS
|
|
# ============================================================================
|
|
|
|
# Critical CVEs
|
|
ATTACK_CVE["log4shell"]="jndi:ldap://|jndi:rmi://|jndi:dns://|jndi:nis://||95||CVE-2021-44228 Log4Shell"
|
|
ATTACK_CVE["shellshock"]="\\(\\) \\{ :;\\};|bash -c |/bin/bash -c||95||CVE-2014-6271 Shellshock"
|
|
ATTACK_CVE["struts2"]="Content-Type:.*ognl|%\\{|#_memberAccess||90||CVE-2017-5638 Struts2"
|
|
ATTACK_CVE["spring4shell"]="class\\.module\\.classLoader|accessLogValve||90||CVE-2022-22965 Spring4Shell"
|
|
|
|
# High severity CVEs
|
|
ATTACK_CVE["php_cgi"]="\\?-d allow_url_include|\\?-d auto_prepend||85||CVE-2012-1823 PHP-CGI"
|
|
ATTACK_CVE["struts2_s2057"]="\\.(action|do).*%\\{||85||CVE-2018-11776 Struts2 S2-057"
|
|
ATTACK_CVE["bluekeep"]="MS_T120|3389||85||CVE-2019-0708 BlueKeep"
|
|
ATTACK_CVE["proxylogon"]="/owa/auth/.*autodiscover|/ecp/.*proxyLogon||90||CVE-2021-26855 ProxyLogon"
|
|
|
|
# Medium severity CVEs
|
|
ATTACK_CVE["drupalgeddon"]="drupalgeddon|node/\\?||70||CVE-2018-7600 Drupal RCE"
|
|
ATTACK_CVE["citrix_traversal"]="vpns.*\\.\\..*\\.xml||75||CVE-2019-19781 Citrix ADC"
|
|
ATTACK_CVE["f5_bigip"]="tmui.*\\.\\..*hsqldb||80||CVE-2020-5902 F5 BIG-IP"
|
|
ATTACK_CVE["phpunit"]="\\.\\..*web-console|vendor/phpunit||70||CVE-2017-9841 PHPUnit"
|
|
|
|
# ============================================================================
|
|
# FILE UPLOAD ATTACK PATTERNS
|
|
# ============================================================================
|
|
|
|
# Double extension bypass
|
|
ATTACK_UPLOAD["double_ext"]="\\.php\\.jpg|\\.php\\.png|\\.php\\.gif|\\.phtml||80||Double extension upload"
|
|
ATTACK_UPLOAD["double_ext2"]="\\.php5|\\.php7|\\.pht|\\.phps||80||PHP alternative extension"
|
|
|
|
# MIME type mismatch
|
|
ATTACK_UPLOAD["mime_mismatch"]="Content-Type:.*application/x-php||85||MIME type mismatch"
|
|
ATTACK_UPLOAD["mime_bypass"]="Content-Type:.*text/php||80||PHP MIME type"
|
|
|
|
# Null byte upload bypass
|
|
ATTACK_UPLOAD["null_byte_upload"]="\\.php%00\\.jpg|\\.php\\\\0\\.png||90||Null byte upload bypass"
|
|
|
|
# Dangerous file types
|
|
ATTACK_UPLOAD["dangerous_ext"]="\\.exe|\\.bat|\\.cmd|\\.vbs|\\.ps1||85||Dangerous executable upload"
|
|
ATTACK_UPLOAD["script_upload"]="\\.sh|\\.pl|\\.py|\\.rb||80||Script file upload"
|
|
|
|
# ============================================================================
|
|
# HELPER FUNCTIONS
|
|
# ============================================================================
|
|
|
|
# Check if request matches attack pattern in specific category
|
|
# Usage: check_attack_pattern "$request_line" "ATTACK_SQLI"
|
|
# Returns: severity|pattern_name|description or empty string
|
|
check_attack_pattern() {
|
|
local request="$1"
|
|
local category="$2"
|
|
|
|
# Get reference to the associative array
|
|
local -n patterns="$category"
|
|
|
|
for pattern_name in "${!patterns[@]}"; do
|
|
local pattern_data="${patterns[$pattern_name]}"
|
|
|
|
# Parse pattern data: regex||severity||description
|
|
local regex="${pattern_data%%||*}"
|
|
local temp="${pattern_data#*||}"
|
|
local severity="${temp%%||*}"
|
|
local description="${temp#*||}"
|
|
|
|
# Case-insensitive regex match
|
|
if echo "$request" | grep -iEq "$regex" 2>/dev/null; then
|
|
echo "$severity||$pattern_name||$description"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
# Get all matching patterns across all categories
|
|
# Usage: detect_all_attack_signatures "$request_line"
|
|
# Returns: max_severity|match_count|matches (space-separated)
|
|
# Each match format: severity|category|pattern_name|description
|
|
# Note: Renamed to avoid conflict with legacy detect_all_attacks in attack-patterns.sh
|
|
detect_all_attack_signatures() {
|
|
local request="$1"
|
|
local matches=()
|
|
local max_severity=0
|
|
|
|
# Check all categories
|
|
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#*||}"
|
|
|
|
# Format: severity||category||pattern_name||description
|
|
matches+=("$severity||${category#ATTACK_}||$pattern_name||$description")
|
|
|
|
# Track max severity (with validation)
|
|
if [[ "$severity" =~ ^[0-9]+$ ]] && [ "$severity" -gt "$max_severity" ]; then
|
|
max_severity="$severity"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Return results
|
|
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
|
|
}
|