{
"event": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "\/tmp\/BotDetectionService-groupB.php",
"old_string": " 'settings' => [\n 'enabled' => (bool)$configLoader->get('bot.enabled'),\n 'log_blocked_bots' => (bool)$configLoader->get('bot.log_blocked_bots'),\n 'auto_ufw_blocking' => (bool)$configLoader->get('bot.auto_ufw_blocking'),\n 'block_duration_minutes' => (int)$configLoader->get('bot.block_duration_minutes'),\n 'max_requests_per_minute' => (int)$configLoader->get('bot.max_requests_per_minute')\n ],",
"new_string": " 'settings' => [\n 'enabled' => (bool)$configLoader->get('bot.enabled'),\n 'log_blocked_bots' => (bool)$configLoader->get('bot.log_blocked_bots'),\n 'block_duration_minutes' => (int)$configLoader->get('bot.block_duration_minutes'),\n 'max_requests_per_minute' => (int)$configLoader->get('bot.max_requests_per_minute')\n ],",
"replace_all": false
}
}
{
"tool_response": {
"filePath": "\/tmp\/BotDetectionService-groupB.php",
"oldString": " 'settings' => [\n 'enabled' => (bool)$configLoader->get('bot.enabled'),\n 'log_blocked_bots' => (bool)$configLoader->get('bot.log_blocked_bots'),\n 'auto_ufw_blocking' => (bool)$configLoader->get('bot.auto_ufw_blocking'),\n 'block_duration_minutes' => (int)$configLoader->get('bot.block_duration_minutes'),\n 'max_requests_per_minute' => (int)$configLoader->get('bot.max_requests_per_minute')\n ],",
"newString": " 'settings' => [\n 'enabled' => (bool)$configLoader->get('bot.enabled'),\n 'log_blocked_bots' => (bool)$configLoader->get('bot.log_blocked_bots'),\n 'block_duration_minutes' => (int)$configLoader->get('bot.block_duration_minutes'),\n 'max_requests_per_minute' => (int)$configLoader->get('bot.max_requests_per_minute')\n ],",
"originalFile": "<?php\ndeclare(strict_types=1);\n\nnamespace App\\Services;\n\nuse App\\Helpers\\ConfigLoader;\n\n\/**\n * Bot Detection Service mit fail2ban\/nftables-Integration\n * Blockiert unerwünschte Bots basierend auf MariaDB-Konfiguration\n *\/\nclass BotDetectionService\n{\n private array $config;\n private Logger $logger;\n private string $blockedIpsFile;\n private array $requestCounts = [];\n private RateLimitingService $rateLimiter;\n \n public function __construct()\n {\n $configLoader = ConfigLoader::getInstance();\n \n \/\/ Load ALL configuration directly from MariaDB - NO FALLBACKS\n $this->config = [\n 'settings' => [\n 'enabled' => (bool)$configLoader->get('bot.enabled'),\n 'log_blocked_bots' => (bool)$configLoader->get('bot.log_blocked_bots'),\n 'auto_ufw_blocking' => (bool)$configLoader->get('bot.auto_ufw_blocking'),\n 'block_duration_minutes' => (int)$configLoader->get('bot.block_duration_minutes'),\n 'max_requests_per_minute' => (int)$configLoader->get('bot.max_requests_per_minute')\n ],\n 'logging' => [\n 'blocked_attempts' => (bool)$configLoader->get('bot.logging.blocked_attempts'),\n 'log_file' => $configLoader->get('bot.logging.log_file')\n ],\n 'rate_limiting' => [\n 'enabled' => (bool)$configLoader->get('bot.rate_limiting.enabled')\n ],\n 'actions' => [\n 'block_request' => (bool)$configLoader->get('bot.actions.block_request'),\n 'add_to_ufw' => (bool)$configLoader->get('bot.actions.add_to_ufw'),\n 'return_403' => (bool)$configLoader->get('bot.actions.return_403'),\n 'return_404' => (bool)$configLoader->get('bot.actions.return_404')\n ],\n 'whitelist' => [\n 'user_agents' => json_decode($configLoader->get('bot.whitelist.user_agents') ?? '[]', true) ?: [],\n 'ips' => json_decode($configLoader->get('bot.whitelist.ips') ?? '[]', true) ?: []\n ],\n 'blacklist' => [\n 'user_agents' => json_decode($configLoader->get('bot.blacklist.user_agents') ?? '[]', true) ?: [],\n 'user_agent_patterns' => json_decode($configLoader->get('bot.blacklist.user_agent_patterns') ?? '[]', true) ?: []\n ]\n ];\n \n $this->logger = new Logger();\n $basePath = dirname(__DIR__, 2); \/\/ Go up from \/src\/Services to project root\n $this->blockedIpsFile = $basePath . '\/cache\/blocked_ips.json';\n \n \/\/ Rate limiting from MariaDB - NO JSON FALLBACKS\n $rateLimitConfig = [\n 'enabled' => $this->config['rate_limiting']['enabled'],\n 'primary' => [\n 'requests_per_minute' => (int)$configLoader->get('bot.rate_limiting.primary.requests_per_minute'),\n 'burst_requests' => (int)$configLoader->get('bot.rate_limiting.primary.burst_requests'),\n 'burst_window_seconds' => (int)$configLoader->get('bot.rate_limiting.primary.burst_window_seconds')\n ],\n 'levels' => json_decode($configLoader->get('bot.rate_limiting.levels') ?? '[]', true) ?: [],\n 'tolerance_multipliers' => json_decode($configLoader->get('bot.rate_limiting.tolerance_multipliers') ?? '[]', true) ?: []\n ];\n \n $this->rateLimiter = new RateLimitingService($rateLimitConfig);\n \n \/\/ Lade bestehende blockierte IPs\n $this->loadBlockedIps();\n }\n \n \/**\n * Hauptfunktion: Prüft ob Request blockiert werden soll\n *\/\n public function shouldBlockRequest(): bool\n {\n if (!$this->config['settings']['enabled']) {\n return false;\n }\n \n $clientIp = $this->getClientIp();\n $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';\n \n \/\/ 1. Whitelist-Prüfung (höchste Priorität)\n if ($this->isWhitelisted($clientIp, $userAgent)) {\n $this->logIfEnabled(\"Whitelist match for IP: $clientIp, UA: $userAgent\", 'whitelist_matches');\n return false;\n }\n \n \/\/ 2. Blacklist-Prüfung\n if ($this->isBlacklisted($clientIp, $userAgent)) {\n $this->blockRequest($clientIp, $userAgent, 'blacklist_match');\n return true;\n }\n \n \/\/ 3. Advanced Rate Limiting\n $isAuthenticated = $this->isUserAuthenticated();\n $rateLimitResult = $this->rateLimiter->isRateLimited($clientIp, $userAgent, $isAuthenticated);\n \n if ($rateLimitResult['limited']) {\n $this->handleRateLimitViolation($clientIp, $userAgent, $rateLimitResult);\n return true;\n }\n \n return false;\n }\n \n \/**\n * Whitelist-Prüfung\n *\/\n private function isWhitelisted(string $ip, string $userAgent): bool\n {\n $whitelist = $this->config['whitelist'];\n \n \/\/ Exakte User-Agent Matches\n if (in_array($userAgent, $whitelist['user_agents'] ?? [])) {\n return true;\n }\n \n \/\/ User-Agent Pattern Matches\n foreach ($whitelist['user_agent_patterns'] ?? [] as $pattern) {\n if (preg_match('\/' . $pattern . '\/i', $userAgent)) {\n return true;\n }\n }\n \n \/\/ IP-Ranges\n foreach ($whitelist['ips'] ?? [] as $range) {\n if ($this->ipInRange($ip, $range)) {\n return true;\n }\n }\n \n return false;\n }\n \n \/**\n * Blacklist-Prüfung\n *\/\n private function isBlacklisted(string $ip, string $userAgent): bool\n {\n $blacklist = $this->config['blacklist'];\n \n \/\/ Exakte User-Agent Matches\n if (in_array($userAgent, $blacklist['exact_user_agents'] ?? [])) {\n return true;\n }\n \n \/\/ Einzelne User-Agent Keywords\n foreach ($blacklist['user_agents'] ?? [] as $botAgent) {\n if (stripos($userAgent, $botAgent) !== false) {\n return true;\n }\n }\n \n \/\/ User-Agent Pattern Matches\n foreach ($blacklist['user_agent_patterns'] ?? [] as $pattern) {\n if (preg_match('\/' . $pattern . '\/i', $userAgent)) {\n return true;\n }\n }\n \n \/\/ IP-Ranges\n foreach ($blacklist['ips'] ?? [] as $range) {\n if ($this->ipInRange($ip, $range)) {\n return true;\n }\n }\n \n return false;\n }\n \n \/**\n * Prüft ob User authentifiziert ist\n *\/\n private function isUserAuthenticated(): bool\n {\n if (session_status() === PHP_SESSION_NONE) {\n session_start();\n }\n \n \/\/ Check verschiedene Session-Indikatoren\n return isset($_SESSION['admin_authenticated']) ||\n isset($_SESSION['user_authenticated']) ||\n isset($_SESSION['crm_contact_id']) ||\n !empty($_COOKIE['crm_session']);\n }\n \n \/**\n * Behandelt Rate Limit Verletzungen basierend auf Level\n *\/\n private function handleRateLimitViolation(string $ip, string $userAgent, array $rateLimitResult): void\n {\n $level = $rateLimitResult['level'];\n $action = $rateLimitResult['action'];\n $remainingSeconds = $rateLimitResult['remaining_seconds'] ?? 0;\n \n \/\/ Logging\n $this->logger->warning(\"Rate limit violation: $level | IP: $ip | Action: $action | Remaining: {$remainingSeconds}s\");\n \n switch ($action) {\n case 'log_warning':\n \/\/ Nur loggen, kein Blocking\n break;\n \n case 'temporary_delay':\n \/\/ 2-Sekunden Delay\n sleep(2);\n break;\n \n case 'temporary_block':\n \/\/ Temporärer Block mit HTTP Response\n $this->sendRateLimitResponse($remainingSeconds, $level);\n break;\n \n case 'ufw_block':\n \/\/ UFW-Regel hinzufügen\n $this->addUfwRule($ip, \"rate_limit_$level\");\n $this->sendRateLimitResponse($remainingSeconds, $level);\n break;\n }\n }\n \n \/**\n * Sendet Rate Limit Response\n *\/\n private function sendRateLimitResponse(int $remainingSeconds, string $level): void\n {\n http_response_code(429); \/\/ Too Many Requests\n header('Retry-After: ' . $remainingSeconds);\n header('Content-Type: text\/plain');\n \n $message = \"Rate limit exceeded ($level). \";\n if ($remainingSeconds > 0) {\n $message .= \"Try again in $remainingSeconds seconds.\";\n } else {\n $message .= \"Please slow down your requests.\";\n }\n \n echo $message;\n exit;\n }\n \n \/**\n * Request blockieren und UFW-Regel hinzufügen\n *\/\n private function blockRequest(string $ip, string $userAgent, string $reason): void\n {\n \/\/ Logging\n if ($this->config['logging']['blocked_attempts']) {\n $this->logger->warning(\"Bot blocked: $reason | IP: $ip | UA: \" . substr($userAgent, 0, 100));\n }\n \n \/\/ UFW-Regel hinzufügen\n if ($this->config['actions']['add_to_ufw'] && $this->config['settings']['auto_ufw_blocking']) {\n $this->addUfwRule($ip, $reason);\n }\n \n \/\/ IP zu blockierten IPs hinzufügen\n $this->addToBlockedIps($ip, $reason);\n \n \/\/ HTTP Response senden\n if ($this->config['actions']['return_403']) {\n http_response_code(403);\n header('Content-Type: text\/plain');\n echo \"Access denied. Automated traffic not permitted.\";\n exit;\n } elseif ($this->config['actions']['return_404']) {\n http_response_code(404);\n header('Content-Type: text\/plain');\n ... [TRUNCATED-50d005109cad44fc]",
"structuredPatch": [
{
"oldStart": 26,
"oldLines": 7,
"newStart": 26,
"newLines": 6,
"lines": [
" 'settings' => [",
" 'enabled' => (bool)$configLoader->get('bot.enabled'),",
" 'log_blocked_bots' => (bool)$configLoader->get('bot.log_blocked_bots'),",
"- 'auto_ufw_blocking' => (bool)$configLoader->get('bot.auto_ufw_blocking'),",
" 'block_duration_minutes' => (int)$configLoader->get('bot.block_duration_minutes'),",
" 'max_requests_per_minute' => (int)$configLoader->get('bot.max_requests_per_minute')",
" ],"
]
}
],
"userModified": false,
"replaceAll": false
}
}