aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/cgi
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2016-07-18 06:05:24 +0000
committerChris Broadfoot <cbro@golang.org>2016-07-18 15:13:06 +0000
commitcad4e97af8f2e0b9f09b97f67fb3a89ced2e9021 (patch)
treefb24b2f2ebc41e265ea34f318d6dfe6fcd525651 /src/net/http/cgi
parent53da5fd4d431881bb3583c9790db7735a6530a1b (diff)
downloadgo-cad4e97af8f2e0b9f09b97f67fb3a89ced2e9021.tar.xz
[release-branch.go1.7] net/http, net/http/cgi: fix for CGI + HTTP_PROXY security issue
Because, * The CGI spec defines that incoming request header "Foo: Bar" maps to environment variable HTTP_FOO == "Bar". (see RFC 3875 4.1.18) * The HTTP_PROXY environment variable is conventionally used to configure the HTTP proxy for HTTP clients (and is respected by default for Go's net/http.Client and Transport) That means Go programs running in a CGI environment (as a child process under a CGI host) are vulnerable to an incoming request containing "Proxy: attacker.com:1234", setting HTTP_PROXY, and changing where Go by default proxies all outbound HTTP requests. This is CVE-2016-5386, aka https://httpoxy.org/ Fixes #16405 Change-Id: I6f68ade85421b4807785799f6d98a8b077e871f0 Reviewed-on: https://go-review.googlesource.com/25010 Run-TryBot: Chris Broadfoot <cbro@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Chris Broadfoot <cbro@golang.org> Reviewed-on: https://go-review.googlesource.com/25013
Diffstat (limited to 'src/net/http/cgi')
-rw-r--r--src/net/http/cgi/host.go4
-rw-r--r--src/net/http/cgi/host_test.go37
2 files changed, 38 insertions, 3 deletions
diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go
index 2eea64334b..58e9f7132a 100644
--- a/src/net/http/cgi/host.go
+++ b/src/net/http/cgi/host.go
@@ -153,6 +153,10 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
for k, v := range req.Header {
k = strings.Map(upperCaseAndUnderscore, k)
+ if k == "PROXY" {
+ // See Issue 16405
+ continue
+ }
joinStr := ", "
if k == "COOKIE" {
joinStr = "; "
diff --git a/src/net/http/cgi/host_test.go b/src/net/http/cgi/host_test.go
index 70c5aff5e2..11213349a7 100644
--- a/src/net/http/cgi/host_test.go
+++ b/src/net/http/cgi/host_test.go
@@ -35,15 +35,18 @@ func newRequest(httpreq string) *http.Request {
return req
}
-func runCgiTest(t *testing.T, h *Handler, httpreq string, expectedMap map[string]string) *httptest.ResponseRecorder {
+func runCgiTest(t *testing.T, h *Handler,
+ httpreq string,
+ expectedMap map[string]string, checks ...func(reqInfo map[string]string)) *httptest.ResponseRecorder {
rw := httptest.NewRecorder()
req := newRequest(httpreq)
h.ServeHTTP(rw, req)
- runResponseChecks(t, rw, expectedMap)
+ runResponseChecks(t, rw, expectedMap, checks...)
return rw
}
-func runResponseChecks(t *testing.T, rw *httptest.ResponseRecorder, expectedMap map[string]string) {
+func runResponseChecks(t *testing.T, rw *httptest.ResponseRecorder,
+ expectedMap map[string]string, checks ...func(reqInfo map[string]string)) {
// Make a map to hold the test map that the CGI returns.
m := make(map[string]string)
m["_body"] = rw.Body.String()
@@ -81,6 +84,9 @@ readlines:
t.Errorf("for key %q got %q; expected %q", key, got, expected)
}
}
+ for _, check := range checks {
+ check(m)
+ }
}
var cgiTested, cgiWorks bool
@@ -236,6 +242,31 @@ func TestDupHeaders(t *testing.T) {
expectedMap)
}
+// Issue 16405: CGI+http.Transport differing uses of HTTP_PROXY.
+// Verify we don't set the HTTP_PROXY environment variable.
+// Hope nobody was depending on it. It's not a known header, though.
+func TestDropProxyHeader(t *testing.T) {
+ check(t)
+ h := &Handler{
+ Path: "testdata/test.cgi",
+ }
+ expectedMap := map[string]string{
+ "env-REQUEST_URI": "/myscript/bar?a=b",
+ "env-SCRIPT_FILENAME": "testdata/test.cgi",
+ "env-HTTP_X_FOO": "a",
+ }
+ runCgiTest(t, h, "GET /myscript/bar?a=b HTTP/1.0\n"+
+ "X-Foo: a\n"+
+ "Proxy: should_be_stripped\n"+
+ "Host: example.com\n\n",
+ expectedMap,
+ func(reqInfo map[string]string) {
+ if v, ok := reqInfo["env-HTTP_PROXY"]; ok {
+ t.Errorf("HTTP_PROXY = %q; should be absent", v)
+ }
+ })
+}
+
func TestPathInfoNoRoot(t *testing.T) {
check(t)
h := &Handler{