31

I have a web application and I have implemented a check on the browser to ensure that a user sets only strong passwords. A company that we have called to check security vulnerabilities pointed out that this is not enough because using some hacking a user can ignore the check and set a weak password.

I do not understand how this can be a security vulnerability. Why would someone hack the security check just to set a weak password? Someone expert enough to hack the web application will understand the importance of using a strong password.

The only reason I can think is that someone, very very lazy, can decide to hack the check just to have an easier password to remember. I do not know how likely is this case.

I know that you cannot enforce a strong password on the client side and that if you are required to have a strong password in any circumstance, you have to do it on the server side.

My point is: given that, to have an acceptable user experience, we have to do the check on the client side, there has to be a good reason, a real use case that creates a possible vulnerability to justify a duplication of the check on the server side.

Reading the answers, so far, it seems that the only use case that can create a vulnerability is when the javascript does not work. This does not seem a problem for me because the submit button is disabled by default.

blahdiblah
  • 113
  • 3
Marco Altieri
  • 633
  • 5
  • 13
  • 11
    You can always ask these companies for clarification. Ask them for an attack scenario. I'm guessing it's a mistake from their side. – Silver Apr 27 '17 at 07:51
  • 10
    If you have the same requirements on both front and back end then there is no confusion to your users and no confusion to your system. – Luke Brown Apr 27 '17 at 14:16
  • 2
    I think that it is not a duplicate of the other question because it is asking something more specific. I knew already the answers given in that question. I I knew that you cannot enforce a password strength on the client side, but I wanted to know in what circumstances this can be a security vulnerability. – Marco Altieri Apr 27 '17 at 17:23
  • One consideration that might help you is if it's possible to run the same code client-side as server-side, or to use a framework where you create the validation specification once in one language, and it's emitted to the client via a tested and trusted transformation. For example, the client side JavaScript to do the strength check could be run using Node on the server side. Then you reduce your coding burden and ensure the implementations are identical to avoid weird problems like users getting errors they don't know how to fix. Finally, make sure you test your javascript! – ErikE Apr 27 '17 at 17:51
  • 5
    "Why isn't a client-side password check considered secure?" -> "Why isn't a client-side password **strength** check considered secure?" – ErikE Apr 27 '17 at 20:59
  • Be very careful with adding "strong" password checks. The least secure passwords I use are the ones where I had to hand mangle the password to get past a series of rules. The most secure are the ones where I told a password generator "20 characters: any mix of letters, numbers, and special characters" and used the result directly. – Patricia Shanahan Apr 27 '17 at 21:40
  • 1
    Part of the answer depends on what you *do* with a weak password. Do you reject it? Do you warn the user and let them set it anyway? – jpmc26 Apr 28 '17 at 03:08

8 Answers8

64

You’re assuming that the check is bypassed on purpose. It could be the case that someone is using a browser which fails to handle the script properly or with scripts disabled, possibly even without knowing this.

You seem to have a reason for people to use strong passwords. If you do so, why accept that people can bypass it?

Client-side validation can be helpful from a usability perspective, but if you decide that a minimum password strength is required, you should enforce it by implementing it server-side.

TRiG
  • 610
  • 5
  • 14
Teun Vink
  • 6,898
  • 2
  • 29
  • 35
  • 9
    Exactly. If it's used more as a guideline, but is not strictly needed, doing it on the client is fine. For my website I "require" users to have a password longer than 5 characters, which must not all be numbers (date of birth...). But if the check isn't executed for some reason, the server is perfectly fine accepting it. Unless you handle sensitive data, this should be just fine. – Stephan Bijzitter Apr 27 '17 at 11:14
  • OK. In my case if the javascript does not work, the submit button will not be enabled. – Marco Altieri Apr 27 '17 at 11:33
  • 9
    @MarcoAltieri it is trivial to block your scripts but still use javascript to enable the submit button. Someone could also manually post to your form's target. – 0xFF Apr 27 '17 at 13:06
  • 5
    @MarcoAltieri, a rule of thumb I use is to assume that a sufficiently malicious/incompetent user is just not using a browser at all, and all they will ever do is send HTTP requests straight to my backend regardless of what I attempt to tell them to do. – ymbirtt Apr 27 '17 at 13:29
  • 2
    To indicate just how trivial @fhl's suggestion is -- *I've done it, and I don't write js, or code for the web in any ther way*. I've used selective commenting of js in a browser (a broken validation that would never pass) and I've written a python script to submit a form with no browser (for my convenience -- a tedious wifi portal screen). – Chris H Apr 27 '17 at 13:54
  • 4
    @fhl The question is: why would someone do it ? Just to set a weak password? It would be easier for this person to write a strong password and then write it down on a post-it, as someone as already pointed out. – Marco Altieri Apr 27 '17 at 18:14
  • 2
    The issue is bigger than just setting a weak password. The real problem is that client-side validation should be assumed to not be done. Surely you've heard of SQL injection? What if they set an empty password? What if it's so long it overflows your database, allowing code injection? What if you only expect ascii and they send some messy unicode? – 0xFF Apr 27 '17 at 18:20
  • @ftl Of course there are checks for other security vulnerabilities in my application and they are server side. Pentesters have not found other issues, only the check for strong passwords. – Marco Altieri Apr 28 '17 at 01:40
  • @MarcoAltieri I could bypass this check either because it is too difficult to create a password that fits the strong password criteria, or because I want a simple password so that I can log in faster, or because I want to use the same password everywhere. –  Apr 28 '17 at 06:41
  • @MarcoAltieri I agree that isn't wrong to let users bypass your passphrase complexity checks in principle (because `My way too long to be realistically bruteforced example passphrase which is totally more secure than 123456` fails almost every naive passphrase complexity validation check I've ever seen, and yet is way better than `abc123!@#` which passes almost every passphrase complexity check I've seen). But, for your specific site, what matters more: enabling careful informed circumvention, or guiding the ignorant or negligent whose browser doesn't do the validation as intended? – mtraceur Apr 28 '17 at 07:44
  • @mtraceur it is impossible that the password is posted if the JavaScript is not enabled or is not working. – Marco Altieri Apr 29 '17 at 07:37
  • @MarcoAltieri I'm not sure I understand. I presume you mean your web page is implemented in a way that uses JavaScript for the password posting, and has no graceful degradation to a plain HTML form submission through an HTTP POST? Even if so, are all JavaScript interpreters now and in the future guaranteed to work correctly? Not a security thing at that point, but if hypothetical future Firefox version 99 or whatever breaks on some peculiar corner-case such that your validation misses one of your passphrase criteria but otherwise works fine, do you want your server to help spot the error? – mtraceur May 01 '17 at 01:45
13

The rule when writing a server application is simply never trust what comes from client. Checks done client side are great as they allow a nice user experience with nice popups and immediate display. But as anything can happen, from a disabled javascript browser to a user using a scripting language to simulate a browser, all checks must be done (again) server side.

If strong passwords are just recommended, do what you want, if they are a requirement, you must implement a check server side.

BTW: you as the dev can propose solutions, but the client does express requirements. If you do not agree with them you can ask for clarification and propose other ways, but in the end the client will decide.

Serge Ballesta
  • 25,952
  • 4
  • 42
  • 84
12

If the user MUST set a strong password, checking the password strength only on the client side is a vulnerability.

Example

If you work in a big company and you have to change your password every 2 or 3 months a few people will start bypassing the client-side check of password strength to use shorter or better to memorize passwords. If these passwords are used to derive cryptographic keys, e.g. for multi-user encryption of files, it becomes horrible...

Solution

Always check the password strength at the server and optionally check the password strength at the client to decrease requests to the server.

Recommended library: ZXCVBN

  • Uses pattern matching and checks for most used passwords to estimate password strength.
  • Is available in multiple programing languages
nebulak
  • 390
  • 1
  • 9
  • Are you saying that there will be users who will really take the time to hack the check just to set a weak password ? It seems so unlikely to me. By the way, I like the library you linked! – Marco Altieri Apr 27 '17 at 08:25
  • I do not know how critical this vulnerability is for your application. But checking the password strength at the server is best practice and it shouldn't be too much work to implement. – nebulak Apr 27 '17 at 08:35
  • 7
    My two cents: checking the password strength on the client is a UX feature, not a security feature. Never trust the client, therefore the same check has to be done on the server regardless – Alex Apr 27 '17 at 08:47
  • 3
    Never validate anything on the client! Never! You can **additionally** check input on the client for increased usability, but you always have to validate it on the server. The client belongs to the user, so client only validation is equal to no validation but just telling the users they have to use a strong password. Wonder how well that would work? – Josef Apr 27 '17 at 08:47
  • @MarcoAltieri the whole "you must set a new pasword that you've got little chance of remembering" thing could be designed to make your users look for workarounds. Or post-its. Particularly if *their perception* is that it's uneccesary hassle. – Chris H Apr 27 '17 at 14:01
  • @MarcoAltieri some expert users might indeed spend their time to circumvent checks they deem unecessary. I've a whole bunch of client-side scripts (bookmarklets) which help me navigate pages more easily, or fill in login forms for customer demos. – Zefiro Apr 28 '17 at 00:08
  • @Zefiro but because you are an expert, you will not use these scripts to set a weak password on a real account. – Marco Altieri Apr 28 '17 at 05:23
  • @MarcoAltieri I will. I have one "standard" password which is very weak I use on all accounts which have no real worth to me. (You have to register to view this image and the like). If your account falls in this category and it is possible to ignore your check to use this password, I will do it! Also, it is great fun. – Josef Apr 28 '17 at 08:37
  • I could, and I might want to, perhaps just for the fun of showing what I think of stupid rules for accounts which I do not value highly, and I want to use my password "dragon" everywhere. So the decision for you is: encourage good passwords, or ENFORCE them? If the latter you have no choice but a second check on the server. – Zefiro Apr 28 '17 at 12:38
10

Building on Teun Vink's answer, there are a few real world scenarios where a user may accidentally bypass the security check.

Let's say a user downloads an adblocker like Adblock Plus or uBlock Origin. Then, due to the scripts being misconfigured, one of these adblockers accidentally blocks the script you were using to verify password security. Now the user can enter 1234 as a password without any server-side checks in place to prevent it.

Or alternatively, maybe local caching gave the user an older version of your script. Maybe they've saved your webpage as a static HTML file on their desktop. Maybe the user's PC has a virus that altered the content of your script. As the common saying goes...

Never trust the user.

Edit: See also "Cannot save profile when maps.googleapis.com is blocked" for a great example of why you should never trust the user.

Stevoisiak
  • 1,535
  • 1
  • 12
  • 27
  • If the javascript is blocked, the submit button won't be enabled because it is disabled by default. – Marco Altieri Apr 27 '17 at 17:30
  • 4
    @MarcoAltieri Adblock doesn't work by blocking JavaScript in its entirety. It works by blocking ***specific*** scripts as defined by the user. – Stevoisiak Apr 27 '17 at 17:36
  • It seems unlikely that the adblock will be able to selectively execute parts of my script ending up enabling the button even if the check has not been executed. It is all in the same script. – Marco Altieri Apr 27 '17 at 17:43
  • 3
    @MarcoAltieri I agree. The scenario I've described is very unlikely. In fact, ***unlikely*** is the key word here. When considering security, if there's a chance of something happening, even if it's extremely unlikely, you typically want to make sure your system is prepared if it happens. – Stevoisiak Apr 27 '17 at 17:47
  • But isn't using google resources in your page bad practice anyway? – wannabeLearner Apr 28 '17 at 09:10
  • @wannabeLearner - Not if you use [subresource integrity](https://en.wikipedia.org/wiki/Subresource_Integrity) – paj28 Apr 28 '17 at 09:33
  • @paj28 yes that would make it safe. But if there is a block in place in your country against google owned services wouldn't that kinda wreck things still? – wannabeLearner Apr 28 '17 at 09:40
  • @wannabeLearner - I'd expect Google hosted libraries are treated differently than Google services, but I'm not sure. You could ask a new question about this – paj28 Apr 28 '17 at 10:02
  • 1
    @paj28 they are. Even SE is a pain to use in countries like china (referring to a past experience i had maybe SE fixed this already) – wannabeLearner Apr 28 '17 at 10:35
  • I meant they are *not* treated just the same – wannabeLearner Apr 28 '17 at 11:04
2

You mention that both the check & the enabling of the submit button are one script, so it's safe even if some scripts are loaded and others aren't. How sure are you that those two functions will always be in the same script?

I suppose what I'm saying is that it sounds like, as things stand right now, it would mean someone intentionally doing something they know is a bad idea in order for them to get a bad password, and you're ok with that; you're trying to prevent accidents, not intentional stupidity.

The thing that worries me is that if this script ever gets refactored & split up, or intentional stupidity becomes your problem, or some attacker writes a client side script ostensibly to help people,... then you're in trouble.

user3742898
  • 121
  • 1
2

One possible problem is that it only takes one wise guy (that might be knowledgeable enough to use that technique to use a password that fails the checker and is nevertheless secure!) to find a way to hack it - and distribute the hack to a few other people (that s/he probably deems responsible enough) that will eventually give it to people against whose lack of security competence the solution was supposed to guard.

rackandboneman
  • 975
  • 4
  • 9
1

Enforce rules on the server

Whatever rules you set up, they must be enforced at the server level in every case. This is true for password setting, and for mandatory fields in forms for example (e.g. if a phone number is required when signing up, it should be checked in the server).

Help your user on the client

Whatever rules you enforce on the server, you should help your user as much as possible by giving help on the client.

It can be just explanation, stars next to mandatory fields, showing errors before you submit forms, ...

But enforce rules on the server

But in any cases, you cannot rely on the client at all. Some people will block JS. Some people will block flash. At some point you may open your API to third parties, which may or may not enforce your rules for you.

I, for one, have at times re-activated JS-blocked buttons because I found that client-enforced rules were ridiculous (e.g. your password must be exactly 8 characters, including exactly 1 capital letter, 1 number, and 1 special character in (!@#$%&*?) only), hoping that the server was not enforcing those rules (which often it didn't).

If your specifications are to have a precise set of rules on your users' password, then having the validation client-side does not meet the specifications.

njzk2
  • 332
  • 2
  • 9
1

I expect the pen test firm are applying a general principle here "do all validation server-side" without considering the specific case in much detail.

In your scenario, where JavaScript cannot be disabled, I see no practical security risk. There may be a non-technical risk if you need complex passwords for a regulatory requirement (e.g. PCI-DSS).

paj28
  • 32,906
  • 8
  • 93
  • 130