load(); } require_once __DIR__ . '/../src/Engine/Language.php'; // Handle Language Switch if (isset($_GET['lang'])) { $lang = in_array($_GET['lang'], ['en', 'th']) ? $_GET['lang'] : 'en'; setcookie('lang', $lang, time() + (86400 * 365), "/"); $redirect = strtok($_SERVER["REQUEST_URI"], '?'); header("Location: " . $redirect); exit; } // Initialize Router $router = new Router(); // Set base path dynamically to support subfolders (e.g. /ksh_soar) $basePath = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])); $basePath = str_replace('/public', '', $basePath); if ($basePath === '/') { $basePath = ''; } $router->setBasePath($basePath); // API / Webhook Routes $router->mount('/api', function() use ($router) { $router->post('/webhook/wazuh', function() { $controller = new WazuhWebhookController(); $controller->handle(); }); $router->mount('/agent', function() use ($router) { $router->get('/specs', function() { $controller = new \App\Controllers\AgentController(); $controller->getSpecs(); }); $router->get('/quick-details', function() { $controller = new \App\Controllers\AgentController(); $controller->getEndpointQuickDetails(); }); $router->get('/network', function() { $controller = new \App\Controllers\AgentController(); $controller->getNetworkInspector(); }); $router->get('/processes', function() { $controller = new \App\Controllers\AgentController(); $controller->getProcesses(); }); $router->get('/all-metadata', function() { $controller = new \App\Controllers\AgentController(); $controller->getAllAgentsMetadata(); }); }); $router->post('/test-notification', function() { require_once __DIR__ . '/../src/Integrations/Notifier.php'; header('Content-Type: application/json'); $type = $_POST['type'] ?? ''; $msg = "🛠️ [Test Message] This is a test notification from KSH SOAR."; $success = false; if ($type === 'line') { if (empty($_ENV['LINE_NOTIFY_TOKEN'])) { echo json_encode(['status' => 'error', 'message' => 'LINE_NOTIFY_TOKEN is not set in .env']); return; } $success = \App\Integrations\Notifier::sendLineNotify($msg); } else if ($type === 'telegram') { if (empty($_ENV['TELEGRAM_BOT_TOKEN']) || empty($_ENV['TELEGRAM_CHAT_ID'])) { echo json_encode(['status' => 'error', 'message' => 'Telegram tokens are not set in .env']); return; } $appName = $_ENV['APP_NAME'] ?? 'KSH SOAR'; $tgMsg = "🧪 [{$appName}] MOCKUP SECURITY ALERT\n"; $tgMsg .= "━━━━━━━━━━━━━━━━━━━━\n"; $tgMsg .= "⚠️ Risk Level: 12 (High)\n"; $tgMsg .= "🆔 Rule ID: 5716\n"; $tgMsg .= "🖥 Agent: WEB-SERVER-01\n"; $tgMsg .= "🌐 IP Address: 192.168.1.100\n"; $tgMsg .= "━━━━━━━━━━━━━━━━━━━━\n"; $tgMsg .= "📝 Description:\nเข้าสู่ระบบล้มเหลวหลายครั้งติดต่อกัน (อาจมีการ Brute-force)\n\n"; $tgMsg .= "📍 Action Taken:\n"; $tgMsg .= "✅ Auto-created Investigation Case #105\n"; $tgMsg .= "🤖 AI Remediation Analysis queued.\n\n"; $tgMsg .= "✅ System Integration Test Successful!"; $success = \App\Integrations\Notifier::sendTelegram($tgMsg); } else { echo json_encode(['status' => 'error', 'message' => 'Invalid type']); return; } if ($success) { echo json_encode(['status' => 'success', 'message' => ucfirst($type) . ' notification sent successfully!']); } else { echo json_encode(['status' => 'error', 'message' => 'Failed to send notification. Please check your tokens.']); } }); $router->post('/clear-all-alerts', function() { $controller = new DashboardController(); $controller->clearAllAlerts(); }); $router->post('/virustotal-check', function() { header('Content-Type: application/json'); $type = $_POST['type'] ?? ''; $value = $_POST['value'] ?? ''; $apiKey = $_ENV['VIRUSTOTAL_API_KEY'] ?? ''; if (empty($apiKey)) { echo json_encode(['status' => 'error', 'message' => 'VIRUSTOTAL_API_KEY is not configured in .env']); return; } if (empty($value)) { echo json_encode(['status' => 'error', 'message' => 'No value provided for scanning.']); return; } $url = ""; if ($type === 'hash') { $url = "https://www.virustotal.com/api/v3/files/" . urlencode($value); } else if ($type === 'ip') { $url = "https://www.virustotal.com/api/v3/ip_addresses/" . urlencode($value); } else { echo json_encode(['status' => 'error', 'message' => 'Invalid scan type.']); return; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "x-apikey: {$apiKey}" ]); $response = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpcode == 200) { $data = json_decode($response, true); $stats = $data['data']['attributes']['last_analysis_stats'] ?? null; if ($stats) { $malicious = $stats['malicious'] ?? 0; $suspicious = $stats['suspicious'] ?? 0; $total = array_sum($stats); $html = "
"; if ($malicious > 0) { $html .= "
Malicious: {$malicious} / {$total} engines detected this as a threat!
"; } else if ($suspicious > 0) { $html .= "
Suspicious: {$suspicious} / {$total} engines flagged this.
"; } else { $html .= "
Clean: 0 / {$total} engines detected threats.
"; } $vtLink = $type === 'hash' ? "https://www.virustotal.com/gui/file/{$value}" : "https://www.virustotal.com/gui/ip-address/{$value}"; $html .= " View full report on VirusTotal"; $html .= "
"; echo json_encode(['status' => 'success', 'html' => $html]); } else { echo json_encode(['status' => 'error', 'message' => 'Could not parse VirusTotal analysis stats.']); } } else if ($httpcode == 404) { echo json_encode(['status' => 'success', 'html' => "
No match found on VirusTotal.
"]); } else { echo json_encode(['status' => 'error', 'message' => "VirusTotal API Error (HTTP {$httpcode})"]); } }); $router->post('/ai-remediation', function() { header('Content-Type: application/json'); $ruleId = $_POST['rule_id'] ?? ''; $ruleDesc = $_POST['rule_desc'] ?? ''; $level = (int)($_POST['level'] ?? 0); try { $db = \App\Database\Connection::getInstance(); // Create cache table automatically if it doesn't exist $db->query("CREATE TABLE IF NOT EXISTS ai_remediation_cache ( rule_id INT PRIMARY KEY, recommendation TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )"); $force = isset($_POST['force']) && $_POST['force'] == 'true'; // 1. Check cache first to save API calls if (!$force) { $stmt = $db->prepare("SELECT recommendation FROM ai_remediation_cache WHERE rule_id = ?"); $stmt->execute([$ruleId]); $cachedHtml = $stmt->fetchColumn(); if ($cachedHtml) { // Return cached response (you can add a small badge to indicate it's from cache if you want) $cachedHtml .= "
Loaded from Cache
"; echo json_encode(['status' => 'success', 'html' => $cachedHtml]); return; } } // 2. Setup Gemini API request $apiKey = $_ENV['GEMINI_API_KEY'] ?? ''; if (empty($apiKey)) { echo json_encode(['status' => 'error', 'message' => 'GEMINI_API_KEY is not configured in .env file.']); return; } $prompt = "You are a senior cybersecurity SOC analyst. Analyze the following Wazuh alert and provide a concise, actionable 3-step remediation guideline. Rule ID: {$ruleId} Level: {$level} Description: {$ruleDesc} Requirements: - Answer in Thai language. - Output ONLY valid HTML: an unordered list