]*>.*?<\/script>)', 'i') ), action: RuleAction::BLOCK, priority: 90, tags: ['xss', 'script', 'owasp-top10'] ), // Event handler injection new Rule( id: RuleId::xss('941110'), name: 'XSS - Event Handler Attack', description: 'Detects JavaScript event handler injection', category: DetectionCategory::XSS, severity: DetectionSeverity::HIGH, condition: RuleCondition::requestBody( RulePattern::regex('(?i:on(?:load|error|click|focus|blur|change|submit|reset|select|keydown|keyup|keypress|mouseover|mouseout|mousedown|mouseup|mousemove)[\s]*=)', 'i') ), action: RuleAction::BLOCK, priority: 85, tags: ['xss', 'events', 'owasp-top10'] ), // JavaScript pseudo protocol new Rule( id: RuleId::xss('941120'), name: 'XSS - JavaScript Pseudo Protocol', description: 'Detects javascript: pseudo protocol usage', category: DetectionCategory::XSS, severity: DetectionSeverity::HIGH, condition: RuleCondition::requestBody( RulePattern::regex('(?i:javascript[\s]*:)', 'i') ), action: RuleAction::BLOCK, priority: 80, tags: ['xss', 'javascript', 'protocol'] ), // HTML injection new Rule( id: RuleId::xss('941130'), name: 'XSS - HTML Tag Injection', description: 'Detects potentially dangerous HTML tags', category: DetectionCategory::XSS, severity: DetectionSeverity::MEDIUM, condition: RuleCondition::requestBody( RulePattern::regex('(?i:<(?:iframe|object|embed|applet|meta|link|style|img|svg|math|details|template)[^>]*>)', 'i') ), action: RuleAction::SCORE, priority: 70, tags: ['xss', 'html', 'tags'] ), ]; } /** * Path Traversal Rules */ public static function getPathTraversalRules(): array { return [ // Directory traversal new Rule( id: RuleId::pathTraversal('930100'), name: 'Path Traversal - Directory Traversal', description: 'Detects directory traversal attempts', category: DetectionCategory::PATH_TRAVERSAL, severity: DetectionSeverity::HIGH, condition: RuleCondition::urlPath( RulePattern::regex('(?i:(?:\.\.[\\/])|(?:[\\/]\.\.)|(?:\.\.\\\\)|(?:\\\\\.\.)|(?:%2e%2e%2f)|(?:%2e%2e\\\\)|(?:\.\.%2f)|(?:\.\.%5c)|(?:%2e%2e%5c)|(?:%c0%ae%c0%ae%c0%af)|(?:%c1%9c%c1%9c%c1%af))', 'i') ), action: RuleAction::BLOCK, priority: 85, tags: ['path-traversal', 'directory', 'file-access'] ), // Absolute path access new Rule( id: RuleId::pathTraversal('930110'), name: 'Path Traversal - Absolute Path Access', description: 'Detects absolute path access attempts', category: DetectionCategory::PATH_TRAVERSAL, severity: DetectionSeverity::MEDIUM, condition: RuleCondition::requestBody( RulePattern::regex('(?i:(?:\/etc\/passwd|\/etc\/shadow|\/etc\/hosts|\/proc\/|\/sys\/|c:[\\\\\\/]|\\\\\\\\))', 'i') ), action: RuleAction::SCORE, priority: 75, tags: ['path-traversal', 'absolute-path', 'system-files'] ), ]; } /** * Command Injection Rules */ public static function getCommandInjectionRules(): array { return [ // OS Command injection new Rule( id: RuleId::commandInjection('932100'), name: 'Command Injection - OS Commands', description: 'Detects OS command injection attempts', category: DetectionCategory::COMMAND_INJECTION, severity: DetectionSeverity::CRITICAL, condition: RuleCondition::requestBody( RulePattern::regex('(?i:(?:;|\||\|\||&&|&|`|\$\(|\${)[\s]*(?:cat|ls|pwd|id|uname|whoami|ps|kill|rm|mv|cp|chmod|chown|find|grep|awk|sed|sort|head|tail|wc|netstat|ifconfig|ping|wget|curl|nc|telnet|ssh|su|sudo|passwd|shadow|etc\/passwd|etc\/shadow|proc\/))', 'i') ), action: RuleAction::BLOCK, priority: 95, tags: ['command-injection', 'os-injection', 'rce', 'owasp-top10'] ), // Shell metacharacters new Rule( id: RuleId::commandInjection('932110'), name: 'Command Injection - Shell Metacharacters', description: 'Detects shell metacharacters', category: DetectionCategory::COMMAND_INJECTION, severity: DetectionSeverity::HIGH, condition: RuleCondition::requestBody( RulePattern::regex('(?i:[;&|`$(){}[\]<>])', 'i') ), action: RuleAction::SCORE, priority: 80, tags: ['command-injection', 'shell', 'metacharacters'] ), ]; } /** * File Upload Rules */ public static function getFileUploadRules(): array { return [ // Malicious file extensions new Rule( id: RuleId::generic('933100'), name: 'File Upload - Malicious Extensions', description: 'Detects potentially malicious file extensions', category: DetectionCategory::FILE_UPLOAD_ABUSE, severity: DetectionSeverity::HIGH, condition: RuleCondition::header( 'Content-Type', RulePattern::regex('(?i:application\/(?:x-)?(?:php|jsp|asp|exe|bat|cmd|sh|python|perl|ruby|javascript)|text\/(?:x-)?(?:php|jsp|asp|python|perl|ruby))', 'i') ), action: RuleAction::BLOCK, priority: 85, tags: ['file-upload', 'malware', 'webshell'] ), // Double extensions new Rule( id: RuleId::generic('933110'), name: 'File Upload - Double Extensions', description: 'Detects double file extensions', category: DetectionCategory::FILE_UPLOAD_ABUSE, severity: DetectionSeverity::MEDIUM, condition: RuleCondition::requestBody( RulePattern::regex('(?i:\.(?:jpg|jpeg|png|gif|bmp|doc|docx|pdf|txt)\.(?:php|jsp|asp|exe|bat|cmd|sh|py|pl|rb|js))', 'i') ), action: RuleAction::SCORE, priority: 70, tags: ['file-upload', 'double-extension', 'bypass'] ), ]; } /** * User Agent Rules */ public static function getUserAgentRules(): array { return [ // Security scanners new Rule( id: RuleId::generic('913100'), name: 'User-Agent - Security Scanner Detection', description: 'Detects known security scanning tools', category: DetectionCategory::BOT_DETECTION, severity: DetectionSeverity::MEDIUM, condition: RuleCondition::userAgent( RulePattern::regex('(?i:(?:sqlmap|nmap|nikto|w3af|acunetix|nessus|openvas|burp|havij|hydra|metasploit|python-requests|curl|wget))', 'i') ), action: RuleAction::CHALLENGE, priority: 70, tags: ['user-agent', 'scanner', 'tool-detection'] ), // Empty or missing User-Agent new Rule( id: RuleId::generic('913110'), name: 'User-Agent - Missing or Empty', description: 'Detects missing or empty user agent strings', category: DetectionCategory::BOT_DETECTION, severity: DetectionSeverity::LOW, condition: RuleCondition::userAgent( RulePattern::regex('^$', '') ), action: RuleAction::SCORE, priority: 40, tags: ['user-agent', 'empty', 'suspicious'] ), ]; } /** * HTTP Protocol Rules */ public static function getHttpProtocolRules(): array { return [ // Invalid HTTP methods new Rule( id: RuleId::generic('911100'), name: 'HTTP Protocol - Invalid Method', description: 'Detects invalid HTTP methods', category: DetectionCategory::PROTOCOL_ATTACK, severity: DetectionSeverity::MEDIUM, condition: RuleCondition::httpMethod( RulePattern::regex('^(?!GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH|TRACE|CONNECT).*', 'i') ), action: RuleAction::BLOCK, priority: 60, tags: ['http', 'protocol', 'method', 'invalid'] ), // Oversized request headers new Rule( id: RuleId::generic('911110'), name: 'HTTP Protocol - Oversized Headers', description: 'Detects oversized HTTP headers', category: DetectionCategory::PROTOCOL_ATTACK, severity: DetectionSeverity::MEDIUM, condition: RuleCondition::header( '*', RulePattern::regex('.{8192,}', '') // Headers over 8KB ), action: RuleAction::BLOCK, priority: 65, tags: ['http', 'protocol', 'headers', 'size'] ), ]; } /** * Application Attack Rules */ public static function getApplicationAttackRules(): array { return [ // LDAP injection new Rule( id: RuleId::generic('950100'), name: 'Application Attack - LDAP Injection', description: 'Detects LDAP injection attempts', category: DetectionCategory::INJECTION_ATTACK, severity: DetectionSeverity::HIGH, condition: RuleCondition::requestBody( RulePattern::regex('(?i:(?:\()(?:&|\|)(?:\(|\)))', 'i') ), action: RuleAction::BLOCK, priority: 80, tags: ['ldap', 'injection', 'application'] ), // XPath injection new Rule( id: RuleId::generic('950110'), name: 'Application Attack - XPath Injection', description: 'Detects XPath injection attempts', category: DetectionCategory::INJECTION_ATTACK, severity: DetectionSeverity::HIGH, condition: RuleCondition::requestBody( RulePattern::regex('(?i:(?:\/\/|\.\.|\[@|position\(\)|text\(\)|node\(\)|ancestor|descendant|following|preceding|self))', 'i') ), action: RuleAction::BLOCK, priority: 75, tags: ['xpath', 'injection', 'xml'] ), ]; } /** * Generic Attack Rules */ public static function getGenericAttackRules(): array { return [ // Null byte injection new Rule( id: RuleId::generic('960100'), name: 'Generic Attack - Null Byte Injection', description: 'Detects null byte injection attempts', category: DetectionCategory::PROTOCOL_ATTACK, severity: DetectionSeverity::HIGH, condition: RuleCondition::requestBody( RulePattern::regex('(?i:%00|\\x00|\0)', 'i') ), action: RuleAction::BLOCK, priority: 80, tags: ['null-byte', 'injection', 'bypass'] ), // Unicode evasion new Rule( id: RuleId::generic('960110'), name: 'Generic Attack - Unicode Evasion', description: 'Detects Unicode-based evasion attempts', category: DetectionCategory::EVASION, severity: DetectionSeverity::MEDIUM, condition: RuleCondition::requestBody( RulePattern::regex('(?i:%u[0-9a-f]{4}|\\\\u[0-9a-f]{4})', 'i') ), action: RuleAction::SCORE, priority: 60, tags: ['unicode', 'evasion', 'encoding'] ), ]; } /** * Get rules by OWASP Top 10 category */ public static function getOwaspTop10Rules(): array { return array_filter( self::getAllRules(), fn (Rule $rule) => $rule->hasTag('owasp-top10') ); } /** * Get critical severity rules only */ public static function getCriticalRules(): array { return array_filter( self::getAllRules(), fn (Rule $rule) => $rule->severity === DetectionSeverity::CRITICAL ); } /** * Get high-priority rules (priority >= 80) */ public static function getHighPriorityRules(): array { return array_filter( self::getAllRules(), fn (Rule $rule) => $rule->priority >= 80 ); } }