diff --git a/server/etcdserver/v3_server.go b/server/etcdserver/v3_server.go index 0184b8d18..960a7b11f 100644 --- a/server/etcdserver/v3_server.go +++ b/server/etcdserver/v3_server.go @@ -454,6 +454,13 @@ func (s *EtcdServer) Authenticate(ctx context.Context, r *pb.AuthenticateRequest lg := s.Logger() + // fix https://nvd.nist.gov/vuln/detail/CVE-2021-28235 + defer func() { + if r != nil { + r.Password = "" + } + }() + var resp proto.Message for { checkedRevision, err := s.AuthStore().CheckPassword(r.Name, r.Password) diff --git a/tests/e2e/ctl_v3_auth_security_test.go b/tests/e2e/ctl_v3_auth_security_test.go new file mode 100644 index 000000000..8e0119b32 --- /dev/null +++ b/tests/e2e/ctl_v3_auth_security_test.go @@ -0,0 +1,55 @@ +// Copyright 2023 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !cluster_proxy + +package e2e + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +// TestAuth_CVE_2021_28235 verifies https://nvd.nist.gov/vuln/detail/CVE-2021-28235 +func TestAuth_CVE_2021_28235(t *testing.T) { + testCtl(t, authTest_CVE_2021_28235, withCfg(*newConfigNoTLS()), withLogLevel("debug")) +} + +func authTest_CVE_2021_28235(cx ctlCtx) { + // create root user with root role + rootPass := "changeme123" + err := ctlV3User(cx, []string{"add", "root", "--interactive=false"}, "User root created", []string{rootPass}) + require.NoError(cx.t, err) + err = ctlV3User(cx, []string{"grant-role", "root", "root"}, "Role root is granted to user root", nil) + require.NoError(cx.t, err) + err = ctlV3AuthEnable(cx) + require.NoError(cx.t, err) + + // issue a put request + cx.user, cx.pass = "root", rootPass + err = ctlV3Put(cx, "foo", "bar", "") + require.NoError(cx.t, err) + + // GET /debug/requests + httpEndpoint := cx.epc.procs[0].EndpointsHTTP()[0] + req := cURLReq{endpoint: "/debug/requests?fam=grpc.Recv.etcdserverpb.Auth&b=0&exp=1", timeout: 5} + respData, err := curl(httpEndpoint, "GET", req, clientNonTLS) + require.NoError(cx.t, err) + + if strings.Contains(respData, rootPass) { + cx.t.Errorf("The root password is included in the request.\n %s", respData) + } +} diff --git a/tests/e2e/ctl_v3_test.go b/tests/e2e/ctl_v3_test.go index 4f65caa4c..a7b10d1da 100644 --- a/tests/e2e/ctl_v3_test.go +++ b/tests/e2e/ctl_v3_test.go @@ -229,6 +229,12 @@ func withSnapshotCount(snapshotCount int) ctlOption { } } +func withLogLevel(logLevel string) ctlOption { + return func(cx *ctlCtx) { + cx.cfg.logLevel = logLevel + } +} + func testCtl(t *testing.T, testFunc func(ctlCtx), opts ...ctlOption) { testCtlWithOffline(t, testFunc, nil, opts...) }