bolt cms V3.7.0 xss和远程代码执行漏洞
本文首发于“合天智汇”公众号 作者:ordar123
声明:笔者初衷用于分享与普及网络知识,若读者因此作出任何危害网络安全行为后果自负,与合天智汇及原作者无关!

1. 漏洞环境搭建
github上下载对应版本,这里下载3.7.0.
https://github.com/bolt/bolt/releases
解压后需要重命名以下文件:
mv .bolt.yml.dist .bolt.yml mv composer.json.dist composer.json mv composer.lock.dist composer.lock mv src/Site/CustomisationExtension.php.dist src/Site/CustomisationExtension.php
为了快速搭建这里使用phpstudy,开启apache和mysql

点击网站,创建站点,选择好php版本并创建数据库,记住域名、数据库名称、用户名和密码

配置数据库app/config/config.yml。填好数据库名称、用户名和密码然后保存

然后浏览器访问http://上面自己设置的域名/public即可到安装页面,第一次需要设置管理员账号和密码
http://上面自己设置的域名/public http://上面自己设置的域名/public/bolt # 管理地址

2. 漏洞分析
1、XSS成因分析
该漏洞存在于vendor/bolt/bolt/src/Controller/Backend/Users.php。有两个变量userEntity用于存储和使用以显示此代码中的用户数据。form->isValid(),这表明userEntity是具有编码的输入。也就是说使用userEntity可以对用户输入编码。
下面代码使用userEntity->getDisplayName(),显示未编码的用户输入,所以导致XSS。
switch ($action) { case 'disable': if ($this->users()->setEnabled($id, false)) { $this->app['logger.system']->info("Disabled user '{$user->getDisplayname()}'.", ['event' => 'security']); $this->flashes()->info(Trans::__('general.phrase.user-disabled', ['%s' => $user->getDisplayname()])); } else { $this->flashes()->info(Trans::__('general.phrase.user-failed-disabled', ['%s' => $user->getDisplayname()])); } break; case 'enable': if ($this->users()->setEnabled($id, true)) { $this->app['logger.system']->info("Enabled user '{$user->getDisplayname()}'.", ['event' => 'security']); $this->flashes()->info(Trans::__('general.phrase.user-enabled', ['%s' => $user->getDisplayname()])); } else { $this->flashes()->info(Trans::__('general.phrase.user-failed-enable', ['%s' => $user->getDisplayname()])); } break; case 'delete': if ($this->isCsrfTokenValid() && $this->users()->deleteUser($id)) { $this->app['logger.system']->info("Deleted user '{$user->getDisplayname()}'.", ['event' => 'security']); $this->flashes()->info(Trans::__('general.phrase.user-deleted', ['%s' => $user->getDisplayname()])); } else { $this->flashes()->info(Trans::__('general.phrase.user-failed-delete', ['%s' => $user->getDisplayname()])); } break; default: $this->flashes()->error(Trans::__('general.phrase.no-such-action-for-user', ['%s' => $user->getDisplayname()])); }
2.远程代码执行成因分析

normalizePath()函数在第823行acts的同一文件中定义作为Flysystem的normalizePath()函数的包装器。已经习惯了
获取文件的“真实”路径。这用于验证文件位置等等。
例如,./somedir/../text.txt == ./text.txt == text.txt
所以'./text.txt' 传递给此函数,它返回 'text.txt'
所以,从文件名 'backdoor.php/.' 将其传递给normalizePath()它返回 'backdoor.php' ,这正是我们所需要的。
所以数据流看起来,首先是值'backdoor.php/.' 传递给validateFileExtension()返回NULL,因为后面没有文本最后一个点。所以,extesion过滤器被绕过了。接下来,相同的值是传递给normalizePath(),它删除最后一个“/.”,因为它看起来像它是指向当前目录的路径。最后,文件被重命名为'backdoor.php'
3. 漏洞测试
1. xss
构造payload
xxxxxxxxxx POST /preview/page HTTP/1.1Host: localhost contenttype=pages&title=title&slug=testpage1&teaser=teaser1&body=<script>alert(1)</script>&id=151


2. 远程代码执行
创建一个文件,然后编辑这个文件,写入木马保存。


然后将shell.html重命名危shell.html.php\.

即可变成shell.html.php。

访问该文件即可执行命令

4. 影响版本
Bolt CMS<= 3.7.0
5. 防御方案
1. XSS 使用具有编码值的变量来显示用户信息。使用$userEntity而不是$user 2. RCE 重命名时更改数据流。先把数据传过来normalizePath()数据,然后通过validateFileExtension()。这样,验证函数验证最终值。
相关实验: WordPress social-warfare插件XSS和RCE漏洞
通过实验了解WordPresssocial-warfare插件XSS和RCE漏洞的成因和利用方法,学会在无需身份验证的情况下实现对网站和服务器的控制。
合天智汇:合天网络靶场、网安实战虚拟环境
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)