File CVE-2016-5386.patch of Package go1.4
diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go
index ec95a97..a851285 100644
--- a/src/net/http/cgi/host.go
+++ b/src/net/http/cgi/host.go
@@ -139,6 +139,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 8c16e68..84b62ba 100644
--- a/src/net/http/cgi/host_test.go
+++ b/src/net/http/cgi/host_test.go
@@ -90,6 +90,9 @@ func check(t *testing.T) {
// TODO: make the child process be Go, not Perl.
t.Skip("Skipping test: test.cgi failed.")
}
+ for _, check := range checks {
+ check(m)
+ }
}
func TestCGIBasicGet(t *testing.T) {
@@ -197,6 +200,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{
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 782f7cd..424dd8c 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -140,6 +140,9 @@ func ProxyFromEnvironment(req *Request) (*url.URL, error) {
}
if proxy == "" {
proxy = httpProxyEnv.Get()
+ if proxy != "" && os.Getenv("REQUEST_METHOD") != "" {
+ return nil, errors.New("net/http: refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")
+ }
}
if proxy == "" {
return nil, nil
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index defa633..760fc8e 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -1705,7 +1705,8 @@ type proxyFromEnvTest struct {
env string // HTTP_PROXY
httpsenv string // HTTPS_PROXY
- noenv string // NO_RPXY
+ noenv string // NO_PROXY
+ reqmeth string // REQUEST_METHOD
want string
wanterr error
@@ -1729,6 +1730,10 @@ func (t proxyFromEnvTest) String() string {
space()
fmt.Fprintf(&buf, "no_proxy=%q", t.noenv)
}
+ if t.reqmeth != "" {
+ space()
+ fmt.Fprintf(&buf, "request_method=%q", t.reqmeth)
+ }
req := "http://example.com"
if t.req != "" {
req = t.req
@@ -1752,6 +1757,12 @@ var proxyFromEnvTests = []proxyFromEnvTest{
{req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"},
{req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"},
+ // Issue 16405: don't use HTTP_PROXY in a CGI environment,
+ // where HTTP_PROXY can be attacker-controlled.
+ {env: "http://10.1.2.3:8080", reqmeth: "POST",
+ want: "<nil>",
+ wanterr: errors.New("net/http: refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")},
+
{want: "<nil>"},
{noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
@@ -1767,6 +1778,7 @@ func TestProxyFromEnvironment(t *testing.T) {
os.Setenv("HTTP_PROXY", tt.env)
os.Setenv("HTTPS_PROXY", tt.httpsenv)
os.Setenv("NO_PROXY", tt.noenv)
+ os.Setenv("REQUEST_METHOD", tt.reqmeth)
ResetCachedEnvironment()
reqURL := tt.req
if reqURL == "" {