Projects
Mega:24.03:SP1:Everything
netty
_service:tar_scm:CVE-2022-41881.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:CVE-2022-41881.patch of Package netty
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2