文章总结: vBulletin6.2.2前版本模板runMaths方法存在预认证RCE。该方法正则过滤后直接调用eval,攻击者利用XOR与phpfuck技巧在仅限数字和运算符条件下构造PHP函数调用,通过公开路由无需登录即可执行命令。官方已移除eval修复,建议立即升级,临时可用WAF拦截。 综合评分: 94 文章分类: 漏洞分析,WEB安全,漏洞POC,漏洞预警
vBulletin 模板引擎的致命算术:一个正则表达式引发的预认证RCE
幻泉之洲
2026年7月29日 10:12 北京
在小说阅读器读本章
去阅读
vBulletin 6.2.2 之前的版本中,模板运行时方法
runMaths因过滤不严格将用户输入丢进eval(),攻击者无需登录就能通过一个巧妙构造的{vb:math}标签执行任意 PHP 代码。这不是理论风险——公开的 PoC 已完整演示了如何借助 XOR 和古老的 phpfuck 技巧,把一串看似人畜无害的数学表达式变成操作系统命令执行的跳板。
一个本不该出现的 eval
出问题的代码在 /includes/vb5/template/runtime.php 的 runMaths 方法里。这个方法本意是处理模板中的 {vb:math} 宏,用来做一些简单的动态计算。常见的用法大概是计算页码、统计数字,或者格式化日期之类。
但它的实现方式让人捏一把汗。它把从模板传入的 $str 参数用一段正则“清洗”后,直接喂给了 eval():
$str = preg_replace(‘#([^+-*=/()\d\^<>&|.]*)#’, ”, $str); // … $status = @eval(“\$str = $str;”);
正则的意思是:只保留数字、数学运算符、括号和二进制位运算符(包括 ^``&``|``<``> 等),其余字符全部删掉。看起来好像把危险函数调用、引号、分号这类东西都挡在了门外,但实际效果跟纸糊的一样。
XOR 成了打开大门的钥匙
PHP 的弱类型和位运算特性在这里变成了一把万能钥匙。因为 XOR(^)在允许列表中,攻击者可以利用 phpfuck 技术——一种通过 XOR 两个不可见字符来拼出任意 ASCII 字符的技巧——绕过正则限制,在只能使用数字和运算符的条件下构造出完整的函数调用。
举个例子,你看到的可能是 ((1)^(2)) 和一堆异或组合,但在 PHP 眼里,这就是一串合法变量名或函数名。phpfuck 的核心正是:用 1 和 2 这些看似无害的数字,异或出 s、y、s、t、e、m……最终拼出 system。然后再通过类似方式构造括号和参数,实现 system('任意命令')。
这种绕过方式并不新鲜,在 CTF 比赛里经常出现。但被用在一个拥有数十万装机量的成熟 CMS 里,就暴露出一个很可怕的问题:开发者在写这行 eval 的时候,显然低估了“只能输入数字和运算符”这种限制的脆弱性。
最致命的是:不需要登录
通常这种模板层面的注入需要管理员登录后台去编辑模板。但 vBulletin 有一个公开的路由 ajax/render/[template_name],允许未认证用户渲染指定模板,并且会解析其中的 {vb:math} 标签。换句话说,攻击者根本不用拿到任何权限,只需要向目标 vBulletin 站点发送一个精心构造的 POST 请求,指定模板名为 pagenav(分页导航),并把 pagenav[pagenumber] 参数赋值为我们的 phpfuck payload,就可以触发 runMaths 里的 eval。
pagenav 模板里正好有这么一段:
{vb:set pagenav.currentpage, {vb:raw pagenav.pagenumber}}
{vb:raw} 会原样输出用户传入的 pagenumber,然后 {vb:set} 计算时就可能经过 runMaths,于是攻击链就形成了。整个过程没有认证检查,没有 CSRF 令牌校验。
PoC 告诉我们:这是实打实的 RCE
SSD Secure Disclosure 公布的 Exploit 脚本用不了几行代码。它拼 payload 的核心逻辑就是遍历要执行的命令字符串,把每个字符的 ASCII 码用数字异或表示,然后通过 pagenav[pagenumber] 注入,最后在返回内容里抓取命令输出。我在自己搭建的测试环境里跑了一下,成功率接近 100%,速度也很快——每次命令执行延迟不过一两秒。
说实话,这种漏洞放在 2026 年有点离谱。PHP 社区从十几年前就反复警告避免使用 eval(),尤其是和用户输入有任何间接接触时。vBulletin 不是第一个在这上面栽跟头的项目,但这次影响的版本跨度大——6.2.1 及之前、6.1.6 及之前全部中招,而很多站点因为定制化或怕兼容性问题并不会第一时间升级。
修复简单,但暴露的问题不简单
官方在 vBulletin 6.2.2 和 6.1.6 的安全补丁里已经移除了 eval(),改用更安全的数学表达式解析器。补丁本身很小,但我觉得更值得关注的是这次事故反映出的开发习惯:为了图省事,把模板逻辑和代码执行边界模糊化,最终让一个纯展示层的东西变成了命令执行入口。
如果你现在还在用老版本,别等了,立马更新。补丁地址:https://forum.vbulletin.com/forum/vbulletin-announcements/vbulletin-announcements_aa/4509404-vbulletin-6-2-2-is-available。如果因为各种原因不能更新,至少用 WAF 规则拦截 ajax/render/pagenav 路由,并严格过滤 pagenav[pagenumber] 参数值中的非数字字符——但这只是临时的止血带,真正的问题在 runMaths 本身。
一个小建议:别再把模板引擎当脚本解释器了
模板引擎的职责是分离逻辑和视图,不是给视图开一扇执行代码的后门。类似 {vb:math} 这种功能看似方便,多数时候只是为了算个页码,根本用不到图灵完备的表达式。用白名单函数库或者沙箱化 DSL 替代 eval(),代价不高,却能从根本上堵死这类漏洞。vBulletin 这次的教训够深刻了。
参考资料
[1] https://ssd-disclosure.com/vbulletin-runtime-template-runmaths-preauth-rce/
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:幻泉之洲 《vBulletin 模板引擎的致命算术:一个正则表达式引发的预认证RCE》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论