Fix CVE-2022-41881

This commit is contained in:
starlet-dx 2023-12-13 15:18:49 +08:00
parent 7d22acf249
commit 8de09516fe
3 changed files with 172 additions and 1 deletions

166
CVE-2022-41881.patch Normal file
View File

@ -0,0 +1,166 @@
From cd91cf3c99123bd1e53fd6a1de0e3d1922f05bb2 Mon Sep 17 00:00:00 2001
From: Norman Maurer <norman_maurer@apple.com>
Date: Mon, 12 Dec 2022 14:04:31 +0100
Subject: [PATCH] Merge pull request from GHSA-fx2c-96vj-985v
Motivation:
A StackOverflowError can be raised when parsing a malformed crafted message due to an
infinite recursion. We should bail out early
Modifications:
- Add a limit to the maximum nesting of TLV.
- Add unit test
Result:
Not possible anymore to trigger a StackOverflowError with a special crafted packet
---
.../handler/codec/haproxy/HAProxyMessage.java | 16 +++--
.../haproxy/HAProxyMessageDecoderTest.java | 65 +++++++++++++++++++
2 files changed, 76 insertions(+), 5 deletions(-)
diff --git a/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java b/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
index b40bf42..3f30c4a 100644
--- a/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
+++ b/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
@@ -30,6 +30,9 @@ import java.util.List;
*/
public final class HAProxyMessage {
+ // Let's pick some conservative limit here.
+ private static final int MAX_NESTING_LEVEL = 128;
+
/**
* Version 1 proxy protocol message for 'UNKNOWN' proxied protocols. Per spec, when the proxied protocol is
* 'UNKNOWN' we must discard all other header values.
@@ -238,7 +241,7 @@ public final class HAProxyMessage {
}
private static List<HAProxyTLV> readTlvs(final ByteBuf header) {
- HAProxyTLV haProxyTLV = readNextTLV(header);
+ HAProxyTLV haProxyTLV = readNextTLV(header, 0);
if (haProxyTLV == null) {
return Collections.emptyList();
}
@@ -250,12 +253,15 @@ public final class HAProxyMessage {
if (haProxyTLV instanceof HAProxySSLTLV) {
haProxyTLVs.addAll(((HAProxySSLTLV) haProxyTLV).encapsulatedTLVs());
}
- } while ((haProxyTLV = readNextTLV(header)) != null);
+ } while ((haProxyTLV = readNextTLV(header, 0)) != null);
return haProxyTLVs;
}
- private static HAProxyTLV readNextTLV(final ByteBuf header) {
-
+ private static HAProxyTLV readNextTLV(final ByteBuf header, int nestingLevel) {
+ if (nestingLevel > MAX_NESTING_LEVEL) {
+ throw new HAProxyProtocolException(
+ "Maximum TLV nesting level reached: " + nestingLevel + " (expected: < " + MAX_NESTING_LEVEL + ')');
+ }
// We need at least 4 bytes for a TLV
if (header.readableBytes() < 4) {
return null;
@@ -276,7 +282,7 @@ public final class HAProxyMessage {
final List<HAProxyTLV> encapsulatedTlvs = new ArrayList<HAProxyTLV>(4);
do {
- final HAProxyTLV haProxyTLV = readNextTLV(byteBuf);
+ final HAProxyTLV haProxyTLV = readNextTLV(byteBuf, nestingLevel + 1);
if (haProxyTLV == null) {
break;
}
diff --git a/codec-haproxy/src/test/java/io/netty/handler/codec/haproxy/HAProxyMessageDecoderTest.java b/codec-haproxy/src/test/java/io/netty/handler/codec/haproxy/HAProxyMessageDecoderTest.java
index 2d4039d..8d27e4a 100644
--- a/codec-haproxy/src/test/java/io/netty/handler/codec/haproxy/HAProxyMessageDecoderTest.java
+++ b/codec-haproxy/src/test/java/io/netty/handler/codec/haproxy/HAProxyMessageDecoderTest.java
@@ -16,6 +16,7 @@
package io.netty.handler.codec.haproxy;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.ProtocolDetectionResult;
@@ -26,6 +27,9 @@ import io.netty.util.CharsetUtil;
import org.junit.Before;
import org.junit.Test;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.util.List;
import static io.netty.buffer.Unpooled.*;
@@ -1013,4 +1017,65 @@ public class HAProxyMessageDecoderTest {
assertNull(result.detectedProtocol());
incompleteHeader.release();
}
+
+ @Test
+ public void testNestedTLV() throws Exception {
+ ByteArrayOutputStream headerWriter = new ByteArrayOutputStream();
+ //src_ip = "AAAA", dst_ip = "BBBB", src_port = "CC", dst_port = "DD"
+ headerWriter.write(new byte[] {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'D', 'D'});
+ //write TLVs
+ int countOfTLVs = 8100;
+ ByteBuffer tlvLengthBuf = ByteBuffer.allocate(2);
+ tlvLengthBuf.order(ByteOrder.BIG_ENDIAN);
+ short totalLength = (short) (countOfTLVs * (1 + 2 + 1 + 4));
+ for (int i = 0; i < countOfTLVs; i++) {
+ //write PP2_TYPE_SSL TLV
+ headerWriter.write(0x20); //PP2_TYPE_SSL
+ //notice that the TLV length cannot be bigger than 0xffff
+ totalLength -= 1 + 2; //exclude type and length themselves
+ tlvLengthBuf.clear();
+ tlvLengthBuf.putShort(totalLength);
+ //add to the header
+ headerWriter.write(tlvLengthBuf.array());
+ //write client field
+ headerWriter.write(1);
+ //write verify field
+ headerWriter.write(new byte[] {'V', 'V', 'V', 'V'});
+ //subtract the client and verify fields
+ totalLength -= 1 + 4;
+ }
+ byte[] header = headerWriter.toByteArray();
+ ByteBuffer numsWrite = ByteBuffer.allocate(2);
+ numsWrite.order(ByteOrder.BIG_ENDIAN);
+ numsWrite.putShort((short) header.length);
+
+ final ByteBuf data = Unpooled.buffer();
+ data.writeBytes(new byte[] {
+ (byte) 0x0D,
+ (byte) 0x0A,
+ (byte) 0x0D,
+ (byte) 0x0A,
+ (byte) 0x00,
+ (byte) 0x0D,
+ (byte) 0x0A,
+ (byte) 0x51,
+ (byte) 0x55,
+ (byte) 0x49,
+ (byte) 0x54,
+ (byte) 0x0A
+ });
+ //verCmd = 32
+ byte versionCmd = 0x20 | 1; //V2 | ProxyCmd
+ data.writeByte(versionCmd);
+ data.writeByte(17); //TPAF_TCP4_BYTE
+ data.writeBytes(numsWrite.array());
+ data.writeBytes(header);
+
+ assertThrows(HAProxyProtocolException.class, new Executable() {
+ @Override
+ public void execute() {
+ ch.writeInbound(data);
+ }
+ });
+ }
}
--
2.30.0

Binary file not shown.

View File

@ -2,7 +2,7 @@
Name: netty Name: netty
Version: 4.1.13 Version: 4.1.13
Release: 19 Release: 20
Summary: Asynchronous event-driven network application Java framework Summary: Asynchronous event-driven network application Java framework
License: ASL 2.0 License: ASL 2.0
URL: https://netty.io/ URL: https://netty.io/
@ -30,6 +30,8 @@ Patch0018: CVE-2021-37137.patch
Patch0019: CVE-2021-43797-pre.patch Patch0019: CVE-2021-43797-pre.patch
Patch0020: CVE-2021-43797.patch Patch0020: CVE-2021-43797.patch
Patch0021: fix-strip.patch Patch0021: fix-strip.patch
# https://github.com/netty/netty/commit/cd91cf3c99123bd1e53fd6a1de0e3d1922f05bb2
Patch0022: CVE-2022-41881.patch
BuildRequires: maven-local mvn(ant-contrib:ant-contrib) BuildRequires: maven-local mvn(ant-contrib:ant-contrib)
BuildRequires: mvn(com.jcraft:jzlib) mvn(commons-logging:commons-logging) BuildRequires: mvn(com.jcraft:jzlib) mvn(commons-logging:commons-logging)
@ -154,6 +156,9 @@ export CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS"
%changelog %changelog
* Wed Dec 13 2023 yaoxin <yao_xin001@hoperun.com> - 4.1.13-20
- Fix CVE-2022-41881
* Sun Mar 05 2023 wulei <wulei80@h-partners.com> - 4.1.13-19 * Sun Mar 05 2023 wulei <wulei80@h-partners.com> - 4.1.13-19
- Add strip - Add strip