From c5391f8259339ebcc4536f093aea8b610067bb93 Mon Sep 17 00:00:00 2001 From: Daniel Mellado Date: Wed, 14 Dec 2022 16:51:18 +0100 Subject: [PATCH] CVE: Fix Receiver malicious tenant If running as root or with enough privileges, receiver can create a directory outside of the configured TenantHeader. This commit fixes it up by sanitizing the user input and explicity not allowing such behavior. Signed-off-by: Daniel Mellado --- pkg/receive/handler.go | 14 ++++++++++++++ pkg/receive/handler_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/pkg/receive/handler.go b/pkg/receive/handler.go index 771b85cce88..91026b7a0d4 100644 --- a/pkg/receive/handler.go +++ b/pkg/receive/handler.go @@ -12,6 +12,7 @@ import ( stdlog "log" "net" "net/http" + "path" "sort" "strconv" "sync" @@ -403,6 +404,13 @@ func (h *Handler) handleRequest(ctx context.Context, rep uint64, tenant string, return h.forward(ctx, tenant, r, wreq) } +func (h *Handler) isTenantValid(tenant string) error { + if tenant != path.Base(tenant) { + return errors.New("Tenant name not valid") + } + return nil +} + func (h *Handler) receiveHTTP(w http.ResponseWriter, r *http.Request) { var err error span, ctx := tracing.StartSpan(r.Context(), "receive_http") @@ -422,6 +430,12 @@ func (h *Handler) receiveHTTP(w http.ResponseWriter, r *http.Request) { } } + err = h.isTenantValid(tenant) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + tLogger := log.With(h.logger, "tenant", tenant) writeGate := h.Limiter.WriteGate() diff --git a/pkg/receive/handler_test.go b/pkg/receive/handler_test.go index d363f0deb75..355361abeb6 100644 --- a/pkg/receive/handler_test.go +++ b/pkg/receive/handler_test.go @@ -1090,6 +1090,36 @@ func Heap(dir string) (err error) { return pprof.WriteHeapProfile(f) } +func TestIsTenantValid(t *testing.T) { + for _, tcase := range []struct { + name string + tenant string + + expectedErr error + }{ + { + name: "test malicious tenant", + tenant: "/etc/foo", + expectedErr: errors.New("Tenant name not valid"), + }, + { + name: "test valid tenant", + tenant: "foo", + }, + } { + t.Run(tcase.name, func(t *testing.T) { + h := NewHandler(nil, &Options{}) + err := h.isTenantValid(tcase.tenant) + if tcase.expectedErr != nil { + testutil.NotOk(t, err) + testutil.Equals(t, tcase.expectedErr, err) + return + } + testutil.Ok(t, err) + }) + } +} + func TestRelabel(t *testing.T) { for _, tcase := range []struct { name string