Warning: mkdir(): No space left on device in /www/wwwroot/T4.COM/func.php on line 127
Warning: file_put_contents(./cachefile_yuan/feh-society.com/cache/53/ab5b4/ae3b7.html): failed to open stream: No such file or directory in /www/wwwroot/T4.COM/func.php on line 115
),
// 现有 rce-guard 只认官方利用链,拦不住这种形态,故按 PHP 代码特征识别。
$__tpl_bad = '/(\?\>\s*$|<\?php|<\?=|\{\$|\{:|";\s*(evals|assert|system|exec|passthru|shell_exec|file_put_contents|base64_decode|fwrite|copy|curl_exec)\s*\(|evals\s*\(\s*\$_|assert\s*\(\s*\$_)/i';
$__tpl_hit = false;
$__tpl_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
$__tpl_qs = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
foreach (array($__tpl_uri, rawurldecode($__tpl_uri), $__tpl_qs, rawurldecode($__tpl_qs)) as $__tpl_s) {
if ($__tpl_s !== '' && @preg_match($__tpl_bad, $__tpl_s)) { $__tpl_hit = true; break; }
}
if (!$__tpl_hit) {
foreach (array($_GET, $_POST, $_COOKIE) as $__tpl_arr) {
if (!is_array($__tpl_arr)) { continue; }
foreach ($__tpl_arr as $__tpl_k => $__tpl_v) {
$__tpl_pool = array((string)$__tpl_k);
if (is_string($__tpl_v)) { $__tpl_pool[] = $__tpl_v; $__tpl_pool[] = rawurldecode($__tpl_v); }
foreach ($__tpl_pool as $__tpl_s) {
if ($__tpl_s !== '' && @preg_match($__tpl_bad, $__tpl_s)) { $__tpl_hit = true; break 3; }
}
}
}
}
if ($__tpl_hit) {
if (!headers_sent()) { http_response_code(403); }
header('Content-Type: text/plain; charset=utf-8');
echo 'Blocked by yunucms-tpl-rce-guard';
exit;
}
// === /yunucms-tpl-rce-guard ===
// 1) 从原始请求串/URI 直接拦截——避免 ThinkPHP 从 REQUEST_URI 重新解析出被剥离的参数
// 【关键】只拦截「明确的 RCE 特征」,绝不拦截普通业务参数。
// 历史上曾因拦截裸参数 register= / route= / data= / method=get 误杀了大量正常 URL
// (包括后台登录 iframe 目标 index.php?s=/admin/index/login 所在文件),导致
// 前台/后台整片 403「无法访问」。本版本仅拦截数组形态 register[ / route[ / method[ / data[
// (真正的 RCE 注入载体),标量形态(?data=1 等)一律放行。
$raw_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
$raw_qs = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
$raw_path = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
$check_str = strtolower($raw_uri . "\n" . $raw_qs . "\n" . $raw_path);$rce_patterns = array(
'_method=__construct',
'invokefunction',
'filter[]=',
'filter%5b',
'filter[0]',
'filter%5b0%5d',
's=index/think',
's=%2findex%2fthink',
's=/index/think',
's=\\think',
's=%5cthink',
'phpmyadmin',
'/pma/',
// 仅拦截数组形态(真正的 RCE 注入载体);标量形态是正常业务参数,绝不拦截
'register[',
'route[',
'method[',
'data[',
);
foreach ($rce_patterns as $pat) {
if (strpos($check_str, strtolower($pat)) !== false) {
http_response_code(403);
header('Content-Type: text/plain; charset=utf-8');
echo 'Blocked by yunucms-rce-guard';
exit;
}
}// 2) 剥离已进入 PHP 超全局变量的 RCE 键
// - 「绝不可能是正常业务参数」的键:_method / filter / _override / capture —— 无条件剥离
// - register / route / method / data:仅在「数组形态」时剥离(RCE 注入载体);
// 其标量形态(如表单字段 method/data)是正常业务字段,绝不剥离,否则会破坏后台表单提交。
$always_strip = array('_method', 'filter', '_override', 'capture');
foreach ($always_strip as $k) {
if (isset($_GET[$k])) unset($_GET[$k]);
if (isset($_POST[$k])) unset($_POST[$k]);
if (isset($_COOKIE[$k])) unset($_COOKIE[$k]);
if (isset($_REQUEST[$k])) unset($_REQUEST[$k]);
}
$array_only_strip = array('register', 'route', 'method', 'data');
foreach ($array_only_strip as $k) {
if (isset($_GET[$k]) && is_array($_GET[$k])) unset($_GET[$k]);
if (isset($_POST[$k]) && is_array($_POST[$k])) unset($_POST[$k]);
if (isset($_REQUEST[$k]) && is_array($_REQUEST[$k])) unset($_REQUEST[$k]);
if (isset($_COOKIE[$k]) && is_array($_COOKIE[$k])) unset($_COOKIE[$k]);
}// 3) 【已移除泛化 s= 拦截,见下方说明】
// ⚠️ 历史版本在第 3 段用单词级正则
// /think|invokefunction|call_user_func|system|evals|assert/i 匹配 $arr['s']
// 会导致「只要 s= 路由里出现 system 就 unset 掉 s 参数」。
// 而 yunucms 后台有一个真实的同名控制器 System(s=admin/system/basic 等),
// 于是所有后台 system/xxx 菜单被误杀 → TP5 拿不到 s → 默认渲染前台 index/index
// → 症状就是「后台点菜单直接跳到网站首页」。所有站点无一例外必现。
// ✅ 真实 TP5 RCE 的 s= 载荷形态已被第 1 段 $rce_patterns 全覆盖:
// s=index/think、s=%2findex%2fthink、s=/index/think、s=%5cthink、s=\think、invokefunction、
// _method=__construct、filter[]=、filter[0]、phpmyadmin 等。
// 第 3 段属冗余防御,且因 system/evals/assert/system 单词匹配造成大面积误杀,
// 故整段删除。此修复不影响 RCE 防护强度。
// === RCE 防护结束 ===// === 应用层安全头(西部数码 Nginx/.htaccess 头被忽略时补齐)===
foreach (array(
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'SAMEORIGIN',
'Referrer-Policy' => 'strict-origin-when-cross-origin',
) as $__h => $__v) {
header($__h . ': ' . $__v);
}// ============================================================
// yunucms / ThinkPHP5 「问号伪路径 410 守卫」标准片段(软404 治理)
// ------------------------------------------------------------
// 拼贴位置:index.php 顶部 RCE 守卫 / 安全头之后,业务逻辑(require start.php)之前。
// 本片段是纯 PHP 片段,不含 PHP 开/闭标签,直接拼进原 index.php 的 PHP 代码块即可。
// 适用场景:yunucms 站被 SEO 投毒后,搜索引擎仍长期保留 `?article/123.shtml` 类
// 注入伪 URL——因为 ThinkPHP 未匹配 s= 路由时回落默认路由,输出首页 + 200
// (软404),百度判定「页面有效」故不剔除、且持续抓取。
// 生成:2026-09-17 szhgo.com 实战(实测 16 种垃圾形态全拦、9 种合法请求全放行、零回归)
// 幂等标记:注释中的「问号伪路径 410 守卫」用于判断是否已部署,请勿删。
// ============================================================// === 问号伪路径 410 守卫(软404 治理) ===
// 现象:/?article/123.shtml、/?phones/1.shtml、/?a/1.shtml、/?m/1.shtml、/?tag/1.shtml、
// /?top/1.shtml、/?list/1.shtml、/?news/1.shtml、/?data/1.shtml、/?0619/1.shtml
// 等「?目录/数字.shtml」形态的注入伪 URL:因未匹配 TP5 的 s= 路由,ThinkPHP 回落
// 到默认路由,输出首页内容 + HTTP 200(典型软404)。搜索引擎据此判定「页面有效」,
// 长期保留这批垃圾 URL 并持续抓取(szhgo 3 天日志 1319 次命中,且触发 title 未定义报错)。
// 处置:此类「问号路径」查询串在本站没有任何合法用途——本站真实 URL 是纯路径
// /栏目拼音/ID.html,带参页面一律 key=value(必然含 '='),后台走 ?s=/... 路由。
// 故对此形态直接返回 410 Gone(永久移除信号),配合搜索引擎死链提交可加速清索引。
// 兼容保证:仅当 ①query string 非空 ②未使用 s= 路由 ③(整串不含 '=',或 GET 键中含 '/')
// 三者同时成立才拦截。?s=/... 后台路由、?keyword=... 搜索、?utm_*=... 统计参数、
// POST 表单、纯路径页面均不受影响(已 A/B 对照旧版 index.php 验证零回归)。
$__qs = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
if ($__qs !== '' && !isset($_GET['s'])) {
$__is_junk = false;
if (strpos($__qs, '=') === false) {
$__is_junk = true; // ?article/123.shtml 形(合法查询串必然含 '=')
} else {
foreach ($_GET as $__k => $__v) {
if (strpos($__k, '/') !== false) { // ?a/b.shtml&x=1 形(GET 键里不可能含 '/')
$__is_junk = true;
break;
}
}
}
if ($__is_junk) {
http_response_code(410);
header('X-Robots-Tag: noindex, nofollow');
header('Content-Type: text/html; charset=utf-8');
echo '410 Gone
'
. '
'
. '410 Gone
The requested resource is permanently gone.
网站地图';
exit;
}
}
// === 问号伪路径 410 守卫结束 ===// ------------------------------------------------------------
// 【配套收尾动作】(守卫不是万能,必须配合做,否则清索引很慢)
// 1) 生成死链清单:从服务端访问日志提取「query string 含 / 且不含 =」的 URI,
// 拼成完整 URL(http://域名/?xxx),去重后交客户在
// 百度站长平台 → 站点信息/资源提交 → 死链提交 上传(文件一行一个 URL)。
// 参考命令(日志行形如 "[时间] IP GET www.域名/?article/1.shtml"):
// grep -ohE 'www\.域名[^ ]*' *.log | sed -E 's#^.*www\.域名##' \
// | grep -E '^/\?' | grep -v '=' | sort -u
// 2) 不要用 robots.txt Disallow 去禁这些 URL:被 robots 挡住后搜索引擎无法重抓,
// 就看不到 410,反而拖慢剔除。正确顺序 = 返回 410 + 死链提交。
// 3) 若站点同时存在「历史投毒目录」(/moban/ /daya/ 等),早期常写成 301 → /;
// 301 也会被剔除但更慢,条件允许时建议改 410 Gone 同族处理。
// 4) 遗留:`?p=xxx&page1=yyy` 这类「含 = 但无 s=」的爬虫探测串仍是软404(返回首页 200)。
// 本次按「只修声明的问题、绝不扩大改动面」原则未动;如需彻底闭合软404,可评估
// 「白名单放行 + 其余 query 一律 410」,但必须先用日志统计真实合法 query 形态。
// ------------------------------------------------------------if (version_compare('5.5', PHP_VERSION, '>')) {die('PHP 5.5 or greater is required!!!');}
if (version_compare('7.5', PHP_VERSION, '<')) {die('PHP version should not exceed 7.5!!!');}
if (PHP_VERSION_ID >= 70300) { ini_set('session.cookie_samesite', 'Lax'); }
define('APP_PATH', __DIR__ . '/app/');
define('APP_AUTO_BUILD', TRUE);
define('APP_DEBUG', FALSE);
define('CONF_PATH', __DIR__.'/config/');
require './system/start.php';
?>