Skip to content

Commit

Permalink
Merge branch '2.x' into dev-protocol-test
Browse files Browse the repository at this point in the history
  • Loading branch information
Bughue authored Jul 29, 2024
2 parents 4b999b4 + 20cd962 commit 7cb2612
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 10 deletions.
2 changes: 1 addition & 1 deletion changes/en-us/2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Add changes here for all PR submitted to the 2.x branch.
### refactor:

### security:

- [[#6702](https://github.com/apache/incubator-seata/pull/6702)] fix REC security vulnerability during Raft deserialization

### test:
- [[#6608](https://github.com/apache/incubator-seata/pull/6608)] add unit test for sql-parser-core
Expand Down
1 change: 1 addition & 0 deletions changes/zh-cn/2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@


### security:
- [[#6702](https://github.com/apache/incubator-seata/pull/6702)] 修复Raft反序列化时存在RCE安全漏洞

### test:
- [[#6608](https://github.com/apache/incubator-seata/pull/6608)] 添加sql-parser-core模块测试用例
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ public enum ErrorCode {
/**
* 0001 ~ 0099 Configuration related errors
*/
ERR_CONFIG(ErrorType.Config, 0001);
ERR_CONFIG(ErrorType.Config, 0001),

/**
* The error code of the transaction exception.
* 0100 ~ 0199 Security related errors
*/
ERR_DESERIALIZATION_SECURITY(ErrorType.Security, 0156);

/**
* The error code of the transaction exception.
*/
private int code;
private ErrorType type;

Expand Down Expand Up @@ -77,6 +82,10 @@ enum ErrorType {
* Network error type.
*/
Network,
/**
* Security related error type.
*/
Security,
/**
* Tm error type.
*/
Expand Down
3 changes: 2 additions & 1 deletion common/src/main/resources/error/ErrorCode_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
#
ERR_PREFIX=ERR-CODE: [Seata-{code}][{key}]
ERR_POSTFIX=More: [https://seata.apache.org/docs/next/overview/faq#{code}]
ERR_CONFIG=config error, {0}
ERR_CONFIG=config error, {0}
ERR_DESERIALIZATION_SECURITY=deserialization security error, {0}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.apache.seata.common.exception.ErrorCode;
import org.apache.seata.common.exception.SeataRuntimeException;
import org.apache.seata.common.loader.EnhancedServiceLoader;
import org.apache.seata.core.compressor.CompressorFactory;
import org.apache.seata.core.serializer.Serializer;
Expand All @@ -36,6 +41,14 @@ public class RaftSyncMessageSerializer {

private static final Logger LOGGER = LoggerFactory.getLogger(RaftSyncMessageSerializer.class);

private static final List<String> PERMITS = new ArrayList<>();

static {
PERMITS.add(RaftSyncMessage.class.getName());
PERMITS.add(io.seata.server.cluster.raft.sync.msg.RaftSyncMessage.class.getName());
PERMITS.add("[B");
}

public static byte[] encode(RaftSyncMessage raftSyncMessage) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
Expand All @@ -62,12 +75,22 @@ public static byte[] encode(io.seata.server.cluster.raft.sync.msg.RaftSyncMessag

public static RaftSyncMessage decode(byte[] raftSyncMsgByte) {
try (ByteArrayInputStream bin = new ByteArrayInputStream(raftSyncMsgByte);
ObjectInputStream ois = new ObjectInputStream(bin)) {
ObjectInputStream ois = new ObjectInputStream(bin) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!PERMITS.contains(desc.getName())) {
throw new SeataRuntimeException(ErrorCode.ERR_DESERIALIZATION_SECURITY,
"Failed to deserialize object: " + desc.getName() + " is not permitted");
}

return super.resolveClass(desc);
}
}) {
Object object = ois.readObject();
RaftSyncMessage raftSyncMessage;
if (object instanceof io.seata.server.cluster.raft.sync.msg.RaftSyncMessage) {
io.seata.server.cluster.raft.sync.msg.RaftSyncMessage oldRaftSyncMessage =
(io.seata.server.cluster.raft.sync.msg.RaftSyncMessage)object;
(io.seata.server.cluster.raft.sync.msg.RaftSyncMessage)object;
raftSyncMessage = new RaftSyncMessage();
raftSyncMessage.setCodec(oldRaftSyncMessage.getCodec());
raftSyncMessage.setCompressor(oldRaftSyncMessage.getCompressor());
Expand All @@ -77,13 +100,16 @@ public static RaftSyncMessage decode(byte[] raftSyncMsgByte) {
raftSyncMessage = (RaftSyncMessage)object;
}
Serializer serializer = EnhancedServiceLoader.load(Serializer.class,
SerializerType.getByCode(raftSyncMessage.getCodec()).name());
SerializerType.getByCode(raftSyncMessage.getCodec()).name());
Optional.ofNullable(raftSyncMessage.getBody())
.ifPresent(value -> raftSyncMessage.setBody(serializer.deserialize(CompressorFactory
.getCompressor(raftSyncMessage.getCompressor()).decompress((byte[])raftSyncMessage.getBody()))));
.ifPresent(value -> raftSyncMessage.setBody(serializer.deserialize(CompressorFactory
.getCompressor(raftSyncMessage.getCompressor()).decompress((byte[])raftSyncMessage.getBody()))));
return raftSyncMessage;
} catch (ClassNotFoundException | IOException e) {
} catch (Exception e) {
LOGGER.info("Failed to read raft synchronization log: {}", e.getMessage(), e);
if (e instanceof SeataRuntimeException) {
throw (SeataRuntimeException)e;
}
throw new RuntimeException(e);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
*/
package org.apache.seata.server.raft;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.seata.common.exception.SeataRuntimeException;
import org.apache.seata.common.metadata.ClusterRole;
import org.apache.seata.common.metadata.Node;
import org.apache.seata.core.exception.TransactionException;
Expand Down Expand Up @@ -62,6 +65,19 @@ public static void setUp(ApplicationContext context){
public static void destroy(){
SessionHolder.destroy();
}

@Test
public void testSecurityMsgSerialize() throws IOException {
TestSecurity testSecurity = new TestSecurity();
byte[] bytes;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(testSecurity);
bytes = bos.toByteArray();
}
Assertions.assertThrows(SeataRuntimeException.class,()->RaftSyncMessageSerializer.decode(bytes));
}

@Test
public void testMsgSerialize() throws IOException {
RaftSyncMessage raftSyncMessage = new RaftSyncMessage();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.seata.server.raft;

public class TestSecurity implements java.io.Serializable {

private static final long serialVersionUID = 543214259201495900L;

String a = "test";

public String getA() {
return a;
}

public void setA(String a) {
this.a = a;
}
}

0 comments on commit 7cb2612

Please sign in to comment.