Skip to content

泛微 ecology 8.x && 9.x 前台SQL注入

  • 泛微 ecology 9.x 补丁版本号 <= v10.56
  • 泛微 ecology 8.x 补丁版本号 <= v10.56

由上面补丁版本,我们需要到官网下载两个补丁包:

1. https://www.weaver.com.cn/cs/package/Ecology_security_20230418_v9.0_v10.57_deta.zip?v=20230420

2. https://www.weaver.com.cn/cs/package/Ecology_security_20221014_v10.55.zip?v=20230420

以确保我们能够根据两个版本的补丁包去精确定位漏洞位置

将这两个补丁包解压后,先用idea打开其中一个目录,然后使用idea自带的比较对象功能去比较这两个补丁包:

image

image

刚开始,我对比的时候自己也很费劲,不知道如何定位漏洞位置,后面静下心来根据时间看漏洞通告在4.18号,我就想着根据文件日期去看,看哪个文件离18号近,就有可能是被改动的。

而且通告里也说了,这个SQL注入是未授权。通告地址:微信公众平台 (qq.com)

然后注意到这个10.57补丁里的这个文件:ecology/WEB-INF/securityRule/E9/4d162ce4-d74e-4371-944f-814d850ff895_forbidden_20230406.xml

image

这里设置了几个需要检查的URL,我看着时间挺近,我就fofa找了几个站尝试访问了一下哪个未授权,然后就发现了

http://xxxxxx/mobile/plugin/CheckServer.jsp是未授权

image

然后又看到了这个文件ecology/WEB-INF/securityRule/E8/4d162ce4-d74e-4371-944f-814d850ff7f9_mobile_setting.xml

image

意思可能是针对这个url对mobilesettings做了某些限制,然后我就去找这个weaver.security.validators.MobileSettingsValidator

ecology/WEB-INF/myclasses/weaver/security/validators/MobileSettingsValidator.class

image

暂时还不知道这个类是干啥的,就先留着,然后我还看到10.57里的CheckServer.jsp这个文件,有改动:

image

这么多新改动指向它,我感觉很有可能就是CheckServer.jsp这个文件有大问题,注入点很有可能就在这。然后就找了个Ecology9的安装包本地把环境搭建起来,具体分析代码了。

测试环境版本:9.00.2003.18

找到源码中的CheckServer.jsp文件:mobile/plugin/CheckServer.jsp​,发现里面是有内容的:

image

而且传参里面带个mobileSetting​,那很有可能就是这个地方有问题了;根据type传值判断属于哪个分支,然后进入对应的方法中,这次主要研究的是mobileSetting这个判断分支,因此传值的时候直接

传type=mobileSetting,即可进入对应分支,然后进入result = ps.syncMobileSetting(settings, timestamp)​这个方法内部看看。

image

这不就妥妥的SQL拼接吗。。。但是我就是在这里卡了一天。按流程来看我们只要传入?type=mobileSetting&settings=x&timestamp=x,就能顺利走到注入处,那我们断点调试一下看看情况

image

image

看到这我就懵了,为啥传值到这里变成了-999999999N​,我尝试了很多值:字母、数字,特殊字符,发现只有数字是没有改变,初步判断可能是强转或者做了限制,我为了方便,直接把值输出

到response上了。

String timestamp = fu.getParameter("timestamp");
out.println(timestamp);

image

image

至于为什么timestamp参数值会进行过滤,我只知道断点后走到这里:

通过classbean/weaver/file/FileUpload.class#getParameter()​这个方法

走到classbean/weaver/security/webcontainer/XssRequestWeblogic.class#getParameter()​,但是里面的代码太冗余了,看的头疼,以后再分析吧

image

然后到这里的时候其实已经快要放弃这个猜测的漏洞点了,继续翻看classbean/weaver/mobile/plugin/ecology/service/PluginServiceImpl.class#syncMobileSetting()​这个方法的时候,突然想起来syncMobileSetting()

这个方法应该在哪见过ecology/WEB-INF/myclasses/weaver/security/validators/MobileSettingsValidator.class​,这不就是补丁包里新增的类嘛,那看来漏洞位置肯定在这个方法里,我就继续翻看这个方法:

因为这里使用到了settings这个参数,因此我首先尝试打印这个参数值,看它有没有过滤:

image

image

可以看到,它完整的输出了我想要的结果,然后我接下来去找看看这个方法的代码里有没有SQL拼接的地方,最后找到了在这个内部方法里

classbean/weaver/mobile/plugin/ecology/service/PluginServiceImpl.classs#yncMobileSetting()-->this.saveMobileDocSetting(var10, var12, var13);

image

image

可以看到,这里有很多地方可以做拼接的,但是要根据分支去具体分析:

我们先来设置几个基础变量

    saveMobileDocSetting(int var1, String var2, String var3)
    var1 = (int)scope
    var2 = (String)setting
    var3 = (string)modulename

这里有两种情况,第一种是var2为空,第二种是var2不为空的情况,我们先来分析第一种:

1: var2为空

image

由这个判断,我们可以知道,当var1(scope) > 0 并且var3(modulename) 不是空值的时候,会进入判断,因此我们目前的payload可以写成:

settings=[{"scope":"1","modulename":"a"}]

继续进入内部的if分支后,可以看到,这里需要确保StringUtils.isBlank(var2)​为true,才会进入判断,而var2=setting,因此我们的poc可以继续写成:

settings=[{"scope":"1","modulename":"a","setting":""}]

现在的问题是,我们该如何进入到内部方法saveMobileDocSetting()​中,回过头来看classbean/weaver/mobile/plugin/ecology/service/PluginServiceImpl.class#syncMobileSetting()​方法

image

因此我们继续设置我们的poc: ​settings=[{"scope":"1","module":"2","modulename":"a","setting":""}]

成功进入分支后,就直接执行sql语句了,通过第三个sql语句我们可以知道,payload可以直接插入modulename中,通过断点调试并结合mysql,去分析:

image

成功走到了saveMobileDocSetting()​内部方法中:

image

在执行三条sql语句之前,我们先看看数据库中该表的状态:

image

执行第二条语句后:

image

执行第三条语句后:

image

我们尝试插入恶意poc:

settings=[{"scope":"1","module":"2","modulename":"1'+and+benchmark(100000000,sha(1))+and+'","setting":""}]&timestamp=11111

image

2. var2 不为空:

当var2(setting)不为空的情况下,就走近了else分支中了

image

我们可以直接看这条sql语句中的var12,var1。看看该else分支中是如何处理这两个变量的

单击var1参数,我们是可以看到这个else分支中是没有var1的动作的:

image

image​​

所以其实我们整个poc只需要修改setting,保证不为空,即可进行select注入:

image

综上:

    insert sqli: [{"scope":"1","module":"2","modulename":"1'+and+benchmark(100000000,sha(1))+and+'","setting":""}]
    select sqli: [{"scope":"1","module":"2","modulename":"1'+and+benchmark(100000000,sha(1))+and+'","setting":"1"}]