Wednesday, 7 August 2013

Preventing fake account creation in mvc

Preventing fake account creation in mvc

We have recently totally rewritten our ASP.NET 2.0 Web Forms website and
it is now an MVC 4.0 website. We are experiencing problems with fake
accounts being created. When I look in my IIS log the IP addresses mostly
originate from China. Our ASP.NET 2.0 Web Forms website never experienced
any fake accounts being created, so I am wondering if I've done anything
wrong to suddenly get so many of these. Below is a cut down version of our
account registration page to illustrate what I am doing...
Controller
<RequireHttps()>
Function Register() As ActionResult
Dim ad As New AccountDetails
Return View("AccountDetails", ad)
End Function
<RequireHttps()>
<ValidateAntiForgeryToken()>
Function Register(model As AccountDetails) As ActionResult
If ModelState.IsValid Then
If Not String.IsNullOrEmpty(model.FormValue1) OrElse Not
String.IsNullOrEmpty(model.FormValue2) Then
' Add Code here to display an error
Else
Dim SerialNo As Integer =
AccountDetailsRepository.InsertRecord(model)
If SerialNo > 0 Then
Dim Roles As String = "Standard"
FormsAuthentication.Initialize()
Dim fat As FormsAuthenticationTicket = New
FormsAuthenticationTicket(1, model.FirstName + " " +
model.Surname, DateTime.Now,
DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),
False, Roles, FormsAuthentication.FormsCookiePath)
Response.Cookies.Add(New
HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(fat)))
Return RedirectToAction("Account")
Else
' Add code here to display an account error
End If
End If
End If
Return View("AccountDetails", model)
End Function
View
@ModelType User.AccountDetails
<div class="Account">
<h1 class="PageTitle">Register</h1>
<div class="AccountDetails">
<p class="PageHeader">Please enter your account details</p>
@Using Html.BeginForm()
@Html.AntiForgeryToken()
@Html.ValidationSummary(True, "Please correct the following
errors:-", New With {.id = "AccountDetailsValidationSummary",
.class = "TopValidationSummary"})
@<div class="AccountDetailsContainer">
@Html.TextBoxFor(Function(model) model.FormValue1, New
With {.id = "FormValue1"})
@Html.HiddenFor(Function(model) model.FormValue2, New With
{.id = "FormValue2"})
<fieldset id="NameGroup" class="FieldGroup">
<legend>Name</legend>
<div class="FieldRow">
<label for="FirstName" class="FieldLabel">First
Name</label>
@Html.TextBoxFor(Function(model) model.FirstName,
New With {.autocomplete = "off", .class = "Field",
.id = "FirstName", .MaxLength = 25})
@Html.ValidationMessageFor(Function(model)
model.FirstName)
</div>
<div class="FieldRow">
<label for="Surname"
class="FieldLabel">Surname</label>
@Html.TextBoxFor(Function(model) model.Surname,
New With {.autocomplete = "off", .class = "Field",
.id = "Surname", .MaxLength = 25})
@Html.ValidationMessageFor(Function(model)
model.Surname)
</div>
</fieldset>
<fieldset id="AddressGroup" class="FieldGroup">
<legend>Address</legend>
<div class="FieldRow">
<label for="Address1" class="FieldLabel">Address
1</label>
@Html.TextBoxFor(Function(model) model.Address1,
New With {.autocomplete = "off", .class = "Field",
.id = "Address1", .MaxLength = 50})
@Html.ValidationMessageFor(Function(model)
model.Address1)
</div>
<div class="FieldRow">
<label for="Address2" class="FieldLabel">Address
2</label>
@Html.TextBoxFor(Function(model) model.Address2,
New With {.autocomplete = "off", .class = "Field",
.id = "Address2", .MaxLength = 50})
</div>
<div class="FieldRow">
<label for="Address3" class="FieldLabel">City</label>
@Html.TextBoxFor(Function(model) model.City, New
With {.autocomplete = "off", .class = "Field", .id
= "Address3", .MaxLength = 35})
@Html.ValidationMessageFor(Function(model)
model.City)
</div>
<div class="FieldRow">
<label for="Address4" class="FieldLabel
DropDown">State</label>
@Html.TextBoxFor(Function(model) model.State, New
With {.autocomplete = "off", .class = "Field", .id
= "Address4", .MaxLength = 4})
@Html.ValidationMessageFor(Function(model)
model.State)
</div>
<div id="PostcodeContainer" @(If(Not
Model.International, Html.Raw("style=""display:
block;"""), Html.Raw("style=""display: none;""")))>
<label for="PostCode" class="FieldLabel">Zip
Code</label>
@Html.TextBoxFor(Function(model) model.PostCode,
New With {.autocomplete = "off", .class = "Field",
.id = "PostCode", .MaxLength = 15})
@Html.ValidationMessageFor(Function(model)
model.PostCode)
</div>
</fieldset>
<fieldset id="ContactDetailsGroup" class="FieldGroup">
<legend>Contact Details</legend>
<div class="FieldRow">
<label for="Email" class="FieldLabel">E-mail</label>
@Html.TextBoxFor(Function(model) model.Email, New
With {.autocomplete = "off", .class = "Field", .id
= "Email", .MaxLength = 100})
@Html.ValidationMessageFor(Function(model)
model.Email)
</div>
<div class="FieldRow">
<label for="ConfirmEmail"
class="FieldLabel">Confirm E-mail</label>
@Html.TextBoxFor(Function(model)
model.ConfirmEmail, New With {.autocomplete =
"off", .class = "Field", .id = "ConfirmEmail",
.MaxLength = 100})
@Html.ValidationMessageFor(Function(model)
model.ConfirmEmail)
</div>
<div class="FieldRow">
<label for="TelNo1" class="FieldLabel">Tel No</label>
@Html.TextBoxFor(Function(model) model.TelNo1, New
With {.autocomplete = "off", .class = "Field", .id
= "TelNo1", .MaxLength = 25})
@Html.ValidationMessageFor(Function(model)
model.TelNo1)
</div>
</fieldset>
<fieldset id="PasswordGroup" class="FieldGroup">
<legend>Password</legend>
<div class="FieldRow">
<label class="FieldLabel"
for="WebPassword">Password</label>
@Html.PasswordFor(Function(model)
model.WebPassword, New With {.autocomplete =
"off", .class = "Field", .id = "WebPassword",
.MaxLength = 25})
@Html.ValidationMessageFor(Function(model)
model.WebPassword)
</div>
<div class="FieldRow">
<label class="FieldLabel"
for="ConfirmWebPassword">Confirm Password</label>
@Html.PasswordFor(Function(model)
model.ConfirmWebPassword, New With {.autocomplete
= "off", .class = "Field", .id =
"ConfirmWebPassword", .MaxLength = 25})
@Html.ValidationMessageFor(Function(model)
model.ConfirmWebPassword)
</div>
</fieldset>
</div>
@<div class="ButtonBar">
<input type="submit" name="SubmitValue"
class="SubmitButton" value="Create Account"
id="AccountDetailsSaveDetailsButton" />
</div>
End Using
</div>
</div>
My Layout view contains scripts for jQuery and I use unobtrusive
validation on client-side as well.
As seen above I've tried a few things:- 1. Adding the AntiForgeryToken. 2.
Adding a textbox called FormValue1 which I hide with CSS. 3. Adding a
hidden field called FormValue2.
FormValue1 and FormValue2 I check to see if they've been filled in. As a
user should not be able to see these, if they've been filled in I assume
it is some sort of automatic hack and don't register the account.
I can consider things like reCAPTCHA but I just wanted to try and figure
out if I am doing something wrong, especially as this problem only seems
to have started with our MVC 4.0 website and didn't experience this issue
with ASP.NET 2.0 Web Forms.
Anything I can do to improve this?

No comments:

Post a Comment