![]() |
VOOZH | about |
The purpose of this page is to establish a concise and consistent approach to secure application development of Mozilla web applications and web services. The information provided here will be focused towards web based applications; however, the concepts can be universally applied to applications to implement sound security controls and design.
This page will largely focus on secure guidelines and may provide example code at a later time.
The secure coding guidelines page is a living document and constantly updated to reflect new recommendations and techniques. Information that is listed is accurate and can be immediately used to bolster security in your application. If you have comments, suggestions or concerns please email mcoates <at> mozilla.com
The guidelines are discussed within logical security areas. Instead of discussing how to prevent each and every type of attack, we focus on a secure approach to designing an application. Within each section there is a listing of the types of the attacks these controls are geared to protect against. However, this document is not intended to serve as an in-depth analysis of the attack types, rather a guide to creating a secure application.
Here are a few items that are often missed and are relevant for most every website.
Attacks of Concern
All sites should have the following base password policy:
Examples: addons.mozilla.org, bugzilla.mozilla.org, or other critical sites.
Critical sites should add the following requirements to the password policy:
Password rotations have proven to be a little tricky and this should only be used if there is lack of monitoring within the applications and there is a mitigating reason to use rotations. Reasons being short password, or lack of password controls.
Account Lockouts vs login failures should be evaluated based on the application. In either case, the application should be able to determine if the password being used is the same one over and over, or a different password being used which would indicate an attack.
The error message for both cases should be generic such as:
Invalid login attempts (for any reason) should return the generic error message
The username or password you entered is not valid
Logging will be critical for these events as they will feed up into our security event system and we can then take action based on these events. The application should also take action. Example would be in the case that the user is being attacked, the application should stop and/or slow down that user progress by either presenting a captcha or by doing a time delay for that IP address. Captcha's should be used in all cases when a limit of failed attempts has been reached.
The password reset page will accept the username and then send an email with a password reset link to the stored email address for that account.
The following message should be returned to the user regardless if the username or email address is valid:
An email has been sent to the requested account with further information. If you do not receive an email then please confirm you have entered the same email address used during account registration.
We do not want to provide any information that would allow an attacker to determine if an entered username/email address is valid or invalid. Otherwise an attacker could enumerate valid accounts for phishing attacks or brute force attack.
Email verification links should not provide the user with an authenticated session.
Email verification codes must expire after the first use or expire after 8 hours if not used.
Separate from the password policy, we should have the following standards when it comes to storing passwords:
The purpose of hmac and bcrypt storage is as follows:
A sample of this code is here: https://github.com/fwenzel/django-sha2
Keep in mind that while bcrypt is secure you should still enforce good passwords. As slow as an algorithm may be if a password is "123" it still would only take a short amount of time before somebody figures it out.
The following process can be used to migrate an application that is using a different hashing algorithm than the standard hash listed above. The benefits of this approach is that it instantly upgrades all hashes to the strong, recommended hashing algorithm and it does not require users to reset their passwords.
Migration Process
Migrate all password hashes entries in the database as follows. This is a one time, offline migration.
Stored in databases in form: {algo}${salt}${migration_hash}
* {algo} is {sha512+MD5},
* {salt} is a salt unique per-user,
* {migration_hash} is SHA512(salt + existingPasswordHash)
New hash process for new accounts or password changes
Use standard hashing process [above]
New Login Process
1. Attempt to login user with migration hash. This involves performing the old password hash procedure then adding the salt and finally performing the sha512.
Example: Old password hash process is md5 Migration Hash = sha512(perUserSalt + md5(user supplied password))
2. If authentication via migration hash is successful:
- Use the user's provided password and calculate the New Hash per the algorithm defined above.
- Overwrite the Migration Hash with the New Hash
3. If authentication via migration hash is NOT successful:
- The user may already be on the New Hash. Attempt to directly authenticate using the new hash. If this fails, then the password provided by the user is wrong.
Attacks of Concern: Session Hijacking, Session Fixation, Brute Forcing Valid Session IDs
Session tokens should be 128-bit or greater
The session tokens should be handled by the web server if possible or generated via a cryptographically secure random number generator.
Authenticated sessions should timeout after determined period of inactivity - 15 minutes is recommended.
The "Secure" flag should be set during every set-cookie. This will instruct the browser to never send the cookie over HTTP. The purpose of this flag is to prevent the accidental exposure of a cookie value if a user follows an HTTP link.
The "HTTP-Only" flag should be set to disable malicious script access to the session ID (e.g. XSS)
New session IDs should be created on login (to prevent session fixation via XSS on sibling domains or subdomains).
Upon logout the session ID should be invalidated on the server side and deleted on the client via expiration/overwriting the value.
Attacks of Concern Enumeration of site features for targeted attacks, Execution of unauthorized functionality, View or modify unauthorized data
Display Features and Functions Granted to User
It is recommended to not display links or functionality that is not accessible to a user. The purpose is to minimize unnecessary access controls messages and minimize privileged information from being unnecessarily provided to users.
Check Access Control Before Performing Action
Ensure that an access control check is performed before an action is executed within the system. A user could craft a custom GET or POST message to attempt to execute unauthorized functionality.
Check Access Control with Consideration of Targeted Data
Ensure that an access control check also verifies that the user is authorized to act upon the target data. Do not assume that a user authorized to perform action X is able to necessarily perform this action on all data sets.
Attacks of Concern: Introduction of Dirty/Malformed Data
Input validation is performed to minimize malformed data from entering the system. Input Validation is NOT the primary method of preventing XSS, SQL Injection. These are covered in output encoding below.
Input Validation Must Be:
Examples of Good Input Validation Approaches For each field define the types of acceptable characters and an acceptable number of characters for the input
Note: These are just examples to illustrate the idea of whitelist input validation. You'll need to adjust based on the type of input you expect.
Be aware that any JavaScript input validation can be bypassed by an attacker that disables JavaScript or uses a Web Proxy. Ensure that any input validation performed by JavaScript is also performed server side as well.
The variations of attacks are enormous. Use regular expressions to define what is good and then deny the input if anything else is received. In other words, we want to use the approach "Accept Known Good" instead of "Reject Known Bad"
Example A field accepts a username. A good regex would be to verify
that the data consists of the following [0-9a-zA-Z]{3,10}. The data
is rejected if it doesn't match.
A bad approach would be to build a list of malicious strings and then just verify that the username does not contain the bad string. This approach begs the question, did you think of all possible bad strings?
All data received from the user should be treated as malicious and verified before using within the application. This includes the following
It is very difficult to validate rich content submitted by a user. Consider more formal approaches such as HTML Purifier (PHP) or AntiSamy or bleach (Python)
Output encoding is the primary method of preventing XSS and injection attacks. Input validation helps minimize the introduction of malformed data, but it is a secondary control.
Attacks of Concern: Cross Site Scripting, SQL/OS/LDAP/XML Injection
Detailed information on XSS prevention here: OWASP XSS Prevention Cheat Sheet
Further Reading: SQL Injection Prevention Cheat Sheet
Further Reading: Reviewing Code for OS Injection
Attacks of Concern: Cross Site Request Forgery (CSRF), Malicious Framing (Clickjacking), 3rd Party Scripts, Insecure Interaction with 3rd party sites
An attacker creates a self posting form or image tag which executes an action on behalf of the authenticated user. Read more about this attack type here
Note: Some frameworks (such as django) provide this capability. Use the established CSRF protection from the framework instead of creating your own.
A newer attack that uses page layering and framing to convince the user to click or enter data on particular parts of the screen. These actions are actually sent to the framed site to perform actions unbeknown to the victim user. Read more about this attack type here
Set the x-frame-options header for all responses containing HTML content. The possible values are "DENY" or "SAMEORIGIN".
the same domain.
The "DENY" setting is recommended unless a specific need has been identified for framing.
Attacks of Concern: Man in the middle, password theft, session id theft
More info on SSL/TLS design can be found here
Where possible, we should utilize STS headers.
Develop sites without inline JavaScript so adoption of CSP is easier
https://developer.mozilla.org/en/Introducing_Content_Security_Policy
The following are generally blockers for any website using an admin page:
1. Controls are in place to prevent brute force attacks
Options (any of these are fine):
2. The login page and all admin pages are exclusively accessed over HTTPS. Any attempts to access a HTTP page redirect to HTTPS
3. The session id uses the SECURE flag
4. The session id uses the HTTPOnly flag
Configuring Wordpress Admin Pages Securely
Attacks of Concern: Malformed user uploads containing JavaScript, HTML or other executable code, Arbitrary file overwrite
Upload Verification
Upload Storage
Public Serving of Uploaded Content
Beware of "special" files
Upload Verification
Upload Verification
Attacks of Concern: Sensitive Information Disclosure, System Information Disclosure, Aiding exploitation of other vulnerabilities
Error messages displayed to the user should not contain system, diagnostic or debug information.
Debug mode is supported by many applications and frameworks and is acceptable for Mozilla applications. However, debug mode should only be enabled in stage.
Error messages are often logged to text files or files viewed within a web browser.
Michael Coates - mcoates [at] mozilla.com
Chris Lyon - clyon [at] mozilla.com
Mark Goodwin - mgoodwin [at] mozilla.com