asp.net mvc 4 - When does WebSecurity.ChangePassword fail when "new password is invalid"? -
this code changing password in default accountcontroller scaffolded in mvc 4:
// changepassword throw exception rather //than return false in failure scenarios. bool changepasswordsucceeded; try { string username = user.identity.name; changepasswordsucceeded = websecurity.changepassword(username, model.oldpassword, model.newpassword); } catch (exception) { changepasswordsucceeded = false; } if (changepasswordsucceeded) { return redirecttoaction("manage", new { message = managemessageid.changepasswordsuccess }); } else { modelstate.addmodelerror("", "the current password incorrect or new password invalid."); }
my issue message unclear. if current password incorrect that's fine if new password invalid i'd present better message user telling them what's wrong , i'd understand "failure scenarios" better can tailor message.
the documentation here specific exceptions , don't think these should swallowed in action , reported invalid passwords.
so why "new password invalid" possibility here? can remove if i'm using simplemembershipprovider without oauth in application?
edit: nb data annotation appears in "registermodel" class there password validity check here too
[stringlength(100, errormessage = "the {0} must @ least {2} characters long.", minimumlength = 6)]
summary
this long answer, have edited sections. not security expert compared user rook, , says not trust security answers, or else's. test , understand yourself, always. web developers reading should read the owasp top ten web security flaws, use online guidance such trustworthy computing and, of course, mr. bruce schneier. security complicated , big 1 of us, use frameworks work according best practice when can. above all, keep in perspective.
see below more detail on these summary answers:
- the message user is deliberately ambiguous, can argued security reasons (see below)
- ref. "failure scenarios", due invalid input should caught model validation, incorrect current password, or edge case exceptions
- the exceptions swallowed , presented 1 either because original developer lazy, or because believed there should single return message cases (see 1 above)
- "new password invalid" not possibility code you've highlighted as long attributes match, or more restrictive length restrictions within changepassword. but, see (1) above.
- can remove it? see (1) above.
- good point, see below discussion.
original answer - conceptual attack vector
think security perspective:
- i wander mobile/tablet/laptop sitting on bar/coffee shop table (or desktop computer in home/office)
- i think might know password
- i go "change password" , type in think password not
- i deliberately put 1 character new password in
the machine tells me
"current password incorrect"
now put in try again think current password is:
"new password invalid"
i know password, don't know haven't changed anything.
footnote: got first set of logic wrong, deleted it, edited , reposted, hey - i'm not bruce
a similar attack
there many combinations of attack, it's email harvesting bad login system. think happens if 2 different messages when try "recover password" using email address:
- an email has been sent address (for email in database)
- your email not found (for fake email address)
then can find out valid member emails site targeted phishing attack on user, or build list of valid email addresses spam.
a possible solution
a more user friendly, equally secure error message our password change in both cases be:
"the current password incorrect or new password invalid. remember password case sensitive, , new passwords must have [64 letters/5 numbers/4 characters/3 names of greek gods]"
to stay sane, keep in context of application use, remember have responsibility in bigger eco-system, , users share passwords between websites, whether or not.
when changepassword return false?
regarding question part when changepassword returns false:
essentially websecurity.changepassword
:
in summary, returns false
if:
- any of arguments fail null, empty or length checks; or
- the database connection fails; or
- the
userid
no longer exists in database; or - the current password incorrect; or
- (and will, obviously, set
changepasswordsucceeded = false
if other exception happens). - there no
newpassword
validity check within callchangepassword
so in theory, if have validation attributes in place correctly, , ignoring edge cases, can return false
if have edge case (the user has been deleted, between , post, or can't hit database, or current password invalid).
this holds true in case attackers bypass ui in browser (which will) action calls isvalid
on model.
the client side message
there serious disclaimer here: don't spend life working on security. follow secure-by-design principles (i keep the owasp top ten project, instance) , believe have awareness of important security principles. may therefore have got of logic wrong.
if client side "password requirements" validation not there - happens? user has wait post return find out happened.
if client side "password requirements" validation is there, weaken our interface? don't believe so.:
- the server still performs both requirements , current password validation
- the server not distinguish between 2 failure scenarios (actually does, see below)
- therefore server going tell if current password valid when is, , when password therefore changes.
- hopefully site also:
- prevents changing old password
- sends email notification password has been changed (maybe wait 15 minutes in order prevent attacker deleting email left open when left phone lying around unlocked in bar our website opened in it, , our email open well)
mvc doesn't, afaik, either of these things, starts fall apart.
it falls apart because return different error , message server due model.isvalid
test inside action, enforces new password validation , different error message failure. therefore, in current implementation, single error message approach is flawed.
summary
so change way done? in hope improve other parts in time, wouldn't, other changing return message bit longer , more informative.
this personal opinion, argued other way
the detail:
- calls
membership.getuser(username, true).changepassword(...)
. in case of argumentexception see docs returnfalse
. - it calls
changepassword
on actual provider (e.g.simplemembershipprovider.changepassword
), , returnfalse
if fails.
the actual provider implementation gets complex. simplemembershipprovider
, example,
- it might pass call "previous provider" if hasn't been initialised yet.
- otherwise might throw
argumentexceptions
(bubblingcatch
,return false
inmembershipuser.changepassword
) if password/username empty, null, long etc. - if doesn't happen
- try ,
userid
database (returns false if fails), - checks current password correct (returns false if fails),
- and updates password update query, setting
passwordchangeddate
while goes
- try ,
- it updates internal data on
membershipuser
Comments
Post a Comment