From cc353250443ea58d09c9b4823b8f02bf4d1819b4 Mon Sep 17 00:00:00 2001 From: Calvin Leung Huang Date: Fri, 15 Dec 2017 17:08:23 -0500 Subject: [PATCH 1/2] Use cleanhttp.PrintablePathCheckHandler to handle non-printable characters in request path --- http/handler.go | 7 ++- http/handler_test.go | 19 ++++++++ .../hashicorp/go-cleanhttp/handlers.go | 43 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 vendor/github.com/hashicorp/go-cleanhttp/handlers.go diff --git a/http/handler.go b/http/handler.go index e8f7ca9e26b8..00d2994b0538 100644 --- a/http/handler.go +++ b/http/handler.go @@ -10,6 +10,7 @@ import ( "time" "github.com/hashicorp/errwrap" + cleanhttp "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/vault/helper/consts" "github.com/hashicorp/vault/helper/jsonutil" "github.com/hashicorp/vault/helper/parseutil" @@ -90,7 +91,11 @@ func Handler(core *vault.Core) http.Handler { // handler genericWrappedHandler := wrapGenericHandler(corsWrappedHandler) - return genericWrappedHandler + // Wrap the handler with PrintablePathCheckHandler to check for non-printable + // characters in the request path. + printablePathCheckHandler := cleanhttp.PrintablePathCheckHandler(genericWrappedHandler, nil) + + return printablePathCheckHandler } // wrapGenericHandler wraps the handler with an extra layer of handler where diff --git a/http/handler_test.go b/http/handler_test.go index f6e015c98512..c41d15780934 100644 --- a/http/handler_test.go +++ b/http/handler_test.go @@ -378,5 +378,24 @@ func TestHandler_error(t *testing.T) { if w3.Code != 503 { t.Fatalf("expected 503, got %d", w3.Code) } +} + +func TestHandler_nonPrintableChars(t *testing.T) { + core, _, token := vault.TestCoreUnsealed(t) + ln, addr := TestServer(t, core) + defer ln.Close() + + req, err := http.NewRequest("GET", addr+"/v1/sys/mounts\n", nil) + if err != nil { + t.Fatalf("err: %s", err) + } + req.Header.Set(AuthHeaderName, token) + + client := cleanhttp.DefaultClient() + resp, err := client.Do(req) + if err != nil { + t.Fatalf("err: %s", err) + } + testResponseStatus(t, resp, 400) } diff --git a/vendor/github.com/hashicorp/go-cleanhttp/handlers.go b/vendor/github.com/hashicorp/go-cleanhttp/handlers.go new file mode 100644 index 000000000000..e0385b7c83b6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-cleanhttp/handlers.go @@ -0,0 +1,43 @@ +package cleanhttp + +import ( + "net/http" + "strings" + "unicode" +) + +// HandlerInput provides input options to cleanhttp's handlers +type HandlerInput struct { + ErrStatus int +} + +// PrintablePathCheckHandler is a middleware that ensures the request path +// contains only printable runes. +func PrintablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Nil-check on input to make it optional + if input == nil { + input = &HandlerInput{ + ErrStatus: http.StatusBadRequest, + } + } + + // Default to http.StatusBadRequest on error + if input.ErrStatus == 0 { + input.ErrStatus = http.StatusBadRequest + } + + // Check URL path for non-printable characters + idx := strings.IndexFunc(r.URL.Path, func(c rune) bool { + return !unicode.IsPrint(c) + }) + + if idx != -1 { + w.WriteHeader(input.ErrStatus) + return + } + + next.ServeHTTP(w, r) + return + }) +} From f9f6a64e43ec247c34b3dbc463e73a970f3d7024 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 15 Dec 2017 20:19:14 -0500 Subject: [PATCH 2/2] Update go-cleanhttp --- vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go | 1 + vendor/vendor.json | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go index 7d8a57c2807d..8d306bf51343 100644 --- a/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go +++ b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go @@ -26,6 +26,7 @@ func DefaultPooledTransport() *http.Transport { DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, + DualStack: true, }).DialContext, MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, diff --git a/vendor/vendor.json b/vendor/vendor.json index 070e4316b56b..bc24e4b4c340 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -985,10 +985,10 @@ "revisionTime": "2014-10-28T05:47:10Z" }, { - "checksumSHA1": "b8F628srIitj5p7Y130xc9k0QWs=", + "checksumSHA1": "b3Y4wgMvMco62K4DfX0Sdoug4+k=", "path": "github.com/hashicorp/go-cleanhttp", - "revision": "3573b8b52aa7b37b9358d966a898feb387f62437", - "revisionTime": "2017-02-11T01:34:15Z" + "revision": "33f138d01ac027decb9a5bd76ad6e7c7c701b0c4", + "revisionTime": "2017-12-16T01:18:02Z" }, { "checksumSHA1": "AA0aYmdg4pb5gPCUSXg8iPzxLag=",