summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch')
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch164
1 files changed, 164 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch
new file mode 100644
index 0000000000..8376dc45ba
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch
@@ -0,0 +1,164 @@
1From 753e3f8da191c2ac400407d83c70f46900769417 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 27 Oct 2022 12:22:41 +0530
4Subject: [PATCH] CVE-2022-2880
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/9d2c73a9fd69e45876509bb3bdb2af99bf77da1e]
7CVE: CVE-2022-2880
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9
10net/http/httputil: avoid query parameter
11
12Query parameter smuggling occurs when a proxy's interpretation
13of query parameters differs from that of a downstream server.
14Change ReverseProxy to avoid forwarding ignored query parameters.
15
16Remove unparsable query parameters from the outbound request
17
18 * if req.Form != nil after calling ReverseProxy.Director; and
19 * before calling ReverseProxy.Rewrite.
20
21This change preserves the existing behavior of forwarding the
22raw query untouched if a Director hook does not parse the query
23by calling Request.ParseForm (possibly indirectly).
24---
25 src/net/http/httputil/reverseproxy.go | 36 +++++++++++
26 src/net/http/httputil/reverseproxy_test.go | 74 ++++++++++++++++++++++
27 2 files changed, 110 insertions(+)
28
29diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
30index 2072a5f..c6fb873 100644
31--- a/src/net/http/httputil/reverseproxy.go
32+++ b/src/net/http/httputil/reverseproxy.go
33@@ -212,6 +212,9 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
34 }
35
36 p.Director(outreq)
37+ if outreq.Form != nil {
38+ outreq.URL.RawQuery = cleanQueryParams(outreq.URL.RawQuery)
39+ }
40 outreq.Close = false
41
42 reqUpType := upgradeType(outreq.Header)
43@@ -561,3 +564,36 @@ func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
44 _, err := io.Copy(c.backend, c.user)
45 errc <- err
46 }
47+
48+func cleanQueryParams(s string) string {
49+ reencode := func(s string) string {
50+ v, _ := url.ParseQuery(s)
51+ return v.Encode()
52+ }
53+ for i := 0; i < len(s); {
54+ switch s[i] {
55+ case ';':
56+ return reencode(s)
57+ case '%':
58+ if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
59+ return reencode(s)
60+ }
61+ i += 3
62+ default:
63+ i++
64+ }
65+ }
66+ return s
67+}
68+
69+func ishex(c byte) bool {
70+ switch {
71+ case '0' <= c && c <= '9':
72+ return true
73+ case 'a' <= c && c <= 'f':
74+ return true
75+ case 'A' <= c && c <= 'F':
76+ return true
77+ }
78+ return false
79+}
80diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
81index 9a7223a..bc87a3b 100644
82--- a/src/net/http/httputil/reverseproxy_test.go
83+++ b/src/net/http/httputil/reverseproxy_test.go
84@@ -1269,3 +1269,77 @@ func TestSingleJoinSlash(t *testing.T) {
85 }
86 }
87 }
88+
89+const (
90+ testWantsCleanQuery = true
91+ testWantsRawQuery = false
92+)
93+
94+func TestReverseProxyQueryParameterSmugglingDirectorDoesNotParseForm(t *testing.T) {
95+ testReverseProxyQueryParameterSmuggling(t, testWantsRawQuery, func(u *url.URL) *ReverseProxy {
96+ proxyHandler := NewSingleHostReverseProxy(u)
97+ oldDirector := proxyHandler.Director
98+ proxyHandler.Director = func(r *http.Request) {
99+ oldDirector(r)
100+ }
101+ return proxyHandler
102+ })
103+}
104+
105+func TestReverseProxyQueryParameterSmugglingDirectorParsesForm(t *testing.T) {
106+ testReverseProxyQueryParameterSmuggling(t, testWantsCleanQuery, func(u *url.URL) *ReverseProxy {
107+ proxyHandler := NewSingleHostReverseProxy(u)
108+ oldDirector := proxyHandler.Director
109+ proxyHandler.Director = func(r *http.Request) {
110+ // Parsing the form causes ReverseProxy to remove unparsable
111+ // query parameters before forwarding.
112+ r.FormValue("a")
113+ oldDirector(r)
114+ }
115+ return proxyHandler
116+ })
117+}
118+
119+func testReverseProxyQueryParameterSmuggling(t *testing.T, wantCleanQuery bool, newProxy func(*url.URL) *ReverseProxy) {
120+ const content = "response_content"
121+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
122+ w.Write([]byte(r.URL.RawQuery))
123+ }))
124+ defer backend.Close()
125+ backendURL, err := url.Parse(backend.URL)
126+ if err != nil {
127+ t.Fatal(err)
128+ }
129+ proxyHandler := newProxy(backendURL)
130+ frontend := httptest.NewServer(proxyHandler)
131+ defer frontend.Close()
132+
133+ // Don't spam output with logs of queries containing semicolons.
134+ backend.Config.ErrorLog = log.New(io.Discard, "", 0)
135+ frontend.Config.ErrorLog = log.New(io.Discard, "", 0)
136+
137+ for _, test := range []struct {
138+ rawQuery string
139+ cleanQuery string
140+ }{{
141+ rawQuery: "a=1&a=2;b=3",
142+ cleanQuery: "a=1",
143+ }, {
144+ rawQuery: "a=1&a=%zz&b=3",
145+ cleanQuery: "a=1&b=3",
146+ }} {
147+ res, err := frontend.Client().Get(frontend.URL + "?" + test.rawQuery)
148+ if err != nil {
149+ t.Fatalf("Get: %v", err)
150+ }
151+ defer res.Body.Close()
152+ body, _ := io.ReadAll(res.Body)
153+ wantQuery := test.rawQuery
154+ if wantCleanQuery {
155+ wantQuery = test.cleanQuery
156+ }
157+ if got, want := string(body), wantQuery; got != want {
158+ t.Errorf("proxy forwarded raw query %q as %q, want %q", test.rawQuery, got, want)
159+ }
160+ }
161+}
162--
1632.25.1
164