Files
cschantz 682bd69cf8 Add missing function exports to library files
QA scan found 4 library files with functions that weren't exported,
making them unavailable in subshells and nested calls.

Added export statements for:
- lib/attack-signatures.sh: 3 functions
- lib/http-attack-analyzer.sh: 5 functions
- lib/email-functions.sh: 18 functions
- lib/rate-anomaly-detector.sh: 9 functions

Total: 35 functions now properly exported

This ensures functions are available when libraries are sourced by
scripts that spawn subshells or use process substitution.
2026-01-02 16:23:17 -05:00

319 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
}
# Export functions for use in subshells
export -f check_attack_pattern
export -f detect_all_attack_signatures
export -f get_category_name