

Mozilla's secure coding guidelines for web developers - girishmony
https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines

======
pornel

        Invalid login attempts (for any reason) should return the generic error message:
        The username or password you entered is not valid
    

In practice, on any non-trivial website, it doesn't make a difference for
security.

Registration form will show a specific error when you try to register username
that is already taken. Password reminder form will show error when you request
reminder for an unknown e-mail. Some websites even have AJAX APIs for checking
validity of usernames/emails!

Because of that it's _easy for an attacker_ to check whether username or
password is invalid. Vague error messages make it _only hard for the user_.

~~~
Joakal
Why not emphasise user privacy more by hiding emails. eg "An email should be
sent to the address above. For user privacy, we cannot confirm if it exists."

I wonder how many emails scrapers have done of Forgotten Email pages.

~~~
T-hawk
This could work, but there's still vulnerabilities. How about a timing attack?
The page with that message probably responds faster if the email address
doesn't exist. (Sure, a timing attack can be fixed if you can make the page
run in constant time; but is it really cost-effective to spend time developing
that rather than actual features?)

~~~
Joakal
1) Validate email address. 5-10ms

2) Send a non-blocking request with a flag, eg "Good" "Bad".

3) Return message to user that email has been sent but can not confirm if the
email is true for privacy reasons.

While yes, it can be down to a timing attack, the trouble is that this vector
can be used against sessions, logins, etc. It can be a standard that Mozilla
should adopt.

------
georgefox
This is a great resource, but some of the input validation stuff doesn't sit
well with me, for example:

> _Examples of Good Input Validation Approaches... Firstname: Letters, single
> apostrophe, 1 to 30 characters_

First, I'm not sure if I should interpret _letters_ as [A-Za-z] or something
more inclusive of non-Latin characters. But anyway, why restrict this so much?
What about spaces, as in _Mary Ellen_ ; dots, as in _P.J._? Heck, why can't I
use a hyphen or a number? Just because you might not try to name your kid
Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb11116 doesn't mean nobody else will
([http://en.wikipedia.org/wiki/Naming_law_in_Sweden#Protest_na...](http://en.wikipedia.org/wiki/Naming_law_in_Sweden#Protest_names)).

Perhaps I'm not seeing the forest for the trees here, but when it comes to
restricting input, it always seems there's a risk of "We can not accept that
last name" behavior
([http://www.cooper.com/journal/2009/09/we_cannot_accept_that....](http://www.cooper.com/journal/2009/09/we_cannot_accept_that.html)).
If you're properly sanitizing/escaping on the way out, why be so harsh on the
way in?

------
nbpoole
One interesting/cool suggestion that I think is worth noting specifically: the
use of HMAC+bcrypt instead of just bcrypt for secure password storage.

[https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines#...](https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines#Password_Storage)

 _\- The nonce for the hmac value is designed to be stored on the file system
and not in the databases storing the password hashes. In the event of a
compromise of hash values due to SQL injection, the nonce will still be an
unknown value since it would not be compromised from the file system. This
significantly increases the complexity of brute forcing the compromised hashes
considering both bcrypt and a large unknown nonce value_

 _\- The hmac operation is simply used as a secondary defense in the event
there is a design weakness with bcrypt that could leak information about the
password or aid an attacker_

~~~
sporksmith
I thought this was interesting as well. The second bullet is a bit misleading
though. The benefit is not just in case there is a design weakness in bcrypt.
The real benefit is briefly summarized in the first bullet: It's effectively
forcing the attacker to compromise not only the database but also the file
system to be able to make _any_ offline password guesses.

With bcrypt alone, compromise of the password hashes still allows brute-force
offline dictionary attacks. bcrypt means that each guess might take, e.g.,
milliseconds instead of microseconds, but an attacker has all of the
information he needs to make offline guesses and check them against the
compromised hash.

The hmac step means that an attacker who has the password hashes but not the
hmac nonce effectively doesn't get _any_ offline guesses. Assuming the nonce
is e.g., 128+ bits, it'll be computationally infeasible for the attacker to
guess the nonce itself, without which he can't verify _any_ offline password
guesses.

------
yahelc
Ironically, immediately after reading these guidelines, I checked my email and
had just received an email from Mozilla's mailing list service that contained
my password in plaintext. Oops. (To be fair, it looks like they're just using
Mailman <http://www.list.org/>)

------
shabda
Whats the point of this?

> Email verification links should not provide the user with an authenticated
> session.

It always bugs me. The "forgot password" links only allows me to choose a new
password, but does not log me, adding a extra step.

~~~
rickmb
The point is obvious: it would give anyone who intercepts the (plain text)
email full access.

However, the price for not doing this is pretty high in terms of conversion,
so as far as I'm concerned it's not a black and white issue.

If there's nothing particularly sensitive to be compromised (and that usually
isn't the case at this stage), simple measures like rapidly expiring the
verification URL and allowing it to be used only once is "good enough" for
most sites.

There are no absolutes in security.

~~~
kijin
If the link allows you to pick a new password without knowing your current
password, anyone who intercepts the email with the link would also get full
access using the new password.

------
Estragon

      Ensure that a robust escaping routine is in place to prevent the user
      from adding additional characters that can be executed by the OS (
      e.g. user appends | to the malicious data and then executes another OS
      command). Remember to use a positive approach when constructing
      escaping routinges.
    

Surprises me that they regard sending client content to the OS at all. What is
wrong with parametrized execution using using functions like os.spawn*, which
place arguments straight into the called function's argv list?

~~~
zobzu
theres more than just python you know. you have to take care of this
regardless of the engine behind.

beside, even parametrized, you have to be careful. I'll remind you of the 2004
Safari handler exploit. Apple fixed the first exploit by using parametrized
argument list. Woot. Next day, exploited again because some programs call
execve on their argument list, for example ssh -o'ProxyCommand=exploit here'
which is 2 arguments (-o and the complete proxycommand line including the
exploit line).

This is valid for websites as well.

------
darrikmazey
Ensure the "tweet this" or "like this" button does not generate a request to
the 3rd party site simply by loading the Mozilla webpage the button is on
(e.g. no requests to third party site without user's intent via clicking on
the button).

Thank you for this.

~~~
zobzu
I'm not sure you can do this without voiding the agreement with
twitter/facebook unfortunately.

I'd suggest the use of Ghostery (works on all major browsers) on the client
side, and on the server site, well, you know, not use any like button :>

~~~
skymt
Heise Online worked out a solution[0]: a two-click Like button. The first
click replaces a placeholder with the official Facebook Like button. Facebook
objected at first, but only because Heise tried to make their placeholder look
official. A quick design change allowed them to keep it.

[0]: <http://news.ycombinator.com/item?id=2957119>

~~~
zobzu
Yeah that's why I'm not sure. It could be attacked depending on the country I
guess, and if you don't use a facebook-like icon, its hard to tell what you're
going to like. Debatable I guess

------
jtchang
A lot of people want to get into web development. One thing they have to
understand as that while the barrier to entry is low there are a ton of
nuances that separate a mediocre web developer from a great one.

These guidelines are a good example of what web developers have to deal with
on a daily basis. Certainly not trivial.

~~~
janto
I see myself as quite competent, but I still wouldn't trust myself to catch
all the nuances. And even if I could it would be too much work for every new
project.

I think this is a good argument for the existence of a suite/library that
manages things like password storage, recovery, validation, etc. Integrating
everything from using good salts and hashes to captchas and retry delays.

------
qjz
_Passwords must be 8 characters or greater_

Half of the top 50 cracked Gawker passwords were 8 characters (and longer
passwords were not exposed, due to the nature of the vulnerability). Since 8
character passwords are vulnerable to a known common weakness (in DES), this
should be revised to:

 _Passwords must be 9 characters or greater_

This will prevent your users from using passwords that are vulnerable to the
DES attack if they reuse them on other sites.

~~~
nbpoole
Lets think about that for a minute. DES truncates at 8 characters, so you're
right that if a database with DES-encrypted passwords leaks and is brute
forced an attacker will only get the first 8 characters of a password.

But what if my password is the word "biological"? By knowing the first 8
characters, the attacker has drastically reduced the number of guesses that
need to be made (assuming a priori knowledge that the password is shared
between sites).

Also consider MD5(PASSWORD) and SHA1(PASSWORD). Those are both fairly common
constructions for "secure password hashing" [note: they're not really secure]
in web applications and both of those would yield up the entire plaintext
password if an attacker used a brute-force or rainbow table attack.

If you're designing a secure web application, you can't make your goal to
secure all the other websites on the Internet. Bumping the minimum number of
characters to 9 wouldn't significantly impact the security of your users. If
you're really worried about a situation where a user's password is disclosed,
you should consider offering two-factor authentication options for your users.

~~~
qjz
All good points, but allowing 8 characters still allows '12345678' and
'password', two of the most egregious examples of weak passwords. Granted,
weak passwords will always scale to the next minimum ('123456789' or
'passwords' for 9 characters), but 8 character passwords are already among the
lowest hanging fruit, so including them in the minimum is misguided.

~~~
nbpoole
Don't forgot 'password1' ;-)

And the guidelines specifically say " _Blacklisted passwords should be
implemented (contact infrasec for the list)_ " which indicates to me that
known common passwords like '12345678' and 'password' will be disallowed
(although we don't have access to the list).

My opinion (and we may have to agree to disagree on this point) is that adding
one character to the minimum is not going to make a significant difference in
application security. I don't believe it mitigates the danger of a leak of
DES-encrypted passwords. If you're concerned about a scenario where a user's
shared password on another site is compromised, your application can use two-
factor authentication or mandate the use of strong pass-phrases instead of
traditional passwords.

------
mgkimsal
OT but scary: [http://michaelkimsal.com/blog/wp-
content/uploads/2011/06/Scr...](http://michaelkimsal.com/blog/wp-
content/uploads/2011/06/Screen-shot-2011-04-06-at-6.34.33-PM.png)

This is a financial institution.

------
rohit89
I have a question about the password policy.

    
    
        All sites should have the following base password policy:
    
        Passwords must be 8 characters or greater
        Passwords must require letters and numbers
        Blacklisted passwords should be implemented (contact     infrasec for the list)
    

Is it responsibility of the website to make sure that the passwords are strong
for the general user ? Isn't it the user's responsibility to create a good
password ? I would think that the site should let the user know about best
practices but ultimately it should be up to the user whether to follow it or
not.

~~~
gcv
Enforcing password strength makes sense for a site which stores sensitive
data. That said, some simple math suggests that length, not character
complexity, should be required.

[http://security.stackexchange.com/questions/6095/xkcd-936-sh...](http://security.stackexchange.com/questions/6095/xkcd-936-short-
complex-password-or-long-dictionary-passphrase)

~~~
starwed
I wonder if there are any sites that simply forbid passwords that are known to
exist in rainbow tables.

~~~
shabble
I'd assume that's what they're talking about with the 'use blacklist'. It'd be
easy enough to occasionally repopulate it with "obvious" or known-compromised
passwords that turn up.

Likewise, I assume they're keeping that list semi-secure to avoid black-
hats/kiddies getting their hands on a list of really good passwords to throw
into their cracking engine ruleset.

------
mcoates-mozilla
Great feedback. I'm glad to see this guide was helpful and I've made a few
enhancements/updates based on these thoughts.

-Michael (@_mwc)

------
wulczer

      Example A field accepts a username. A good regex would
      be to verify that the data consists of the following
      [0-9a-A-Z]{3,10}. The data is rejected if it doesn't
      match.
    

I guess then that pg won't be able to sign up for your service... Nor will
donfernandovillaverde79.

~~~
qjz
On a related note, one of the web sites I frequently use stripped all spaces
from my password without notice before storing it on the server. So when I
registered with a password like 'I am Sam', I found I could only log in using
'IamSam'. Any attempt to use the original password caused an error. I reported
this to the site admin, and the solution they came up with was to silently
strip the spaces from the password _as it is typed into the form_. Now I can
type in 'I am Sam', but 'IamSam' is the actual password sent to the server.
File this under '2 wrongs don't make a right'.

~~~
elehack
A while ago, Tracfone's web site had a rather disappointing bug. Both the
account registration and login flows did password validation, and used
different validation functions. The result was that I could create an account
with a password containing special characters that the authentication system
would reject as containing invalid characters (and therefore not even try to
verify against my stored password/hash).

Moral: account registration and authentication must use the same password
normalization functions, and if you validate at auth time (which is pointless,
but hey), the validation function must be the same as the registration one.

Better moral: just don't do silly things with passwords. Encrypt them and
store them, accepting whatever the user wants to send you that's sufficiently
long/high-entropy.

------
rickdale
this is brilliant. I am wondering if there are other secure coding guidelines
for web devs? I usually refer to stackoverflow for questions about security,
but often wondered if there was a set standard.

~~~
petejansson
<https://www.owasp.org/index.php/Category:OWASP_Guide_Project>

I was actually wondering how the Mozilla guidance is different.

~~~
zobzu
mozilla websecurity leadis also chairman of owasp. nuff said:-)

------
tszming
Ruby on Rails also provide a guidelines for web security:
<http://guides.rubyonrails.org/security.html>

------
mindhunter
I love the standardisation of generic answers. First thing coming to my mind
as a non-nativ speaker: is there a way to provide translated versions of it
inside the wiki?

------
jroseattle
Good security practices and ease-of-use are often at direct odds with each
other.

