From: Vijay Anusuri <vanus...@mvista.com>

A malicious HTTP sender can use chunk extensions to cause a receiver
reading from a request or response body to read many more bytes from
the network than are in the body. A malicious HTTP client can further
exploit this to cause a server to automatically read a large amount
of data (up to about 1GiB) when a handler fails to read the entire
body of a request. Chunk extensions are a little-used HTTP feature
which permit including additional metadata in a request or response
body sent using the chunked encoding. The net/http chunked encoding
reader discards this metadata. A sender can exploit this by inserting
a large metadata segment with each byte transferred. The chunk reader
now produces an error if the ratio of real body to encoded bytes grows
too small.

References:
https://nvd.nist.gov/vuln/detail/CVE-2023-39326
https://security-tracker.debian.org/tracker/CVE-2023-39326

Signed-off-by: Vijay Anusuri <vanus...@mvista.com>
Signed-off-by: Steve Sakoman <st...@sakoman.com>
---
 meta/recipes-devtools/go/go-1.14.inc          |   1 +
 .../go/go-1.14/CVE-2023-39326.patch           | 181 ++++++++++++++++++
 2 files changed, 182 insertions(+)
 create mode 100644 meta/recipes-devtools/go/go-1.14/CVE-2023-39326.patch

diff --git a/meta/recipes-devtools/go/go-1.14.inc 
b/meta/recipes-devtools/go/go-1.14.inc
index 091b778de8..b827a3606d 100644
--- a/meta/recipes-devtools/go/go-1.14.inc
+++ b/meta/recipes-devtools/go/go-1.14.inc
@@ -82,6 +82,7 @@ SRC_URI += "\
     file://CVE-2023-24536_3.patch \
     file://CVE-2023-39318.patch \
     file://CVE-2023-39319.patch \
+    file://CVE-2023-39326.patch \
 "
 
 SRC_URI_append_libc-musl = " 
file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch"
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-39326.patch 
b/meta/recipes-devtools/go/go-1.14/CVE-2023-39326.patch
new file mode 100644
index 0000000000..998af361e8
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-39326.patch
@@ -0,0 +1,181 @@
+From 6446af942e2e2b161c4ec1b60d9703a2b55dc4dd Mon Sep 17 00:00:00 2001
+From: Damien Neil <dn...@google.com>
+Date: Tue, 7 Nov 2023 10:47:56 -0800
+Subject: [PATCH] [release-branch.go1.20] net/http: limit chunked data overhead
+
+The chunked transfer encoding adds some overhead to
+the content transferred. When writing one byte per
+chunk, for example, there are five bytes of overhead
+per byte of data transferred: "1\r\nX\r\n" to send "X".
+
+Chunks may include "chunk extensions",
+which we skip over and do not use.
+For example: "1;chunk extension here\r\nX\r\n".
+
+A malicious sender can use chunk extensions to add
+about 4k of overhead per byte of data.
+(The maximum chunk header line size we will accept.)
+
+Track the amount of overhead read in chunked data,
+and produce an error if it seems excessive.
+
+Updates #64433
+Fixes #64434
+Fixes CVE-2023-39326
+
+Change-Id: I40f8d70eb6f9575fb43f506eb19132ccedafcf39
+Reviewed-on: 
https://team-review.git.corp.google.com/c/golang/go-private/+/2076135
+Reviewed-by: Tatiana Bradley <tatianabrad...@google.com>
+Reviewed-by: Roland Shoemaker <bracew...@google.com>
+(cherry picked from commit 3473ae72ee66c60744665a24b2fde143e8964d4f)
+Reviewed-on: 
https://team-review.git.corp.google.com/c/golang/go-private/+/2095407
+Run-TryBot: Roland Shoemaker <bracew...@google.com>
+TryBot-Result: Security TryBots 
<security-tryb...@go-security-trybots.iam.gserviceaccount.com>
+Reviewed-by: Damien Neil <dn...@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/547355
+Reviewed-by: Dmitri Shuralyov <dmits...@google.com>
+LUCI-TryBot-Result: Go LUCI 
<golang-sco...@luci-project-accounts.iam.gserviceaccount.com>
+
+Upstream-Status: Backport 
[https://github.com/golang/go/commit/6446af942e2e2b161c4ec1b60d9703a2b55dc4dd]
+CVE: CVE-2023-39326
+Signed-off-by: Vijay Anusuri <vanus...@mvista.com>
+---
+ src/net/http/internal/chunked.go      | 36 +++++++++++++---
+ src/net/http/internal/chunked_test.go | 59 +++++++++++++++++++++++++++
+ 2 files changed, 89 insertions(+), 6 deletions(-)
+
+diff --git a/src/net/http/internal/chunked.go 
b/src/net/http/internal/chunked.go
+index f06e572..ddbaacb 100644
+--- a/src/net/http/internal/chunked.go
++++ b/src/net/http/internal/chunked.go
+@@ -39,7 +39,8 @@ type chunkedReader struct {
+       n        uint64 // unread bytes in chunk
+       err      error
+       buf      [2]byte
+-      checkEnd bool // whether need to check for \r\n chunk footer
++      checkEnd bool  // whether need to check for \r\n chunk footer
++      excess   int64 // "excessive" chunk overhead, for malicious sender 
detection
+ }
+ 
+ func (cr *chunkedReader) beginChunk() {
+@@ -49,10 +50,38 @@ func (cr *chunkedReader) beginChunk() {
+       if cr.err != nil {
+               return
+       }
++      cr.excess += int64(len(line)) + 2 // header, plus \r\n after the chunk 
data
++      line = trimTrailingWhitespace(line)
++      line, cr.err = removeChunkExtension(line)
++      if cr.err != nil {
++              return
++      }
+       cr.n, cr.err = parseHexUint(line)
+       if cr.err != nil {
+               return
+       }
++      // A sender who sends one byte per chunk will send 5 bytes of overhead
++      // for every byte of data. ("1\r\nX\r\n" to send "X".)
++      // We want to allow this, since streaming a byte at a time can be 
legitimate.
++      //
++      // A sender can use chunk extensions to add arbitrary amounts of 
additional
++      // data per byte read. ("1;very long extension\r\nX\r\n" to send "X".)
++      // We don't want to disallow extensions (although we discard them),
++      // but we also don't want to allow a sender to reduce the signal/noise 
ratio
++      // arbitrarily.
++      //
++      // We track the amount of excess overhead read,
++      // and produce an error if it grows too large.
++      //
++      // Currently, we say that we're willing to accept 16 bytes of overhead 
per chunk,
++      // plus twice the amount of real data in the chunk.
++      cr.excess -= 16 + (2 * int64(cr.n))
++      if cr.excess < 0 {
++              cr.excess = 0
++      }
++      if cr.excess > 16*1024 {
++              cr.err = errors.New("chunked encoding contains too much 
non-data")
++      }
+       if cr.n == 0 {
+               cr.err = io.EOF
+       }
+@@ -133,11 +162,6 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) {
+       if len(p) >= maxLineLength {
+               return nil, ErrLineTooLong
+       }
+-      p = trimTrailingWhitespace(p)
+-      p, err = removeChunkExtension(p)
+-      if err != nil {
+-              return nil, err
+-      }
+       return p, nil
+ }
+ 
+diff --git a/src/net/http/internal/chunked_test.go 
b/src/net/http/internal/chunked_test.go
+index d067165..b20747d 100644
+--- a/src/net/http/internal/chunked_test.go
++++ b/src/net/http/internal/chunked_test.go
+@@ -212,3 +212,62 @@ func TestChunkReadPartial(t *testing.T) {
+       }
+ 
+ }
++
++func TestChunkReaderTooMuchOverhead(t *testing.T) {
++      // If the sender is sending 100x as many chunk header bytes as chunk 
data,
++      // we should reject the stream at some point.
++      chunk := []byte("1;")
++      for i := 0; i < 100; i++ {
++              chunk = append(chunk, 'a') // chunk extension
++      }
++      chunk = append(chunk, "\r\nX\r\n"...)
++      const bodylen = 1 << 20
++      r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) {
++              if i < bodylen {
++                      return chunk, nil
++              }
++              return []byte("0\r\n"), nil
++      }})
++      _, err := io.ReadAll(r)
++      if err == nil {
++              t.Fatalf("successfully read body with excessive overhead; want 
error")
++      }
++}
++
++func TestChunkReaderByteAtATime(t *testing.T) {
++      // Sending one byte per chunk should not trip the excess-overhead 
detection.
++      const bodylen = 1 << 20
++      r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) {
++              if i < bodylen {
++                      return []byte("1\r\nX\r\n"), nil
++              }
++              return []byte("0\r\n"), nil
++      }})
++      got, err := io.ReadAll(r)
++      if err != nil {
++              t.Errorf("unexpected error: %v", err)
++      }
++      if len(got) != bodylen {
++              t.Errorf("read %v bytes, want %v", len(got), bodylen)
++      }
++}
++
++type funcReader struct {
++      f   func(iteration int) ([]byte, error)
++      i   int
++      b   []byte
++      err error
++}
++
++func (r *funcReader) Read(p []byte) (n int, err error) {
++      if len(r.b) == 0 && r.err == nil {
++              r.b, r.err = r.f(r.i)
++              r.i++
++      }
++      n = copy(p, r.b)
++      r.b = r.b[n:]
++      if len(r.b) > 0 {
++              return n, nil
++      }
++      return n, r.err
++}
+-- 
+2.25.1
+
-- 
2.34.1

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#193266): 
https://lists.openembedded.org/g/openembedded-core/message/193266
Mute This Topic: https://lists.openembedded.org/mt/103496211/21656
Group Owner: openembedded-core+ow...@lists.openembedded.org
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to