[Git][java-team/netty][master] 2 commits: Add patch for CVE-2021-21409
Tony Mancill
gitlab at salsa.debian.org
Thu Apr 1 06:44:44 BST 2021
Tony Mancill pushed to branch master at Debian Java Maintainers / netty
Commits:
9a67d3dd by tony mancill at 2021-03-31T22:06:05-07:00
Add patch for CVE-2021-21409
- - - - -
96ba0b4c by tony mancill at 2021-03-31T22:34:37-07:00
prepare changelog for upload to unstable
- - - - -
3 changed files:
- debian/changelog
- + debian/patches/CVE-2021-21409.patch
- debian/patches/series
Changes:
=====================================
debian/changelog
=====================================
@@ -1,3 +1,15 @@
+netty (1:4.1.48-4) unstable; urgency=high
+
+ * Team upload.
+ * Fix CVE-2021-21409 (Closes: #986217)
+ Address a vulnerability that enables request smuggling. The content-length
+ header is not correctly validated if the request only uses a single
+ Http2HeaderFrame with the endStream set to true. This could lead to request
+ smuggling if the request is proxied to a remote peer and translated to
+ HTTP/1.1. This is a followup to CVE-2021-21295 to address this case.
+
+ -- tony mancill <tmancill at debian.org> Wed, 31 Mar 2021 22:01:52 -0700
+
netty (1:4.1.48-3) unstable; urgency=high
* Team upload.
=====================================
debian/patches/CVE-2021-21409.patch
=====================================
@@ -0,0 +1,211 @@
+From: Norman Maurer <norman_maurer at apple.com>
+Date: Tue, 30 Mar 2021 09:40:47 +0200
+Subject: CVE-2021-21409 (was: [PATCH] Merge pull request from GHSA-f256-j965-7f32)
+Origin: https://github.com/netty/netty/commit/b0fa4d5aab4215f3c22ce6123dd8dd5f38dc0432
+
+Motivation:
+
+We also need to ensure that all the header validation is done when a single header with the endStream flag is received
+
+Modifications:
+
+- Adjust code to always enforce the validation
+- Add more unit tests
+
+Result:
+
+Always correctly validate
+---
+ .../http2/DefaultHttp2ConnectionDecoder.java | 5 ++-
+ .../codec/http2/Http2MultiplexTest.java | 45 ++++++++++++++++++-
+ 2 files changed, 48 insertions(+), 2 deletions(-)
+
+--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
++++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
+@@ -352,10 +352,13 @@
+ short weight, boolean exclusive, int padding, boolean endOfStream) throws Http2Exception {
+ Http2Stream stream = connection.stream(streamId);
+ boolean allowHalfClosedRemote = false;
++ boolean isTrailers = false;
+ if (stream == null && !connection.streamMayHaveExisted(streamId)) {
+ stream = connection.remote().createStream(streamId, endOfStream);
+ // Allow the state to be HALF_CLOSE_REMOTE if we're creating it in that state.
+ allowHalfClosedRemote = stream.state() == HALF_CLOSED_REMOTE;
++ } else if (stream != null) {
++ isTrailers = stream.isHeadersReceived();
+ }
+
+ if (shouldIgnoreHeadersOrDataFrame(ctx, streamId, stream, "HEADERS")) {
+@@ -393,7 +396,7 @@
+ stream.state());
+ }
+
+- if (!stream.isHeadersReceived()) {
++ if (!isTrailers) {
+ // extract the content-length header
+ List<? extends CharSequence> contentLength = headers.getAll(HttpHeaderNames.CONTENT_LENGTH);
+ if (contentLength != null && !contentLength.isEmpty()) {
+--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2MultiplexTest.java
++++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2MultiplexTest.java
+@@ -5,7 +5,7 @@
+ * "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
++ * https://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
+@@ -26,12 +26,14 @@
+ import io.netty.channel.ChannelPromise;
+ import io.netty.channel.WriteBufferWaterMark;
+ import io.netty.channel.embedded.EmbeddedChannel;
++import io.netty.handler.codec.http.HttpHeaderNames;
+ import io.netty.handler.codec.http.HttpMethod;
+ import io.netty.handler.codec.http.HttpScheme;
+ import io.netty.handler.codec.http2.Http2Exception.StreamException;
+ import io.netty.handler.codec.http2.LastInboundHandler.Consumer;
+ import io.netty.util.AsciiString;
+ import io.netty.util.AttributeKey;
++import org.hamcrest.CoreMatchers;
+ import org.junit.After;
+ import org.junit.Before;
+ import org.junit.Test;
+@@ -219,6 +221,137 @@
+ }
+
+ @Test
++ public void headerMultipleContentLengthValidationShouldPropagate() {
++ headerMultipleContentLengthValidationShouldPropagate(false);
++ }
++
++ @Test
++ public void headerMultipleContentLengthValidationShouldPropagateWithEndStream() {
++ headerMultipleContentLengthValidationShouldPropagate(true);
++ }
++
++ private void headerMultipleContentLengthValidationShouldPropagate(boolean endStream) {
++ LastInboundHandler inboundHandler = new LastInboundHandler();
++ request.addLong(HttpHeaderNames.CONTENT_LENGTH, 0);
++ request.addLong(HttpHeaderNames.CONTENT_LENGTH, 1);
++ Http2StreamChannel channel = newInboundStream(3, endStream, inboundHandler);
++ try {
++ inboundHandler.checkException();
++ fail();
++ } catch (Exception e) {
++ assertThat(e, CoreMatchers.<Exception>instanceOf(StreamException.class));
++ }
++ assertNull(inboundHandler.readInbound());
++ assertFalse(channel.isActive());
++ }
++
++ @Test
++ public void headerPlusSignContentLengthValidationShouldPropagate() {
++ headerSignContentLengthValidationShouldPropagateWithEndStream(false, false);
++ }
++
++ @Test
++ public void headerPlusSignContentLengthValidationShouldPropagateWithEndStream() {
++ headerSignContentLengthValidationShouldPropagateWithEndStream(false, true);
++ }
++
++ @Test
++ public void headerMinusSignContentLengthValidationShouldPropagate() {
++ headerSignContentLengthValidationShouldPropagateWithEndStream(true, false);
++ }
++
++ @Test
++ public void headerMinusSignContentLengthValidationShouldPropagateWithEndStream() {
++ headerSignContentLengthValidationShouldPropagateWithEndStream(true, true);
++ }
++
++ private void headerSignContentLengthValidationShouldPropagateWithEndStream(boolean minus, boolean endStream) {
++ LastInboundHandler inboundHandler = new LastInboundHandler();
++ request.add(HttpHeaderNames.CONTENT_LENGTH, (minus ? "-" : "+") + 1);
++ Http2StreamChannel channel = newInboundStream(3, endStream, inboundHandler);
++ try {
++ inboundHandler.checkException();
++ fail();
++ } catch (Exception e) {
++ assertThat(e, CoreMatchers.<Exception>instanceOf(StreamException.class));
++ }
++ assertNull(inboundHandler.readInbound());
++ assertFalse(channel.isActive());
++ }
++
++ @Test
++ public void headerContentLengthNotMatchValidationShouldPropagate() {
++ headerContentLengthNotMatchValidationShouldPropagate(false, false, false);
++ }
++
++ @Test
++ public void headerContentLengthNotMatchValidationShouldPropagateWithEndStream() {
++ headerContentLengthNotMatchValidationShouldPropagate(false, true, false);
++ }
++
++ @Test
++ public void headerContentLengthNotMatchValidationShouldPropagateCloseLocal() {
++ headerContentLengthNotMatchValidationShouldPropagate(true, false, false);
++ }
++
++ @Test
++ public void headerContentLengthNotMatchValidationShouldPropagateWithEndStreamCloseLocal() {
++ headerContentLengthNotMatchValidationShouldPropagate(true, true, false);
++ }
++
++ @Test
++ public void headerContentLengthNotMatchValidationShouldPropagateTrailers() {
++ headerContentLengthNotMatchValidationShouldPropagate(false, false, true);
++ }
++
++ @Test
++ public void headerContentLengthNotMatchValidationShouldPropagateWithEndStreamTrailers() {
++ headerContentLengthNotMatchValidationShouldPropagate(false, true, true);
++ }
++
++ @Test
++ public void headerContentLengthNotMatchValidationShouldPropagateCloseLocalTrailers() {
++ headerContentLengthNotMatchValidationShouldPropagate(true, false, true);
++ }
++
++ @Test
++ public void headerContentLengthNotMatchValidationShouldPropagateWithEndStreamCloseLocalTrailers() {
++ headerContentLengthNotMatchValidationShouldPropagate(true, true, true);
++ }
++
++ private void headerContentLengthNotMatchValidationShouldPropagate(
++ boolean closeLocal, boolean endStream, boolean trailer) {
++ LastInboundHandler inboundHandler = new LastInboundHandler();
++ request.addLong(HttpHeaderNames.CONTENT_LENGTH, 1);
++ Http2StreamChannel channel = newInboundStream(3, false, inboundHandler);
++ assertTrue(channel.isActive());
++
++ if (closeLocal) {
++ channel.writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers(), true))
++ .syncUninterruptibly();
++ assertEquals(Http2Stream.State.HALF_CLOSED_LOCAL, channel.stream().state());
++ } else {
++ assertEquals(Http2Stream.State.OPEN, channel.stream().state());
++ }
++
++ if (trailer) {
++ frameInboundWriter.writeInboundHeaders(channel.stream().id(), new DefaultHttp2Headers(), 0, endStream);
++ } else {
++ frameInboundWriter.writeInboundData(channel.stream().id(), bb("foo"), 0, endStream);
++ }
++ try {
++ inboundHandler.checkException();
++ fail();
++ } catch (Exception e) {
++ assertThat(e, CoreMatchers.<Exception>instanceOf(StreamException.class));
++ }
++ Http2HeadersFrame headersFrame = new DefaultHttp2HeadersFrame(request).stream(channel.stream());
++ assertEquals(headersFrame, inboundHandler.readInbound());
++ assertNull(inboundHandler.readInbound());
++ assertFalse(channel.isActive());
++ }
++
++ @Test
+ public void framesShouldBeMultiplexed() {
+ LastInboundHandler handler1 = new LastInboundHandler();
+ Http2StreamChannel channel1 = newInboundStream(3, false, handler1);
=====================================
debian/patches/series
=====================================
@@ -14,3 +14,4 @@
17-disable-blockhound-integration.patch
CVE-2021-21290.patch
CVE-2021-21295.patch
+CVE-2021-21409.patch
View it on GitLab: https://salsa.debian.org/java-team/netty/-/compare/200e9921ff56d59d1871b02a04b7099c60d0de6c...96ba0b4c395222998f6e7b6f9a593d2b766b6fec
--
View it on GitLab: https://salsa.debian.org/java-team/netty/-/compare/200e9921ff56d59d1871b02a04b7099c60d0de6c...96ba0b4c395222998f6e7b6f9a593d2b766b6fec
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20210401/62014d2c/attachment.htm>
More information about the pkg-java-commits
mailing list