/* ========================================================= * 站外跳转硬拦截(HTTP/Meta/JS),保留当前页 * - 拦截一切指向站外(不同根域)的 Location/Refresh 头 * - 清洗页面中的 与 JS 跳转 * - 添加 CSP 导航限制:navigate-to 'self' * 说明:不会影响同根域内部跳转(如非 www -> www) * =======================================================*/ // 供根域名判断使用(与下方你的强制 www 里列表一致即可) $__SAFE_PUBLIC_SUFFIXES = [ 'com','net','org','gov','edu','cn','cc','tv','xyz','icu','top','me','biz','club','site','online', 'store','link','fun','pro','vip','space','tech','work','live','cloud','app','dev','page','buzz', 'bond','pw','cyou','wang','com.cn','net.cn','org.cn','gov.cn','co.uk' ]; // 计算根域(eTLD+1) function __mac_base_domain($host){ global $__SAFE_PUBLIC_SUFFIXES; $host = strtolower(trim($host)); if ($host === '' || strpos($host, '.') === false) return $host; $parts = explode('.', $host); for ($i = count($parts) - 1; $i > 0; $i--) { $possible_suffix = implode('.', array_slice($parts, $i)); if (in_array($possible_suffix, $__SAFE_PUBLIC_SUFFIXES, true)) { $domain_part = $parts[$i - 1] ?? ''; return ($domain_part ? $domain_part . '.' : '') . $possible_suffix; } } // 兜底:取最后两段 $n = count($parts); return $n >= 2 ? $parts[$n-2] . '.' . $parts[$n-1] : $host; } // URL 是否指向站外(不同根域) function __mac_is_external($url, $currentHost){ if ($url === '' || $url[0] === '/' || strpos($url, '?') === 0 || strpos($url, '#') === 0) { return false; // 相对地址视为站内 } if (strpos($url, '//') === 0) { // 协议相对 $url = 'http:' . $url; } $p = @parse_url($url); $targetHost = strtolower($p['host'] ?? ''); if ($targetHost === '') return false; // 无 host,当作站内 $curBase = __mac_base_domain($currentHost); $tarBase = __mac_base_domain($targetHost); return $curBase !== $tarBase; } // 全局标记:是否拦截过站外跳转 $GLOBALS['__mac_blocked_external_redirect'] = false; // 1) HTTP 头部层面拦截(Location/Refresh) function __mac_headers_redirect_guard(){ $headers = headers_list(); $host = strtolower($_SERVER['HTTP_HOST'] ?? ''); $blocked = false; foreach ($headers as $h) { // Location if (stripos($h, 'Location:') === 0) { $loc = trim(substr($h, 9)); if (__mac_is_external($loc, $host)) { header_remove('Location'); // 取消跳转 $blocked = true; } } // Refresh: 0;url=... if (stripos($h, 'Refresh:') === 0) { // 无论目标为何,统一移除 Refresh(常用于跳转) header_remove('Refresh'); $blocked = true; } } if ($blocked) { // 改回 200,避免浏览器按 3xx 行为处理 http_response_code(200); header('Cache-Control: no-store, max-age=0'); header('Pragma: no-cache'); // 强化:限制浏览器端导航只允许到本站 header("Content-Security-Policy: navigate-to 'self'; base-uri 'self'; frame-ancestors 'self'"); header('X-Redirect-Blocked: 1'); $GLOBALS['__mac_blocked_external_redirect'] = true; } } // 注册头部回调(在发送前执行,可移除/改写) if (function_exists('header_register_callback')) { header_register_callback('__mac_headers_redirect_guard'); } // 2) 输出内容清洗(Meta Refresh / JS 跳转 / 外部 ) function __mac_output_sanitizer($buffer){ $host = strtolower($_SERVER['HTTP_HOST'] ?? ''); // ... url=...> $buffer = preg_replace_callback( '/]*http-equiv=["\']?refresh["\']?[^>]*>/i', function($m) use ($host){ $tag = $m[0]; if (preg_match('/content\s*=\s*["\']?([^"\'>]+)["\']?/i', $tag, $c)) { $content = $c[1]; if (preg_match('/url\s*=\s*([^;,\s]+)/i', $content, $u)) { $url = trim($u[1], '\'"'); if (__mac_is_external($url, $host)) { return ''; // 直接移除 } } } return $tag; } , $buffer); // 指向站外时移除(避免相对链接被“带走”) $buffer = preg_replace_callback( '/]*href=["\']([^"\']+)["\'][^>]*>/i', function($m) use ($host){ $href = $m[1]; return __mac_is_external($href, $host) ? '' : $m[0]; } , $buffer); // JS:location / location.href / location.assign / location.replace $buffer = preg_replace_callback( '/(?:window\.)?(?:top\.)?location(?:\.href)?\s*=\s*(["\'])([^"\']+)\1\s*;?/i', function($m) use ($host){ return __mac_is_external($m[2], $host) ? '/* blocked external redirect */' : $m[0]; } , $buffer); $buffer = preg_replace_callback( '/(?:window\.)?(?:top\.)?location\.(assign|replace)\s*\(\s*(["\'])([^"\']+)\2\s*\)\s*;?/i', function($m) use ($host){ return __mac_is_external($m[3], $host) ? '/* blocked external redirect */' : $m[0]; } , $buffer); return $buffer; } ob_start('__mac_output_sanitizer'); // 3) 兜底:若恶意代码 header()+exit 过早结束,输出最小安全页 register_shutdown_function(function(){ if (!empty($GLOBALS['__mac_blocked_external_redirect'])) { if (!headers_sent()) { header_remove('Location'); header_remove('Refresh'); http_response_code(200); header('Content-Type: text/html; charset=utf-8'); header("Content-Security-Policy: navigate-to 'self'; base-uri 'self'; frame-ancestors 'self'"); } // 若尚无任何输出,给出最小提示页(保持在当前站) $buf = ''; if (ob_get_level() > 0) { $buf = (string)ob_get_contents(); } if (trim($buf) === '') { echo "安全拦截

已拦截站外跳转

为保护您的安全,本次页面跳转已被阻止。

"; } } });