【安全通报】Liferay Portal中的RCE漏洞

22.png

近期,白帽汇安全研究院观察到国外安全研究团队Code White公开了在Liferay Portal中发现的和JSON反序列化有关的高危漏洞,影响了6.1,6.2,,7.0,7.1,7.2版本。它可让未授权的攻击者通过JSON Web服务的API实现远程代码执行。

Liferay是一个开源的Portal产品,提供对多个独立系统的内容集成,为企业信息、流程等的整合提供了一套完整的解决方案,和其他商业产品相比,Liferay有着很多优良的特性,而且免费,在全球都有较多用户。

从FOFA的搜索结果来看,不少学校和政府网站都和其有关。

33.png

44.png

概况

根据目前FOFA系统最新数据(一年内数据),显示全球范围内共有44929个Liferay服务对外开放。美国使用数量最多,共有11045个,意大利第二,共有3481个,德国第三,共有3327个,西班牙第四,共有2866个,中国第五,共有2427个。

全球范围内分布情况如下(仅为分布情况,非漏洞影响情况)。

55.png

中国大陆地区浙江省使用数量最多,共有630个,北京市第二,共有462个,上海市第三,共有179个,广东省第四,共有164个,四川省第五,共有130个。

66.png

危害等级

高危

漏洞原理

Liferay Portal提供了一个全面的JSON Web服务API,并提供了三种不同的调用Web服务方法的示例:

1.通过通用URL/api/jsonws/invoke,其中服务方法及其参数通过POST作传输,一个JSON对象或基于表单的参数。

2.通过服务方法特定的URL,例如/api/jsonws/service-class-name/service-method-name,其中参数传递是通过基于表单的POST数据包。

3.通过服务方法特定的URL,例如/api/jsonws/service-class-name/service-method-name,其中参数也是通过URL的形式传递,例如/api/jsonws/service-class-name/service-method-name/arg1/val1/arg2/val2/…

身份验证和授权检查是在调用服务方法本身中实现的,而请求的处理和JSON反序列化则是在之前进行的。

1.CST-7111: 通过JSON反序列化实现RCE (LPS-88051/LPE-16598)

在Liferay Portal 6.1和6.2中,Flexjson库用于序列化和反序列化数据。它支持对象绑定,对任何带有无参数构造函数的类将使用被初始化对象的setter方法。类的规范是通过class对象键:

{"class":"fully.qualified.ClassName", ... }

该漏洞于2018年12月被报告,已在企业版中被修复,包括6.1 EE GA3 fixpack 716.2 EE GA2 fixpack 1692和6.2 GA6。

2.CST-7205: 通过JSONWS实现远程代码执行 (LPS-97029/CVE-2020-7961)

在Liferay Portal 7中,Flexjson库被Jodd Json库取代,其不支持在JSON数据本身指定要反序列化的类。相反,只能指定根对象的类型,而且必须由java.lang.Class对象实例显式提供。在查找对rootType字段写访问的调用层次结构时,如下所示:

77.png

虽然大多数调用都指定了硬编码类型,但是有一个调用是可变的。通过调用层次结构向后跟踪parameter类型变量,可以发现它来自一个ClassLoader.loadClass(String)调用,该调用带有一个来自JSONWebServiceActionParameters实例的参数值。该对象拥有在web服务调用中传递的参数。JSONWebServiceActionParameters对象有一个JSONWebServiceActionParametersMap实例,该实例有一个_parameterTypes字段,用于将参数映射到类型。该映射用于在调用JSONWebServiceActionImpl._prepareParameters(Class<?>)中的web服务方法的参数准备期间查找反序列化的类。

_parameterTypes映射是通过JSONWebServiceActionParametersMap.put(String, object)方法填充:

/*     */   public object put(String key, object value)
/*     */   {
/*  64 */     int pos = key.indexOf(':');
/*     */
/*  66 */     if (key.startsWith("-")) {
/*     */       // [...]
/*     */     }
/*  71 */     else if (key.startsWith("+")) {
/*     */       // [...]
/*     */     }
/* 101 */     else if (pos != -1) {
/* 102 */       String typeName = key.substring(pos + 1);
/*     */
/* 104 */       key = key.substring(0, pos);
/*     */
/* 106 */       if (_parameterTypes == null) {
/* 107 */         _parameterTypes = new HashMap();
/*     */       }
/*     */
/* 110 */       _parameterTypes.put(key, typeName);
/*     */
/* 112 */       if (Validator.isNull(GetterUtil.getString(value))) {
/* 113 */         value = Void.TYPE;
/*     */       }
/*     */     }
/*     */
/*     */     // [...]
/*     */
/* 142 */     return super.put(key, value);
/*     */   }

上述第102到110行:typeName取自传入的key字符串。因此,如果一个请求参数名包含一个':',它后面的部分指定参数的类型,即:

parameterName:fully.qualified.ClassName

JSONWebServiceActionImpl._prepareParameters(Class<?>)中,使用ReflectUtil.isTypeOf(Class, Class)检查指定的类型是否扩展了要调用的方法的相应参数的类型。因为存在使用java.lang.object参数的服务方法,所以可以指定任何类型。

该漏洞于2019年6月报告,在6.2 GA6、7.0 GA7、7.1 GA4、和7.2 GA2版本中被修复。

CVE-2020-7961利用截图如下:

88.png

外网也有研究人员复现成功:https://twitter.com/chybeta/status/1242133506974560256

微信图片_20200324182814.png

本地复现情况如下:

微信图片_20200326191015.png

漏洞影响

Liferay Portal

6.1、6.2、7.0、7.1、7.2

对应的修复版本是:

6.2 GA6、7.0 GA7、7.1 GA4和7.2 GA2

漏洞编号

CVE-2020-7961

修复建议

目前官方已发布了安全补丁,可到https://liferay.dev/blogs/-/blogs/security-patches-for-liferay-portal-6-2-7-0-and-7-1进行相应版本的下载。

参考

[1] https://github.com/liferay/liferay-portal

[2] https://codewhitesec.blogspot.com/2020/03/liferay-portal-json-vulns.html

[3] https://blog.csdn.net/lushuaiyin/article/details/7023920

白帽汇从事信息安全,专注于安全大数据、企业威胁情报。

公司产品:FOFA-网络空间安全搜索引擎、FOEYE-网络空间检索系统、NOSEC-安全讯息平台。

为您提供:网络空间测绘、企业资产收集、企业威胁情报、应急响应服务。

免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。查看原文

为您推荐