All of lore.kernel.org
 help / color / mirror / Atom feed
* [meta-virtualization][PATCH] kubernetes: fix CVE-2020-8559
@ 2020-07-27 17:13 sakib.sajal
  2020-07-27 17:18 ` Bruce Ashfield
  0 siblings, 1 reply; 3+ messages in thread
From: sakib.sajal @ 2020-07-27 17:13 UTC (permalink / raw)
  To: meta-virtualization

Backported fix to resolve CVE-2020-8559.

Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
---
 ...turn-proxied-redirects-to-the-client.patch | 149 ++++++++++++++++++
 .../kubernetes/kubernetes_git.bb              |   1 +
 2 files changed, 150 insertions(+)
 create mode 100644 recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch

diff --git a/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch b/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
new file mode 100644
index 0000000..c4552cd
--- /dev/null
+++ b/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
@@ -0,0 +1,149 @@
+From 469c439ea18cb6cc58e36357b9ead15d68122341 Mon Sep 17 00:00:00 2001
+From: Tim Allclair <tallclair@google.com>
+Date: Wed, 17 Jun 2020 11:09:02 -0700
+Subject: [PATCH] Don't return proxied redirects to the client
+
+Upstream-Status: Backport [469c439ea18cb6cc58e36357b9ead15d68122341]
+CVE: CVE-2020-8559
+Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
+
+---
+ .../k8s.io/apimachinery/pkg/util/net/http.go  |  2 +-
+ .../apimachinery/pkg/util/net/http_test.go    | 12 ++---
+ .../pkg/util/proxy/upgradeaware.go            | 10 ++++
+ .../pkg/util/proxy/upgradeaware_test.go       | 47 ++++++++++++++++++-
+ 4 files changed, 62 insertions(+), 9 deletions(-)
+
+diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
+index 7449cbb0a01..7b64e68157e 100644
+--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
+@@ -446,7 +446,7 @@ redirectLoop:
+ 
+ 		// Only follow redirects to the same host. Otherwise, propagate the redirect response back.
+ 		if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() {
+-			break redirectLoop
++			return nil, nil, fmt.Errorf("hostname mismatch: expected %s, found %s", originalLocation.Hostname(), location.Hostname())
+ 		}
+ 
+ 		// Reset the connection.
+diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
+index da483c3563b..2fd3675d4fd 100644
+--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
+@@ -330,13 +330,13 @@ func TestConnectWithRedirects(t *testing.T) {
+ 		redirects:   []string{"/1", "/2", "/3", "/4", "/5", "/6", "/7", "/8", "/9", "/10"},
+ 		expectError: true,
+ 	}, {
+-		desc:              "redirect to different host are prevented",
+-		redirects:         []string{"http://example.com/foo"},
+-		expectedRedirects: 0,
++		desc:        "redirect to different host are prevented",
++		redirects:   []string{"http://example.com/foo"},
++		expectError: true,
+ 	}, {
+-		desc:              "multiple redirect to different host forbidden",
+-		redirects:         []string{"/1", "/2", "/3", "http://example.com/foo"},
+-		expectedRedirects: 3,
++		desc:        "multiple redirect to different host forbidden",
++		redirects:   []string{"/1", "/2", "/3", "http://example.com/foo"},
++		expectError: true,
+ 	}, {
+ 		desc:              "redirect to different port is allowed",
+ 		redirects:         []string{"http://HOST/foo"},
+diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
+index d007c10b506..39c79be81bd 100644
+--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
+@@ -298,6 +298,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
+ 		rawResponse = headerBytes
+ 	}
+ 
++	// If the backend did not upgrade the request, return an error to the client. If the response was
++	// an error, the error is forwarded directly after the connection is hijacked. Otherwise, just
++	// return a generic error here.
++	if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 {
++		err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode)
++		klog.Errorf("Proxy upgrade error: %v", err)
++		h.Responder.Error(w, req, err)
++		return true
++	}
++
+ 	// Once the connection is hijacked, the ErrorResponder will no longer work, so
+ 	// hijacking should be the last step in the upgrade.
+ 	requestHijacker, ok := w.(http.Hijacker)
+diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
+index 710fc6a9c21..c1dfb029d93 100644
+--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
+@@ -512,7 +512,7 @@ func (r *noErrorsAllowed) Error(w http.ResponseWriter, req *http.Request, err er
+ 	r.t.Error(err)
+ }
+ 
+-func TestProxyUpgradeErrorResponse(t *testing.T) {
++func TestProxyUpgradeConnectionErrorResponse(t *testing.T) {
+ 	var (
+ 		responder   *fakeResponder
+ 		expectedErr = errors.New("EXPECTED")
+@@ -560,7 +560,7 @@ func TestProxyUpgradeErrorResponse(t *testing.T) {
+ 
+ func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
+ 	for _, intercept := range []bool{true, false} {
+-		for _, code := range []int{200, 400, 500} {
++		for _, code := range []int{400, 500} {
+ 			t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
+ 				// Set up a backend server
+ 				backend := http.NewServeMux()
+@@ -620,6 +620,49 @@ func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
+ 	}
+ }
+ 
++func TestProxyUpgradeErrorResponse(t *testing.T) {
++	for _, intercept := range []bool{true, false} {
++		for _, code := range []int{200, 300, 302, 307} {
++			t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
++				// Set up a backend server
++				backend := http.NewServeMux()
++				backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
++					http.Redirect(w, r, "https://example.com/there", code)
++				}))
++				backendServer := httptest.NewServer(backend)
++				defer backendServer.Close()
++				backendServerURL, _ := url.Parse(backendServer.URL)
++				backendServerURL.Path = "/hello"
++
++				// Set up a proxy pointing to a specific path on the backend
++				proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t})
++				proxyHandler.InterceptRedirects = intercept
++				proxyHandler.RequireSameHostRedirects = true
++				proxy := httptest.NewServer(proxyHandler)
++				defer proxy.Close()
++				proxyURL, _ := url.Parse(proxy.URL)
++
++				conn, err := net.Dial("tcp", proxyURL.Host)
++				require.NoError(t, err)
++				bufferedReader := bufio.NewReader(conn)
++
++				// Send upgrade request resulting in a non-101 response from the backend
++				req, _ := http.NewRequest("GET", "/", nil)
++				req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
++				require.NoError(t, req.Write(conn))
++				// Verify we get the correct response and full message body content
++				resp, err := http.ReadResponse(bufferedReader, nil)
++				require.NoError(t, err)
++				assert.Equal(t, fakeStatusCode, resp.StatusCode)
++				resp.Body.Close()
++
++				// clean up
++				conn.Close()
++			})
++		}
++	}
++}
++
+ func TestDefaultProxyTransport(t *testing.T) {
+ 	tests := []struct {
+ 		name,
+-- 
+2.20.1
+
diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb
index d28e6a2..156e083 100644
--- a/recipes-containers/kubernetes/kubernetes_git.bb
+++ b/recipes-containers/kubernetes/kubernetes_git.bb
@@ -13,6 +13,7 @@ SRC_URI = "git://github.com/kubernetes/kubernetes.git;branch=release-1.18;name=k
            git://github.com/kubernetes/release;branch=master;name=kubernetes-release;destsuffix=git/release \
            file://0001-hack-lib-golang.sh-use-CC-from-environment.patch \
            file://0001-cross-don-t-build-tests-by-default.patch \
+           file://0001-Don-t-return-proxied-redirects-to-the-client.patch \
           "
 
 DEPENDS += "rsync-native \
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [meta-virtualization][PATCH] kubernetes: fix CVE-2020-8559
  2020-07-27 17:13 [meta-virtualization][PATCH] kubernetes: fix CVE-2020-8559 sakib.sajal
@ 2020-07-27 17:18 ` Bruce Ashfield
  2020-07-27 18:10   ` sakib.sajal
  0 siblings, 1 reply; 3+ messages in thread
From: Bruce Ashfield @ 2020-07-27 17:18 UTC (permalink / raw)
  To: Sakib Sajal; +Cc: meta-virtualization

[-- Attachment #1: Type: text/plain, Size: 11021 bytes --]

On Mon, Jul 27, 2020 at 1:14 PM <sakib.sajal@windriver.com> wrote:

> Backported fix to resolve CVE-2020-8559.
>

This is on the release 1.18 branch, it makes no sense to do a backport of
an individual patch.

We will refresh k8s again shortly, so it will be picked up by that.

Bruce



>
> Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
> ---
>  ...turn-proxied-redirects-to-the-client.patch | 149 ++++++++++++++++++
>  .../kubernetes/kubernetes_git.bb              |   1 +
>  2 files changed, 150 insertions(+)
>  create mode 100644
> recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
>
> diff --git
> a/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
> b/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
> new file mode 100644
> index 0000000..c4552cd
> --- /dev/null
> +++
> b/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
> @@ -0,0 +1,149 @@
> +From 469c439ea18cb6cc58e36357b9ead15d68122341 Mon Sep 17 00:00:00 2001
> +From: Tim Allclair <tallclair@google.com>
> +Date: Wed, 17 Jun 2020 11:09:02 -0700
> +Subject: [PATCH] Don't return proxied redirects to the client
> +
> +Upstream-Status: Backport [469c439ea18cb6cc58e36357b9ead15d68122341]
> +CVE: CVE-2020-8559
> +Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
> +
> +---
> + .../k8s.io/apimachinery/pkg/util/net/http.go  |  2 +-
> + .../apimachinery/pkg/util/net/http_test.go    | 12 ++---
> + .../pkg/util/proxy/upgradeaware.go            | 10 ++++
> + .../pkg/util/proxy/upgradeaware_test.go       | 47 ++++++++++++++++++-
> + 4 files changed, 62 insertions(+), 9 deletions(-)
> +
> +diff --git a/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/net/http.go b/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/net/http.go
> +index 7449cbb0a01..7b64e68157e 100644
> +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
> ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
> +@@ -446,7 +446,7 @@ redirectLoop:
> +
> +               // Only follow redirects to the same host. Otherwise,
> propagate the redirect response back.
> +               if requireSameHostRedirects && location.Hostname() !=
> originalLocation.Hostname() {
> +-                      break redirectLoop
> ++                      return nil, nil, fmt.Errorf("hostname mismatch:
> expected %s, found %s", originalLocation.Hostname(), location.Hostname())
> +               }
> +
> +               // Reset the connection.
> +diff --git a/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/net/http_test.go b/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/net/http_test.go
> +index da483c3563b..2fd3675d4fd 100644
> +--- a/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/net/http_test.go
> ++++ b/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/net/http_test.go
> +@@ -330,13 +330,13 @@ func TestConnectWithRedirects(t *testing.T) {
> +               redirects:   []string{"/1", "/2", "/3", "/4", "/5", "/6",
> "/7", "/8", "/9", "/10"},
> +               expectError: true,
> +       }, {
> +-              desc:              "redirect to different host are
> prevented",
> +-              redirects:         []string{"http://example.com/foo"},
> +-              expectedRedirects: 0,
> ++              desc:        "redirect to different host are prevented",
> ++              redirects:   []string{"http://example.com/foo"},
> ++              expectError: true,
> +       }, {
> +-              desc:              "multiple redirect to different host
> forbidden",
> +-              redirects:         []string{"/1", "/2", "/3", "
> http://example.com/foo"},
> +-              expectedRedirects: 3,
> ++              desc:        "multiple redirect to different host
> forbidden",
> ++              redirects:   []string{"/1", "/2", "/3", "
> http://example.com/foo"},
> ++              expectError: true,
> +       }, {
> +               desc:              "redirect to different port is allowed",
> +               redirects:         []string{"http://HOST/foo"},
> +diff --git a/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
> b/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
> +index d007c10b506..39c79be81bd 100644
> +--- a/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
> ++++ b/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
> +@@ -298,6 +298,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w
> http.ResponseWriter, req *http.Reques
> +               rawResponse = headerBytes
> +       }
> +
> ++      // If the backend did not upgrade the request, return an error to
> the client. If the response was
> ++      // an error, the error is forwarded directly after the connection
> is hijacked. Otherwise, just
> ++      // return a generic error here.
> ++      if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols
> && backendHTTPResponse.StatusCode < 400 {
> ++              err := fmt.Errorf("invalid upgrade response: status code
> %d", backendHTTPResponse.StatusCode)
> ++              klog.Errorf("Proxy upgrade error: %v", err)
> ++              h.Responder.Error(w, req, err)
> ++              return true
> ++      }
> ++
> +       // Once the connection is hijacked, the ErrorResponder will no
> longer work, so
> +       // hijacking should be the last step in the upgrade.
> +       requestHijacker, ok := w.(http.Hijacker)
> +diff --git a/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
> b/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
> +index 710fc6a9c21..c1dfb029d93 100644
> +--- a/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
> ++++ b/src/import/staging/src/
> k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
> +@@ -512,7 +512,7 @@ func (r *noErrorsAllowed) Error(w
> http.ResponseWriter, req *http.Request, err er
> +       r.t.Error(err)
> + }
> +
> +-func TestProxyUpgradeErrorResponse(t *testing.T) {
> ++func TestProxyUpgradeConnectionErrorResponse(t *testing.T) {
> +       var (
> +               responder   *fakeResponder
> +               expectedErr = errors.New("EXPECTED")
> +@@ -560,7 +560,7 @@ func TestProxyUpgradeErrorResponse(t *testing.T) {
> +
> + func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
> +       for _, intercept := range []bool{true, false} {
> +-              for _, code := range []int{200, 400, 500} {
> ++              for _, code := range []int{400, 500} {
> +                       t.Run(fmt.Sprintf("intercept=%v,code=%v",
> intercept, code), func(t *testing.T) {
> +                               // Set up a backend server
> +                               backend := http.NewServeMux()
> +@@ -620,6 +620,49 @@ func TestProxyUpgradeErrorResponseTerminates(t
> *testing.T) {
> +       }
> + }
> +
> ++func TestProxyUpgradeErrorResponse(t *testing.T) {
> ++      for _, intercept := range []bool{true, false} {
> ++              for _, code := range []int{200, 300, 302, 307} {
> ++                      t.Run(fmt.Sprintf("intercept=%v,code=%v",
> intercept, code), func(t *testing.T) {
> ++                              // Set up a backend server
> ++                              backend := http.NewServeMux()
> ++                              backend.Handle("/hello",
> http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
> ++                                      http.Redirect(w, r, "
> https://example.com/there", code)
> ++                              }))
> ++                              backendServer :=
> httptest.NewServer(backend)
> ++                              defer backendServer.Close()
> ++                              backendServerURL, _ :=
> url.Parse(backendServer.URL)
> ++                              backendServerURL.Path = "/hello"
> ++
> ++                              // Set up a proxy pointing to a specific
> path on the backend
> ++                              proxyHandler :=
> NewUpgradeAwareHandler(backendServerURL, nil, false, false,
> &fakeResponder{t: t})
> ++                              proxyHandler.InterceptRedirects = intercept
> ++                              proxyHandler.RequireSameHostRedirects =
> true
> ++                              proxy := httptest.NewServer(proxyHandler)
> ++                              defer proxy.Close()
> ++                              proxyURL, _ := url.Parse(proxy.URL)
> ++
> ++                              conn, err := net.Dial("tcp", proxyURL.Host)
> ++                              require.NoError(t, err)
> ++                              bufferedReader := bufio.NewReader(conn)
> ++
> ++                              // Send upgrade request resulting in a
> non-101 response from the backend
> ++                              req, _ := http.NewRequest("GET", "/", nil)
> ++
> req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
> ++                              require.NoError(t, req.Write(conn))
> ++                              // Verify we get the correct response and
> full message body content
> ++                              resp, err :=
> http.ReadResponse(bufferedReader, nil)
> ++                              require.NoError(t, err)
> ++                              assert.Equal(t, fakeStatusCode,
> resp.StatusCode)
> ++                              resp.Body.Close()
> ++
> ++                              // clean up
> ++                              conn.Close()
> ++                      })
> ++              }
> ++      }
> ++}
> ++
> + func TestDefaultProxyTransport(t *testing.T) {
> +       tests := []struct {
> +               name,
> +--
> +2.20.1
> +
> diff --git a/recipes-containers/kubernetes/kubernetes_git.bb
> b/recipes-containers/kubernetes/kubernetes_git.bb
> index d28e6a2..156e083 100644
> --- a/recipes-containers/kubernetes/kubernetes_git.bb
> +++ b/recipes-containers/kubernetes/kubernetes_git.bb
> @@ -13,6 +13,7 @@ SRC_URI = "git://
> github.com/kubernetes/kubernetes.git;branch=release-1.18;name=k
>             git://
> github.com/kubernetes/release;branch=master;name=kubernetes-release;destsuffix=git/release
> \
>             file://0001-hack-lib-golang.sh-use-CC-from-environment.patch \
>             file://0001-cross-don-t-build-tests-by-default.patch \
> +           file://0001-Don-t-return-proxied-redirects-to-the-client.patch
> \
>            "
>
>  DEPENDS += "rsync-native \
> --
> 2.17.1
>
> 
>


-- 
- Thou shalt not follow the NULL pointer, for chaos and madness await thee
at its end
- "Use the force Harry" - Gandalf, Star Trek II

[-- Attachment #2: Type: text/html, Size: 16490 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [meta-virtualization][PATCH] kubernetes: fix CVE-2020-8559
  2020-07-27 17:18 ` Bruce Ashfield
@ 2020-07-27 18:10   ` sakib.sajal
  0 siblings, 0 replies; 3+ messages in thread
From: sakib.sajal @ 2020-07-27 18:10 UTC (permalink / raw)
  To: Bruce Ashfield; +Cc: meta-virtualization


On 2020-07-27 1:18 p.m., Bruce Ashfield wrote:
> On Mon, Jul 27, 2020 at 1:14 PM <sakib.sajal@windriver.com> wrote:
>
>> Backported fix to resolve CVE-2020-8559.
>>
> This is on the release 1.18 branch, it makes no sense to do a backport of
> an individual patch.
>
> We will refresh k8s again shortly, so it will be picked up by that.
>
> Bruce
>
Thanks for the information.

Sakib

>
>> Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
>> ---
>>   ...turn-proxied-redirects-to-the-client.patch | 149 ++++++++++++++++++
>>   .../kubernetes/kubernetes_git.bb              |   1 +
>>   2 files changed, 150 insertions(+)
>>   create mode 100644
>> recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
>>
>> diff --git
>> a/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
>> b/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
>> new file mode 100644
>> index 0000000..c4552cd
>> --- /dev/null
>> +++
>> b/recipes-containers/kubernetes/kubernetes/0001-Don-t-return-proxied-redirects-to-the-client.patch
>> @@ -0,0 +1,149 @@
>> +From 469c439ea18cb6cc58e36357b9ead15d68122341 Mon Sep 17 00:00:00 2001
>> +From: Tim Allclair <tallclair@google.com>
>> +Date: Wed, 17 Jun 2020 11:09:02 -0700
>> +Subject: [PATCH] Don't return proxied redirects to the client
>> +
>> +Upstream-Status: Backport [469c439ea18cb6cc58e36357b9ead15d68122341]
>> +CVE: CVE-2020-8559
>> +Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
>> +
>> +---
>> + .../k8s.io/apimachinery/pkg/util/net/http.go  |  2 +-
>> + .../apimachinery/pkg/util/net/http_test.go    | 12 ++---
>> + .../pkg/util/proxy/upgradeaware.go            | 10 ++++
>> + .../pkg/util/proxy/upgradeaware_test.go       | 47 ++++++++++++++++++-
>> + 4 files changed, 62 insertions(+), 9 deletions(-)
>> +
>> +diff --git a/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/net/http.go b/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/net/http.go
>> +index 7449cbb0a01..7b64e68157e 100644
>> +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
>> ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
>> +@@ -446,7 +446,7 @@ redirectLoop:
>> +
>> +               // Only follow redirects to the same host. Otherwise,
>> propagate the redirect response back.
>> +               if requireSameHostRedirects && location.Hostname() !=
>> originalLocation.Hostname() {
>> +-                      break redirectLoop
>> ++                      return nil, nil, fmt.Errorf("hostname mismatch:
>> expected %s, found %s", originalLocation.Hostname(), location.Hostname())
>> +               }
>> +
>> +               // Reset the connection.
>> +diff --git a/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/net/http_test.go b/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/net/http_test.go
>> +index da483c3563b..2fd3675d4fd 100644
>> +--- a/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/net/http_test.go
>> ++++ b/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/net/http_test.go
>> +@@ -330,13 +330,13 @@ func TestConnectWithRedirects(t *testing.T) {
>> +               redirects:   []string{"/1", "/2", "/3", "/4", "/5", "/6",
>> "/7", "/8", "/9", "/10"},
>> +               expectError: true,
>> +       }, {
>> +-              desc:              "redirect to different host are
>> prevented",
>> +-              redirects:         []string{"http://example.com/foo"},
>> +-              expectedRedirects: 0,
>> ++              desc:        "redirect to different host are prevented",
>> ++              redirects:   []string{"http://example.com/foo"},
>> ++              expectError: true,
>> +       }, {
>> +-              desc:              "multiple redirect to different host
>> forbidden",
>> +-              redirects:         []string{"/1", "/2", "/3", "
>> http://example.com/foo"},
>> +-              expectedRedirects: 3,
>> ++              desc:        "multiple redirect to different host
>> forbidden",
>> ++              redirects:   []string{"/1", "/2", "/3", "
>> http://example.com/foo"},
>> ++              expectError: true,
>> +       }, {
>> +               desc:              "redirect to different port is allowed",
>> +               redirects:         []string{"http://HOST/foo"},
>> +diff --git a/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>> b/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>> +index d007c10b506..39c79be81bd 100644
>> +--- a/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>> ++++ b/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>> +@@ -298,6 +298,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w
>> http.ResponseWriter, req *http.Reques
>> +               rawResponse = headerBytes
>> +       }
>> +
>> ++      // If the backend did not upgrade the request, return an error to
>> the client. If the response was
>> ++      // an error, the error is forwarded directly after the connection
>> is hijacked. Otherwise, just
>> ++      // return a generic error here.
>> ++      if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols
>> && backendHTTPResponse.StatusCode < 400 {
>> ++              err := fmt.Errorf("invalid upgrade response: status code
>> %d", backendHTTPResponse.StatusCode)
>> ++              klog.Errorf("Proxy upgrade error: %v", err)
>> ++              h.Responder.Error(w, req, err)
>> ++              return true
>> ++      }
>> ++
>> +       // Once the connection is hijacked, the ErrorResponder will no
>> longer work, so
>> +       // hijacking should be the last step in the upgrade.
>> +       requestHijacker, ok := w.(http.Hijacker)
>> +diff --git a/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>> b/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>> +index 710fc6a9c21..c1dfb029d93 100644
>> +--- a/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>> ++++ b/src/import/staging/src/
>> k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>> +@@ -512,7 +512,7 @@ func (r *noErrorsAllowed) Error(w
>> http.ResponseWriter, req *http.Request, err er
>> +       r.t.Error(err)
>> + }
>> +
>> +-func TestProxyUpgradeErrorResponse(t *testing.T) {
>> ++func TestProxyUpgradeConnectionErrorResponse(t *testing.T) {
>> +       var (
>> +               responder   *fakeResponder
>> +               expectedErr = errors.New("EXPECTED")
>> +@@ -560,7 +560,7 @@ func TestProxyUpgradeErrorResponse(t *testing.T) {
>> +
>> + func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
>> +       for _, intercept := range []bool{true, false} {
>> +-              for _, code := range []int{200, 400, 500} {
>> ++              for _, code := range []int{400, 500} {
>> +                       t.Run(fmt.Sprintf("intercept=%v,code=%v",
>> intercept, code), func(t *testing.T) {
>> +                               // Set up a backend server
>> +                               backend := http.NewServeMux()
>> +@@ -620,6 +620,49 @@ func TestProxyUpgradeErrorResponseTerminates(t
>> *testing.T) {
>> +       }
>> + }
>> +
>> ++func TestProxyUpgradeErrorResponse(t *testing.T) {
>> ++      for _, intercept := range []bool{true, false} {
>> ++              for _, code := range []int{200, 300, 302, 307} {
>> ++                      t.Run(fmt.Sprintf("intercept=%v,code=%v",
>> intercept, code), func(t *testing.T) {
>> ++                              // Set up a backend server
>> ++                              backend := http.NewServeMux()
>> ++                              backend.Handle("/hello",
>> http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
>> ++                                      http.Redirect(w, r, "
>> https://example.com/there", code)
>> ++                              }))
>> ++                              backendServer :=
>> httptest.NewServer(backend)
>> ++                              defer backendServer.Close()
>> ++                              backendServerURL, _ :=
>> url.Parse(backendServer.URL)
>> ++                              backendServerURL.Path = "/hello"
>> ++
>> ++                              // Set up a proxy pointing to a specific
>> path on the backend
>> ++                              proxyHandler :=
>> NewUpgradeAwareHandler(backendServerURL, nil, false, false,
>> &fakeResponder{t: t})
>> ++                              proxyHandler.InterceptRedirects = intercept
>> ++                              proxyHandler.RequireSameHostRedirects =
>> true
>> ++                              proxy := httptest.NewServer(proxyHandler)
>> ++                              defer proxy.Close()
>> ++                              proxyURL, _ := url.Parse(proxy.URL)
>> ++
>> ++                              conn, err := net.Dial("tcp", proxyURL.Host)
>> ++                              require.NoError(t, err)
>> ++                              bufferedReader := bufio.NewReader(conn)
>> ++
>> ++                              // Send upgrade request resulting in a
>> non-101 response from the backend
>> ++                              req, _ := http.NewRequest("GET", "/", nil)
>> ++
>> req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
>> ++                              require.NoError(t, req.Write(conn))
>> ++                              // Verify we get the correct response and
>> full message body content
>> ++                              resp, err :=
>> http.ReadResponse(bufferedReader, nil)
>> ++                              require.NoError(t, err)
>> ++                              assert.Equal(t, fakeStatusCode,
>> resp.StatusCode)
>> ++                              resp.Body.Close()
>> ++
>> ++                              // clean up
>> ++                              conn.Close()
>> ++                      })
>> ++              }
>> ++      }
>> ++}
>> ++
>> + func TestDefaultProxyTransport(t *testing.T) {
>> +       tests := []struct {
>> +               name,
>> +--
>> +2.20.1
>> +
>> diff --git a/recipes-containers/kubernetes/kubernetes_git.bb
>> b/recipes-containers/kubernetes/kubernetes_git.bb
>> index d28e6a2..156e083 100644
>> --- a/recipes-containers/kubernetes/kubernetes_git.bb
>> +++ b/recipes-containers/kubernetes/kubernetes_git.bb
>> @@ -13,6 +13,7 @@ SRC_URI = "git://
>> github.com/kubernetes/kubernetes.git;branch=release-1.18;name=k
>>              git://
>> github.com/kubernetes/release;branch=master;name=kubernetes-release;destsuffix=git/release
>> \
>>              file://0001-hack-lib-golang.sh-use-CC-from-environment.patch \
>>              file://0001-cross-don-t-build-tests-by-default.patch \
>> +           file://0001-Don-t-return-proxied-redirects-to-the-client.patch
>> \
>>             "
>>
>>   DEPENDS += "rsync-native \
>> --
>> 2.17.1
>>
>> 
>>
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-07-27 18:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-27 17:13 [meta-virtualization][PATCH] kubernetes: fix CVE-2020-8559 sakib.sajal
2020-07-27 17:18 ` Bruce Ashfield
2020-07-27 18:10   ` sakib.sajal

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.