diff --git a/satellite/console/consoleweb/consoleapi/auth.go b/satellite/console/consoleweb/consoleapi/auth.go index 4f1ccdda9..db889f6db 100644 --- a/satellite/console/consoleweb/consoleapi/auth.go +++ b/satellite/console/consoleweb/consoleapi/auth.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "net/http" + "regexp" "time" "github.com/gorilla/mux" @@ -119,6 +120,12 @@ func (a *Auth) Logout(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") } +// removeSpecialCharacters removes any non alphanumeric or space/dash/underscore characters from a string. +func removeSpecialCharacters(s string) string { + re := regexp.MustCompile(`[^a-zA-Z0-9 \-\_]`) + return re.ReplaceAllString(s, "") +} + // Register creates new user, sends activation e-mail. // If a user with the given e-mail address already exists, a password reset e-mail is sent instead. func (a *Auth) Register(w http.ResponseWriter, r *http.Request) { @@ -174,6 +181,10 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) { return } + // remove special characters from submitted name so that malicious link cannot be injected into verification or password reset emails. + registerData.FullName = removeSpecialCharacters(registerData.FullName) + registerData.ShortName = removeSpecialCharacters(registerData.ShortName) + verified, unverified, err := a.service.GetUserByEmailWithUnverified(ctx, registerData.Email) if err != nil && !console.ErrEmailNotFound.Has(err) { a.serveJSONError(w, err) diff --git a/satellite/console/consoleweb/consoleapi/auth_test.go b/satellite/console/consoleweb/consoleapi/auth_test.go index 02e878319..e999eec7c 100644 --- a/satellite/console/consoleweb/consoleapi/auth_test.go +++ b/satellite/console/consoleweb/consoleapi/auth_test.go @@ -691,3 +691,52 @@ func TestResendActivationEmail(t *testing.T) { require.Contains(t, body, "/activation") }) } + +func TestAuth_Register_NameSpecialChars(t *testing.T) { + testplanet.Run(t, testplanet.Config{ + SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 0, + }, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) { + inputName := "The website has been changed to https://evil.com/login.html - Enter Login_Details," + filteredName := "The website has been changed to httpsevilcomloginhtml - Enter Login_Details" + + registerData := struct { + FullName string `json:"fullName"` + ShortName string `json:"shortName"` + Email string `json:"email"` + Password string `json:"password"` + }{ + FullName: inputName, + ShortName: inputName, + Email: "user@mail.test", + Password: "abc123", + } + + jsonBody, err := json.Marshal(registerData) + require.NoError(t, err) + + url := planet.Satellites[0].ConsoleURL() + "/api/v0/auth/register" + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonBody)) + require.NoError(t, err) + req.Header.Set("Content-Type", "application/json") + result, err := http.DefaultClient.Do(req) + require.NoError(t, err) + require.Equal(t, http.StatusOK, result.StatusCode) + + defer func() { + err = result.Body.Close() + require.NoError(t, err) + }() + + body, err := ioutil.ReadAll(result.Body) + require.NoError(t, err) + + var userID uuid.UUID + err = json.Unmarshal(body, &userID) + require.NoError(t, err) + + user, err := planet.Satellites[0].API.Console.Service.GetUser(ctx, userID) + require.NoError(t, err) + require.Equal(t, filteredName, user.FullName) + require.Equal(t, filteredName, user.ShortName) + }) +}