ThinkPHP模板变量输出必须手动htmlspecialchars,因{$name}默认不转义;富文本需htmlpurifier白名单过滤;禁用{php}标签并升级至8.1+启用security_mode;回调名等参数须白名单校验。

模板变量输出必须手动 htmlspecialchars,别信 {$name} 默认安全
ThinkPHP 模板引擎的 {$name} 语法默认不做任何转义,原样输出变量内容。攻击者传入 <script>alert(1)</script>,页面就会直接执行——这不是漏洞,是设计如此。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 所有用户可控变量输出到 HTML 上下文,必须显式包裹
htmlspecialchars():{:htmlspecialchars($name, ENT_QUOTES, 'UTF-8')} - 不要依赖全局
default_filter配置,它对所有模板变量一视同仁,可能把合法 JSON 字段里的双引号也转义掉,导致前端解析失败 - 若需批量处理,可在控制器赋值前统一过滤:
$this->assign('title', htmlspecialchars($input['title'] ?? '', ENT_QUOTES, 'UTF-8'))
富文本字段不能用 htmlspecialchars,得上 htmlpurifier 或白名单过滤
新闻正文、商品描述这类字段允许部分 HTML(如 <p>、<strong>),但禁用 <script>、onerror=、javascript: 等危险标签和属性。此时 htmlspecialchars() 会把所有标签变成纯文本,彻底破坏格式。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 服务端引入
htmlpurifier库,配置白名单:$config = HTMLPurifier_Config::createDefault(); $config->set('HTML.Allowed', 'p,strong,ul,ol,li,a[href|title],img[src|alt]'); - 避免用正则“删掉 script 标签”,正则无法应对嵌套、注释绕过、Unicode 变体等手法
- 前端富文本编辑器(如 Quill、Tiptap)也需开启 XSS 过滤,但不能只靠前端——服务端校验才是最后一道防线
禁止模板中执行 PHP 代码,关闭 {php} 标签并剥离残留
ThinkPHP 默认模板引擎仍支持 {php}...{/php} 语法,攻击者可通过探测载荷(如 {php}phpinfo(){/php})判断是否启用原生 PHP 执行,进而触发 RCE。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 在
config/template.php中设置'tpl_replace_string' => ['{php}' => '{notag}', '{/php}' => '{/notag}'],让解析器忽略该标签 - 额外加一层行为钩子,在模板读取后做字符串级清洗:
str_replace(['{php}', '{/php}'], '', $content) - 升级到 ThinkPHP 8.1+ 并启用
security_mode => true,该版本已默认剥离 AST 层级的原生 PHP 节点
回调名、文件路径、JSONP callback 参数必须白名单校验
这类参数不进 HTML、不进 SQL,但会被拼进 URL、shell 命令或文件系统路径,htmlspecialchars() 和整型转换完全无效。例如 callback=userInput,攻击者填 callback=alert(1)// 就能污染 JSONP 响应。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 严格白名单匹配:
in_array(input('callback'), ['cb_success', 'cb_fail']),而不是试图“过滤掉括号” - 文件路径类参数(如
template=xxx)必须限制根目录:str_starts_with(input('template'), 'email/') && !str_contains(input('template'), '..') - URL 类参数(如跳转地址)必须双重校验:
filter_var($url, FILTER_VALIDATE_URL)+ 域名白名单(如只允许example.com子域)
最常被忽略的是上下文切换:同一个参数,在日志里要原样记,在 HTML 里要转义,在文件路径里要白名单,在 SQL 里要绑定。没有银弹,只有按用途选函数——input('x') 拿到的是原始输入,它本身不带安全语义。



















