SPIP 的一个漏洞:你以为过滤了,其实没过滤干净
SPIP 是个老牌 CMS,法国那边用得很多。它后台有个"安全屏"(security screen),专门拦危险输入------PHP 标签、系统命令、各种注入 payload,理论上到了这一层全给你挡回去。
但 CVE-2026-8429 让这个安全屏形同虚设。
怎么回事?一句话:
安全屏确实在干活,但攻击者找到了一条路径------构造的 payload 在到达"真正执行代码的地方"之前,经过了某个处理环节,这个环节把 payload 变形了。变形之后,代码执行点拿到的东西已经不是安全屏当初检查的那个了。
这就很像前端里一个经典问题:你写了个 XSS 过滤器,把 <script> 和 onerror 全拦了。但攻击者传了段 Base64 编码的字符串------过滤器没认出来,放行了。然后下游某个渲染逻辑做了一次 atob(),解码出来的就是 <script>alert(1)</script>。
过滤器和执行器之间多了一步"还原"操作,安全的假象就是这么来的。
js
// 你以为过滤了
const input = atob(userInput); // 下游解码
const safe = sanitize(input); // 过滤
render(safe); // 渲染
// 但实际可能是
const safe = sanitize(userInput); // 过滤的是编码版本------看起来无害
const decoded = atob(safe); // 解码
render(decoded); // 渲染------恶意代码出现了
SPIP 这次的问题本质一样:安全屏检查的是 A,代码执行点拿到的是 B。A 和 B 长得不一样。
具体来说,SPIP 后台有个处理流程:
text
用户输入 → 安全屏检查 → 通过 → 进入模板引擎/代码执行上下文
正常情况下,安全屏会抓出 <?php、system()、eval() 这些危险模式。
但攻击者发现,某些输入经过 SPIP 内部的处理函数后,字符会被转义、拼接或重组。你在输入框里写的东西,安全屏看到的是一种形态,到了代码执行点因为经过了中间处理,变成了另一种形态------而变完之后恰好形成了可执行的 PHP 代码。
写成伪代码大概这种感觉:
js
// 安全屏的逻辑(简化的等价版本)
function securityScreen(input) {
if (input.includes('<?php')) throw new Error('blocked');
if (input.includes('system')) throw new Error('blocked');
return input; // 放行
}
// 下游的处理逻辑
function preprocess(input) {
// 某种字符串处理,比如拼接模板标签、转义反转等
return '<?php ' + input + ' ?>'; // 注意这里------它帮你拼上了 PHP 标签
}
// 事故的发生:
const userInput = 'system("id");'; // 不含 <?php,安全屏放行
const processed = preprocess(userInput); // 变成了 '<?php system("id"); ?>'
eval(processed); // 代码执行
当然实际漏洞比这个绕------牵涉到 SPIP 的模板语法、过滤器绕过技巧、特定的 HTTP 参数组合。但核心问题就是:安全屏和执行点之间信息不对称。
这个漏洞危险在哪?
你需要一个后台账号。但 SPIP 的后台账号门槛不高------很多站点开放注册,或者用了弱密码。一旦进了后台,这个漏洞就能让你从"只能编辑文章"变成"服务器完全控制"。
而且你干了什么很难被发现。安全屏日志显示"检查通过",Web 日志显示正常的 POST 请求,Payload 在传输过程中看起来也不像传统 webshell。只有真正执行了才会暴露------那时候已经晚了。
怎么修?
原则就一句:安全屏检查的是啥,执行点就拿啥。中间别动。
SPIP 4.4.14 的修复思路是重构过滤逻辑,让安全屏覆盖输入的所有可能形态------包括被内部函数处理之后的状态。说白了你不管怎么变形,变形之前和变形之后我都检查一遍。
应用层如果暂时升不了级,几个缓解措施:
- 后台加 IP 白名单或 MFA,先把攻击面缩到最小
- Web 服务用最小权限跑(
www-data,不要root) - 监控后台的异常请求------尤其是带编码内容、非典型参数的 POST
本地复现
需要搭建 SPIP < 4.4.14 环境(Docker 或本地 PHP + MySQL)。核心步骤:
- 用低权限账号登录
/ecrire/ - 在受影响的功能点(模板编辑、特定表单)提交 payload
- 触发渲染,观察命令是否执行
概念验证 payload(实际需根据版本调整触发路径):
text
提交内容包含绕过安全屏的 PHP 片段,如经过编码或利用模板语法的:
[(#EVAL{system('id')})]
注意:具体触发点和 payload 格式因版本而异,以上仅为概念演示。实际复现需参考 VulnCheck 或 SentinelOne 的详细分析调整。
影响版本 :SPIP < 4.4.14 | 修复版本:4.4.14+
前提 :需低权限后台认证 | 参考:SentinelOne 分析 / SPIP 官方安全更新 / VulnCheck Advisory