clientIp} attempted path traversal: {$this->requestedPath}"; $context = ExceptionContext::forOperation('security.path_traversal_detection', 'Security') ->withData([ 'client_ip' => $this->clientIp, 'requested_path' => $this->requestedPath, 'pattern' => $this->pattern, 'context' => $this->attackContext, 'path_depth' => $this->calculateTraversalDepth(), 'event_identifier' => "security_path_traversal:{$this->clientIp}", 'category' => 'file_access', 'requires_alert' => true, // Path-Traversal-Versuche erfordern immer Alerts ]) ->withMetadata([ 'security_event' => true, 'owasp_compliant' => true, 'log_level' => 'ERROR', 'attack_type' => 'path_traversal', 'critical_security_event' => true, ]); parent::__construct( message: $message, context: $context, code: 400, // Bad Request previous: $previous, errorCode: ErrorCode::SECURITY_PATH_TRAVERSAL ); } // === Factory Methods für verschiedene Path-Traversal-Patterns === public static function dotDotSlash(string $clientIp, string $path): self { return new self($clientIp, $path, '../ pattern', 'file_access'); } public static function dotDotBackslash(string $clientIp, string $path): self { return new self($clientIp, $path, '..\ pattern', 'file_access'); } public static function encodedTraversal(string $clientIp, string $path): self { return new self($clientIp, $path, 'URL-encoded traversal', 'file_access'); } public static function unicodeTraversal(string $clientIp, string $path): self { return new self($clientIp, $path, 'Unicode-encoded traversal', 'file_access'); } public static function absolutePath(string $clientIp, string $path): self { return new self($clientIp, $path, 'Absolute path access', 'file_access'); } public static function systemPath(string $clientIp, string $path): self { return new self($clientIp, $path, 'System directory access', 'system_access'); } public static function configFileAccess(string $clientIp, string $path): self { return new self($clientIp, $path, 'Configuration file access', 'config_access'); } /** * Gibt OWASP-konforme Event-Daten zurück */ public function getSecurityEventData(): array { return [ 'event_identifier' => "security_path_traversal:{$this->clientIp}", 'description' => "Client {$this->clientIp} attempted path traversal: {$this->requestedPath}", 'category' => 'file_access', 'log_level' => 'ERROR', 'requires_alert' => true, 'client_ip' => $this->clientIp, 'requested_path' => $this->requestedPath, 'pattern' => $this->pattern, 'context' => $this->attackContext, 'attack_severity' => $this->getAttackSeverity(), ]; } /** * Bestimmt Schweregrad des Path-Traversal-Angriffs */ public function getAttackSeverity(): string { // Systemverzeichnisse sind kritisch $criticalPaths = ['/etc/', '/var/', '/usr/', '/sys/', '/proc/', 'C:\Windows', 'C:\System']; foreach ($criticalPaths as $critical) { if (str_contains($this->requestedPath, $critical)) { return 'CRITICAL'; } } // Konfigurationsdateien sind hochriskant $sensitiveFiles = ['.env', 'config', 'passwd', 'shadow', 'hosts', 'web.config']; foreach ($sensitiveFiles as $sensitive) { if (str_contains($this->requestedPath, $sensitive)) { return 'HIGH'; } } // Deep traversal ist verdächtig if ($this->calculateTraversalDepth() > 3) { return 'HIGH'; } return 'MEDIUM'; } /** * Berechnet die Tiefe des Traversal-Versuchs */ public function calculateTraversalDepth(): int { return substr_count($this->requestedPath, '../') + substr_count($this->requestedPath, '..\\'); } /** * Path-Traversal-Versuche erfordern immer Alerts */ public function requiresAlert(): bool { return true; } /** * Prüft ob es ein automatisierter Angriff ist */ public function isAutomatedAttack(): bool { // Typische automatisierte Scanner-Patterns $automatedPatterns = [ '../../../../../../../../etc/passwd', '..\\..\\..\\..\\windows\\system32', '%2e%2e%2f', // URL-encoded ../ '\x2e\x2e\x2f', // Hex-encoded ]; $lowerPath = strtolower($this->requestedPath); foreach ($automatedPatterns as $pattern) { if (str_contains($lowerPath, strtolower($pattern))) { return true; } } return false; } /** * Analysiert das Path-Traversal-Pattern detailliert */ public function analyzePattern(): array { $analysis = [ 'encoding_type' => 'none', 'target_os' => 'unknown', 'target_files' => [], 'traversal_depth' => $this->calculateTraversalDepth(), 'automation_detected' => $this->isAutomatedAttack(), 'evasion_techniques' => [], ]; // Encoding-Erkennung if (str_contains($this->requestedPath, '%')) { $analysis['encoding_type'] = 'url_encoded'; } elseif (str_contains($this->requestedPath, '\x')) { $analysis['encoding_type'] = 'hex_encoded'; } elseif (preg_match('/\\u[0-9a-f]{4}/i', $this->requestedPath)) { $analysis['encoding_type'] = 'unicode_encoded'; } // OS-Erkennung if (str_contains($this->requestedPath, '\\')) { $analysis['target_os'] = 'windows'; } elseif (str_contains($this->requestedPath, '/')) { $analysis['target_os'] = 'unix'; } // Zieldateien identifizieren $targetFiles = [ 'passwd' => 'unix_password_file', 'shadow' => 'unix_shadow_file', 'hosts' => 'hosts_file', '.env' => 'environment_file', 'config' => 'configuration_file', 'web.config' => 'iis_config', 'httpd.conf' => 'apache_config', 'nginx.conf' => 'nginx_config', ]; foreach ($targetFiles as $file => $description) { if (str_contains(strtolower($this->requestedPath), $file)) { $analysis['target_files'][] = $description; } } // Evasion-Techniken if (str_contains($this->requestedPath, './')) { $analysis['evasion_techniques'][] = 'current_directory_reference'; } if (preg_match('/\.{3,}/', $this->requestedPath)) { $analysis['evasion_techniques'][] = 'multiple_dots'; } if (str_contains($this->requestedPath, '//')) { $analysis['evasion_techniques'][] = 'double_slash'; } return $analysis; } /** * Gibt benutzerfreundliche Fehlermeldung zurück (ohne Details zu verraten) */ public function getUserMessage(): string { return "Invalid file path. Access denied."; } /** * Gibt spezifische Verteidigungsempfehlung zurück */ public function getDefenseRecommendation(): string { return match ($this->attackContext) { 'file_access' => 'Implement proper path validation, use allowlists, and restrict file access to specific directories.', 'system_access' => 'Block access to system directories, implement strict path validation, and use security contexts.', 'config_access' => 'Secure configuration files, implement access controls, and use environment variables.', default => 'Implement comprehensive path validation and access controls.', }; } /** * Generiert IOC (Indicator of Compromise) für Security-Teams */ public function generateIOC(): array { return [ 'type' => 'path_traversal_attempt', 'source_ip' => $this->clientIp, 'requested_path' => $this->requestedPath, 'pattern' => $this->pattern, 'context' => $this->attackContext, 'severity' => $this->getAttackSeverity(), 'timestamp' => date('Y-m-d H:i:s'), 'automated' => $this->isAutomatedAttack(), 'analysis' => $this->analyzePattern(), ]; } /** * Prüft ob sofortige Gegenmaßnahmen erforderlich sind */ public function requiresImmediateAction(): bool { return in_array($this->getAttackSeverity(), ['HIGH', 'CRITICAL']) || $this->isAutomatedAttack() || $this->calculateTraversalDepth() > 5; } /** * Gibt WAF-Regel-Vorschläge zurück */ public function getWafRuleSuggestions(): array { $rules = [ 'Block requests containing ../ or ..\\ patterns', 'Block requests with URL-encoded path traversal sequences', 'Block access to sensitive file extensions (.env, .config, etc.)', ]; $analysis = $this->analyzePattern(); if ($analysis['encoding_type'] !== 'none') { $rules[] = 'Implement URL decoding before path traversal detection'; } if (! empty($analysis['target_files'])) { $rules[] = 'Block access to system configuration files and password files'; } if ($analysis['traversal_depth'] > 3) { $rules[] = 'Limit maximum directory traversal depth'; } return $rules; } /** * Gibt sichere Alternative für File-Access vor */ public function getSecureAlternatives(): array { return [ 'Use file IDs instead of file paths in URLs', 'Implement a file mapping table', 'Restrict file access to a specific directory', 'Use symbolic links instead of direct paths', 'Implement role-based file access controls', 'Validate file paths against an allowlist', ]; } }