WebAppSec/Secure Coding Guidelines

< WebAppSec
Revision as of 18:26, 12 July 2010 by Mcoates (talk | contribs) (Created page with '=Introduction= 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 info…')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Introduction

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.

Status

The secure coding guidelines page is currently alpha. 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@mozilla.com

Layout

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.

Secure Coding Guidelines

Authentication

Attacks of Concern: brute force password guessing, user enumeration, mass account lockout, time trade-off hash cracking

Password Complexity

Implement the following policy:

  • Passwords must be greater than 8 characters
  • Passwords must require numbers and letters and a special character

Password Rotation

  • Privileged accounts - Password for privileged accounts should be rotated every: 90 days.
  • General User Account - It is also recommended to implement password rotations for general users if possible.
  • Log Entry - an application log entry for this event should be generated.

Account Lockout and Failed Login

Account Lockouts and login failures should be evaluated based on the application. In both cases, the application needs to be aware of the passwords being used in order to determine the corrective action.

Each application should store a hash of the current and previous password. This will be used in order to do a compare against the password being used. If the previous password is being used, this isn't a security event, this is just an informational since the users password change could have just taken place.

The next scenario is if the password has doesn't match the current and previous hash in which we would detect a possible attack against the user account. This would be a logged event and should be logged as such.

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.

Password Reset Functions

If a user has not requested a password reset, it would be nice if the user was given the option to cancel that request. This would also be a good logging point too.

We should hash the current and previous passwords and during a failed login process, do a compare against these records. If they are different, this event would be higher then just a failed password attempt. We should also store the last couple of failed passwords as a hash and also do a compare against them too. This would be to detect if somebody is trying to brute force an account which would generate a critical log message.

Password Storage

  • Passwords stored in a database should using the following format that leverages secure hashing and a per user salt.
 * Every new password stored in a form like {algo}-{salt}-{hash}
   * {algo} is {SHA-256},
   * {salt} is a salt unique per-user,
   * {hash} is algo(salt + password)
  • If upgrading from an existing scheme such as md5 hashing with no-salt, then a conversion process can be established. This conversion will occur whenever a user logs into the system. First attempt to authenticate the user via the above scheme (e.g. unique salt and sha-256). If that fails then authenticate via the old scheme (e.g. md5) and create a new hash in the above scheme(e.g. unique salt and sha-256). Remember to also clear out the old hash value after the conversion is complete for the user.

Session Management

Attacks of Concern: Session Hijacking, Session Fixation, Brute Forcing Valid Session IDs

Session ID Length

Session tokens should be 128-bit or greater

Session ID Creation

The session tokens should be handled by the web server if possible or generated via a cryptographically secure random number generator.

Inactivity Time Out

Authenticated sessions should timeout after determined period of inactivity - 15 minutes is recommended

Secure Flag

The "Secure" flag should be set to prevent exposure of the session ID

HTTP-Only Flag

The "HTTP-Only" flag should be set to disable malicious script access to the session ID (e.g. XSS)

Logout

Upon logout the session ID should be invalidated on the server side and deleted on the client via expiration/overwriting the value.

Access Control

Attacks of Concern Enumeration of site features for targeted attacks, Execution of unauthorized functionality, View or modify unauthorized data

Presentation Layer

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.

Business Layer

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.

Data Layer

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.

Input Validation

Attacks of Concern: Introduction of Dirty/Malformed Data

JavaScript vs Server Side Validation

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.

Positive Approach

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?

Robust Use of Input Validation

All data received from the user should be treated as malicious and verified before using within the application. This includes the following

  • Form data
  • URL parameters
  • Hidden fields
  • Cookie data
  • HTTP Headers
  • Essentially anything in the HTTP request

Goal of Input Validation

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.

Examples of Good Input Validation Approaches For each field define the types of acceptable characters and an acceptable number of characters for the input

  • Username: Letters, numbers, 3 to 10 characters
  • Firstname: Letters, single apostrophe, 1 to 30 characters
  • Simple Zipcode: Numbers, 5 characters

Validating Rich User Content

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

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

Preventing XSS

  • All user data controlled must be encoded when returned in the html page to prevent the execution of malicious data (e.g. XSS). For example <script> would be returned as &lt;script&gt;
  • The type of encoding is specific to the context of the page where the user controlled data is inserted. For example, HTML entity encoding is appropriate for data placed into the HTML body. However, user data placed into a script would need JavaScript specific output encoding

Detailed information on XSS prevention here: OWASP XSS Prevention Cheat Sheet

Preventing SQL Injection

  • String concatenation to build any part of a SQL statement with user controlled data creates a SQL injection vulnerability.
  • Parameterized queries are the sure fire way to prevent SQL injection.

Further Reading: SQL Injection Prevention Cheat Sheet

Preventing OS Injection

  • Avoid sending user controlled data to the OS as much as possible
  • 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. Example

Further Reading: Reviewing Code for OS Injection

Preventing XML Injection

  • Same approach as OS injection. In addition to the existing input validation, define a positive approach which escapes/encodes characters that can be interpreted as xml. At a minimum this includes the following: < > " ' &
  • If accepting raw XML then more robust validation is necessary. This can be complex. Please contact the infrastructure security team for additional discussion

Cross Domain / Unintended User Actions

Attacks of Concern: Cross Site Request Forgery (CSRF), Malicious Framing (Clickjacking), 3rd Party Scripts

Preventing CSRF

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

  • Any state changing operation requires a secure random token (e.g CSRF token) to prevent against CSRF attacks
  • Characteristics of a CSRF Token
    • Unique per user & per user session
    • Large random value
    • Generated by a cryptographically secure random number generator
  • The CSRF token is added as a hidden field for forms or within the URL if the state changing operation occurs via a GET
  • The server rejects the requested action if the CSRF token fails validation

Preventing ClickJacking

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

  • Two approaches to preventing ClickJacking
  1. Set Header "X-Frame-Options: Deny" This works in most current versions of browsers (and soon FF too!)
  2. Add a "FrameBreaking" script that uses a mix of "hiding" page content until JavaScript is guaranteed to be available and the top-most window is guaranteed to be the current frame.

3rd Party Scripts

  • Careful consideration should be used when using third party scripts. While I am sure everybody would do an initial review, updates to scripts should be reviewed with the same due diligence.
  • Ensure any scripts that are used are hosted locally and not dynamically referenced from a third party site.

Secure Transmission

Attacks of Concern: Man in the middle, password theft, session id theft

When To Use SSL/TLS

  • All points from the login page to the logout page must be served over HTTPS.
  • Ensure that the page where a user completes the login form is accessed over HTTPS. This is in addition to POST'ing the form over HTTPS.
  • All authenticated pages must be served over HTTPS. This includes css, scripts, images. Failure to do so creates a vector for man in the middle attack and also causes the browser to display a mixed SSL warning message.

Don't Allow HTTP Access to Secure Pages

  • Never provide an authenticated page or a login page over HTTP. HTTPS should be used for the login landing page and all subsequent authenticated pages.
  • The most secure approach is to display a warning when a user requests the HTTP page to instruct the user to bookmark or type the HTTPS page for future use. However, the more common approach is to just redirect from the HTTP request to the HTTPS equivalent page.

More info on SSL/TLS design can be found here

Implement STS

Where possible, we should utilize STS headers.

Content Security Policy (CSP)

Logging

See Security/Users_and_Logs#Logging_Recommendations

Further Reading

OWASP Top 10

Php Sec Library