satellite/console: Filter special characters out of name

When a user is created, but before verification or forgot password email
is sent, remove any special characters in the provided name. This
protects us against certain phishing attacks.

Change-Id: Ieddd3479da20eb80b9f1b56eb86c8f46bca2642c
This commit is contained in:
Moby von Briesen 2022-01-19 18:45:35 -05:00 committed by Antonio Franco
parent 9f3c1f9cda
commit 59648dc272
2 changed files with 60 additions and 0 deletions

View File

@ -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)

View File

@ -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)
})
}