There are many facets to web application security. It's critical to any system that the development team is familiar with common exploits and the best practices to prevent them.
 Best Practices
When building a web application there are common practices which should be followed to enhance security. In addition to the basic security of the server operating system and runtimes, web developers should follow accepted guidelines to write secure applications. These best practices expand on the security best practices which should be applied to all applications.
 Validate Input
Whether a web application is open to the internet or only on a private network, always validate all input. Any layer of an application may be a security risk, and any input may be an attack vector. There are a wide variety of reasons for validating input:
- Input validation helps ensure data integrity. A user may input something unexpected. A bug on the client interface may post something incorrectly and corrupt data.
- Form posts may not be coming from the expected client or from the same web application. A post may come from any client. A form on one web site may post to a web application on another site.
- Malicious code may connect to a web application server from any other computer, with or without the owner's knowledge. The input posted to a web application may not be coming from the actual end user. Bots and scripts from other sources may unexpectedly connect to the web server and attempt to post data or download files. This is extremely common on public web servers.
- Some vulnerabilities in runtimes such as PHP have historically been exposed through requests and posts to web applications. By validating and escaping user input this attack vector becomes limited.
A web application should always know what data or data characteristics to expect. Generally:
- Use whitelisted values whenever possible. For example, if a posted email address should only contain one of a predetermined set of domains, confirm submitted addresses only contain one of those domains. Conversely, use a blacklist when it's known that a subset of data must never be allowed to be input.
- Revalidate limited selections. A form containing an HTML/select (drop-down) lets the user choose from a subset of values, but does not guarantee the form will be posted with one of those values. A malicious post can still contain any value.
- Escape data, using built-in escape functions when available
- Validate data types
- Validate data sources. If data is expected from a form post, be sure the data is actually coming from a post. PHP, for example, has a $_REQUEST variable which combines the data from post, get, and cookies. A cross-site request forgery (CSRF) can come from img tags passing parameters with the URL that may otherwise be expected to come from a form post. Using PHP's $_POST array prevents img elements posted to third-party sites from mimicking form actions.
 Escape and Filter Output
Escaping, filtering, and related functions:
 File System
Web servers generally expose files which are within certain file system paths (the "document root"). Images and CSS files, for example, are often served directly from the generic web server and not by the custom web application. Files which should remain secure should be carefully placed outside the realm of publicly exposed directories.
For example, a web application's code may be securely organized with this directory structure:
/app - Internal application code /htdocs - Document root, publicly accessible /htdocs/index.php - The only script accessible directly by clients /htdocs/main.css /logs /template
Web applications should also be careful when processing file requests from the query string or post data. A request containing a path may expose any file which the web application has read access to. Code files, configuration files, and even password files may become exposed. Before immediately responding with a file's contents, strip the directory part of the path or determine that it's safe for output.
For example, a request for /download?file=data.txt may be safe while /download?file=/etc/passwd should be ignored. This can be handled in a few ways. One simple solution is to store every downloadable file in one directory and not allow the path as part of the request. So in this example data.txt would be a valid request while anything containing a slash ("/" or "\") could respond with a forbidden message. Also be weary of relative paths (like ../../home/username) because they can expose directories other than those intended when evaluated to their absolute path.
One common scenario involves documents which should only be available to logged in users. To provide them for download, they can be placed within a publicly available web directory. But this can expose them to any requests from any client. One method to secure files is to place them outside any directories publicly exposed by the web server and handle the requests manually within the web application. For example, a predefined URL such as /uploads might not resolve to an actual file directory on disk, but is instead handled by PHP code which checks user security and transmits the file itself.
Another common scenario to consider is project checkouts from code repositories. Typical revision control systems store local files for synchronization with a repository. These can accidentally be exposed on a web server, allowing others to see internal file paths and execute them. To avoid this problem, export the code from the repository instead of checking it out. Or block requests for these repository files. With subversion this can be accomplished with the following mod_rewrite configuration:
RewriteRule (\.svn)/(.*?) - [F,L]
A web server should execute with restricted file system rights, only giving it access to read, write, and execute files which are appropriate. Executable scripts should be read-only for the web server so they can't be overwritten by an attacker who leverages a vulnerability to alter the application. A web application should have no access at all to files which it would never require, such as other system configuration files.
There are a few different ways in which databases for web applications should be secured.
- Secure the database itself by limiting connection sources, user accounts, and permissions. Generally, create the most restrictive database environment possible while still allowing the application to function.
- Set the database server to only accept connections from the web application server. Even if the server has a firewall, the database software itself should only be listening to connections from the web application.
- Do not create database user accounts for each web application user (when it's not absolutely necessary). Create one user account to always be used by the application. Handle user authentication at the application level.
- This single application database user should only have the minimum amount of permissions it requires. For example, do not allow the web application database user to create tables, drop tables, or alter grants if it's not required. Never use the database's root or super-user account for a web application; these are only appropriate for system administrators.
- Consider running all queries through stored procedures and not granting the database user any permissions other than execution of those stored procedures. This will greatly restrict the abilities of the database user.
- Do not generate SQL based directly on form input. If a client can post any field names or otherwise generate their own SQL, it often exposes data in unexpected ways.
- Escape form input / POST data so SQL can not be injected directly by the client. It's best to use preparted sql statements. If those are not available, escape each value individually before using in any SQL statement.
In some default server configurations all session information is stored in one location. A security hole in one web application might expose session data among all web applications on the server. Therefore it's often beneficial to store sessions individually for each application.
Sessions should not contain especially secure information in unencrypted form, such as passwords.
Sessions should also be used to ensure that information is only requested or posted from appropriate users. For example, if each user on a site can edit their own profile, check that the user account attempting to edit a profile is the owner of the account. A user ID or account name in the URL is not sufficient. It should be compared with the credentials of the currently logged in user (via session or other cookie).
Especially secure information, such as passwords and credit card numbers, should never be stored in an unencrypted format. One-way encryption functions should be used when decryption is never necessary, such as with a password. To confirm a password, for example, encrypt the user input and compare that value against the encrypted password stored within the system.
Encryption / Decryption functions: