All of lore.kernel.org
 help / color / mirror / Atom feed
From: Robert Yang <liezhi.yang@windriver.com>
To: vkumbhar <vkumbhar@mvista.com>, openembedded-core@lists.openembedded.org
Subject: Re: [OE-core][kirkstone][PATCH] go: fix CVE-2023-29406 net/http insufficient sanitization of Host header
Date: Tue, 22 Aug 2023 11:38:40 +0800	[thread overview]
Message-ID: <86ec0a3c-e9bb-89e6-dd68-e8eb4b18bb16@windriver.com> (raw)
In-Reply-To: <20230726043733.1979925-1-vkumbhar@mvista.com>

Hello,

This patch caused docker failed to run on kirkstone branch:

$ docker run --rm -it ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
3153aa388d02: Pull complete
Digest: sha256:0bced47fffa3361afa981854fcabcd4577cd43cebbb808cea2b1f33a3dd7f508
Status: Downloaded newer image for ubuntu:latest
http: invalid Host header

Maybe we need consider revert it atm since CVE-2023-29406 is a medium bug.

// Robert

On 7/26/23 12:37, vkumbhar wrote:
> Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
> ---
>   meta/recipes-devtools/go/go-1.17.13.inc       |   1 +
>   .../go/go-1.18/CVE-2023-29406.patch           | 210 ++++++++++++++++++
>   2 files changed, 211 insertions(+)
>   create mode 100644 meta/recipes-devtools/go/go-1.18/CVE-2023-29406.patch
> 
> diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc
> index 73921852fc..36904a92fb 100644
> --- a/meta/recipes-devtools/go/go-1.17.13.inc
> +++ b/meta/recipes-devtools/go/go-1.17.13.inc
> @@ -36,6 +36,7 @@ SRC_URI += "\
>       file://CVE-2023-29405.patch \
>       file://CVE-2023-29402.patch \
>       file://CVE-2023-29400.patch \
> +    file://CVE-2023-29406.patch \
>   "
>   SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd"
>   
> diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2023-29406.patch b/meta/recipes-devtools/go/go-1.18/CVE-2023-29406.patch
> new file mode 100644
> index 0000000000..a326cda5c4
> --- /dev/null
> +++ b/meta/recipes-devtools/go/go-1.18/CVE-2023-29406.patch
> @@ -0,0 +1,210 @@
> +From 5fa6923b1ea891400153d04ddf1545e23b40041b Mon Sep 17 00:00:00 2001
> +From: Damien Neil <dneil@google.com>
> +Date: Wed, 28 Jun 2023 13:20:08 -0700
> +Subject: [PATCH] [release-branch.go1.19] net/http: validate Host header before
> + sending
> +
> +Verify that the Host header we send is valid.
> +Avoids surprising behavior such as a Host of "go.dev\r\nX-Evil:oops"
> +adding an X-Evil header to HTTP/1 requests.
> +
> +Add a test, skip the test for HTTP/2. HTTP/2 is not vulnerable to
> +header injection in the way HTTP/1 is, but x/net/http2 doesn't validate
> +the header and will go into a retry loop when the server rejects it.
> +CL 506995 adds the necessary validation to x/net/http2.
> +
> +Updates #60374
> +Fixes #61075
> +For CVE-2023-29406
> +
> +Change-Id: I05cb6866a9bead043101954dfded199258c6dd04
> +Reviewed-on: https://go-review.googlesource.com/c/go/+/506996
> +Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
> +TryBot-Result: Gopher Robot <gobot@golang.org>
> +Run-TryBot: Damien Neil <dneil@google.com>
> +(cherry picked from commit 499458f7ca04087958987a33c2703c3ef03e27e2)
> +Reviewed-on: https://go-review.googlesource.com/c/go/+/507358
> +Run-TryBot: Tatiana Bradley <tatianabradley@google.com>
> +Reviewed-by: Roland Shoemaker <roland@golang.org>
> +
> +Upstream-Status: Backport [https://github.com/golang/go/commit/5fa6923b1ea891400153d04ddf1545e23b40041b]
> +CVE: CVE-2023-29406
> +Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
> +---
> + src/net/http/http_test.go      | 29 ----------------------
> + src/net/http/request.go        | 45 ++++++++--------------------------
> + src/net/http/request_test.go   | 11 ++-------
> + src/net/http/transport_test.go | 18 ++++++++++++++
> + 4 files changed, 30 insertions(+), 73 deletions(-)
> +
> +diff --git a/src/net/http/http_test.go b/src/net/http/http_test.go
> +index 0d92fe5..f03272a 100644
> +--- a/src/net/http/http_test.go
> ++++ b/src/net/http/http_test.go
> +@@ -48,35 +48,6 @@ func TestForeachHeaderElement(t *testing.T) {
> +	}
> + }
> +
> +-func TestCleanHost(t *testing.T) {
> +-	tests := []struct {
> +-		in, want string
> +-	}{
> +-		{"www.google.com", "www.google.com"},
> +-		{"www.google.com foo", "www.google.com"},
> +-		{"www.google.com/foo", "www.google.com"},
> +-		{" first character is a space", ""},
> +-		{"[1::6]:8080", "[1::6]:8080"},
> +-
> +-		// Punycode:
> +-		{"гофер.рф/foo", "xn--c1ae0ajs.xn--p1ai"},
> +-		{"bücher.de", "xn--bcher-kva.de"},
> +-		{"bücher.de:8080", "xn--bcher-kva.de:8080"},
> +-		// Verify we convert to lowercase before punycode:
> +-		{"BÜCHER.de", "xn--bcher-kva.de"},
> +-		{"BÜCHER.de:8080", "xn--bcher-kva.de:8080"},
> +-		// Verify we normalize to NFC before punycode:
> +-		{"gophér.nfc", "xn--gophr-esa.nfc"},            // NFC input; no work needed
> +-		{"goph\u0065\u0301r.nfd", "xn--gophr-esa.nfd"}, // NFD input
> +-	}
> +-	for _, tt := range tests {
> +-		got := cleanHost(tt.in)
> +-		if tt.want != got {
> +-			t.Errorf("cleanHost(%q) = %q, want %q", tt.in, got, tt.want)
> +-		}
> +-	}
> +-}
> +-
> + // Test that cmd/go doesn't link in the HTTP server.
> + //
> + // This catches accidental dependencies between the HTTP transport and
> +diff --git a/src/net/http/request.go b/src/net/http/request.go
> +index 09cb0c7..2f4e740 100644
> +--- a/src/net/http/request.go
> ++++ b/src/net/http/request.go
> +@@ -17,7 +17,6 @@ import (
> +	"io"
> +	"mime"
> +	"mime/multipart"
> +-	"net"
> +	"net/http/httptrace"
> +	"net/http/internal/ascii"
> +	"net/textproto"
> +@@ -27,6 +26,7 @@ import (
> +	"strings"
> +	"sync"
> +
> ++	"golang.org/x/net/http/httpguts"
> +	"golang.org/x/net/idna"
> + )
> +
> +@@ -568,12 +568,19 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
> +	// is not given, use the host from the request URL.
> +	//
> +	// Clean the host, in case it arrives with unexpected stuff in it.
> +-	host := cleanHost(r.Host)
> ++	host := r.Host
> +	if host == "" {
> +		if r.URL == nil {
> +			return errMissingHost
> +		}
> +-		host = cleanHost(r.URL.Host)
> ++		host = r.URL.Host
> ++	}
> ++	host, err = httpguts.PunycodeHostPort(host)
> ++	if err != nil {
> ++		return err
> ++	}
> ++	if !httpguts.ValidHostHeader(host) {
> ++		return errors.New("http: invalid Host header")
> +	}
> +
> +	// According to RFC 6874, an HTTP client, proxy, or other
> +@@ -730,38 +737,6 @@ func idnaASCII(v string) (string, error) {
> +	return idna.Lookup.ToASCII(v)
> + }
> +
> +-// cleanHost cleans up the host sent in request's Host header.
> +-//
> +-// It both strips anything after '/' or ' ', and puts the value
> +-// into Punycode form, if necessary.
> +-//
> +-// Ideally we'd clean the Host header according to the spec:
> +-//   https://tools.ietf.org/html/rfc7230#section-5.4 (Host = uri-host [ ":" port ]")
> +-//   https://tools.ietf.org/html/rfc7230#section-2.7 (uri-host -> rfc3986's host)
> +-//   https://tools.ietf.org/html/rfc3986#section-3.2.2 (definition of host)
> +-// But practically, what we are trying to avoid is the situation in
> +-// issue 11206, where a malformed Host header used in the proxy context
> +-// would create a bad request. So it is enough to just truncate at the
> +-// first offending character.
> +-func cleanHost(in string) string {
> +-	if i := strings.IndexAny(in, " /"); i != -1 {
> +-		in = in[:i]
> +-	}
> +-	host, port, err := net.SplitHostPort(in)
> +-	if err != nil { // input was just a host
> +-		a, err := idnaASCII(in)
> +-		if err != nil {
> +-			return in // garbage in, garbage out
> +-		}
> +-		return a
> +-	}
> +-	a, err := idnaASCII(host)
> +-	if err != nil {
> +-		return in // garbage in, garbage out
> +-	}
> +-	return net.JoinHostPort(a, port)
> +-}
> +-
> + // removeZone removes IPv6 zone identifier from host.
> + // E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
> + func removeZone(host string) string {
> +diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
> +index fac12b7..368e87a 100644
> +--- a/src/net/http/request_test.go
> ++++ b/src/net/http/request_test.go
> +@@ -776,15 +776,8 @@ func TestRequestBadHost(t *testing.T) {
> +	}
> +	req.Host = "foo.com with spaces"
> +	req.URL.Host = "foo.com with spaces"
> +-	req.Write(logWrites{t, &got})
> +-	want := []string{
> +-		"GET /after HTTP/1.1\r\n",
> +-		"Host: foo.com\r\n",
> +-		"User-Agent: " + DefaultUserAgent + "\r\n",
> +-		"\r\n",
> +-	}
> +-	if !reflect.DeepEqual(got, want) {
> +-		t.Errorf("Writes = %q\n  Want = %q", got, want)
> ++	if err := req.Write(logWrites{t, &got}); err == nil {
> ++		t.Errorf("Writing request with invalid Host: succeded, want error")
> +	}
> + }
> +
> +diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
> +index eeaa492..58f12af 100644
> +--- a/src/net/http/transport_test.go
> ++++ b/src/net/http/transport_test.go
> +@@ -6512,3 +6512,21 @@ func TestCancelRequestWhenSharingConnection(t *testing.T) {
> +	close(r2c)
> +	wg.Wait()
> + }
> ++
> ++func TestRequestSanitization(t *testing.T) {
> ++	setParallel(t)
> ++	defer afterTest(t)
> ++
> ++	ts := newClientServerTest(t, h1Mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
> ++		if h, ok := req.Header["X-Evil"]; ok {
> ++			t.Errorf("request has X-Evil header: %q", h)
> ++		}
> ++	})).ts
> ++	defer ts.Close()
> ++	req, _ := NewRequest("GET", ts.URL, nil)
> ++	req.Host = "go.dev\r\nX-Evil:evil"
> ++	resp, _ := ts.Client().Do(req)
> ++	if resp != nil {
> ++		resp.Body.Close()
> ++	}
> ++}
> +--
> +2.25.1
> 
> 
> 
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#184856): https://lists.openembedded.org/g/openembedded-core/message/184856
> Mute This Topic: https://lists.openembedded.org/mt/100365153/7304958
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [liezhi.yang@eng.windriver.com]
> -=-=-=-=-=-=-=-=-=-=-=-
> 


  reply	other threads:[~2023-08-22  3:38 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-26  4:37 [OE-core][kirkstone][PATCH] go: fix CVE-2023-29406 net/http insufficient sanitization of Host header Vivek Kumbhar
2023-08-22  3:38 ` Robert Yang [this message]
2023-08-22  4:00   ` Vivek Kumbhar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86ec0a3c-e9bb-89e6-dd68-e8eb4b18bb16@windriver.com \
    --to=liezhi.yang@windriver.com \
    --cc=openembedded-core@lists.openembedded.org \
    --cc=vkumbhar@mvista.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.