What do I need to know to make my web application secure?


I have built simple PHP application by looking at various articles and tutorials around the web. Since I am now giving it to a few clients, I am worried about its security. How do I make sure it doesn't get hacked?

If you're talking just from the perspective of making your code secure, there are some things you should be aware of (this is an incomplete list but should get you started):

SQL Injection

If you have any SQL queries in your application and any of them use input from the user, you could be vulnerable to SQL Injection. This is when the user submits something malicious in the place of a form field, which, when inserted into your query, will give the attacker the ability to access other parts of your database.

How to prevent: any input you get from the user needs to be sanitized before you use it in a query. In order to do so, you can use prepared (or parameterized) statements (ie. mysqli::prepare or PDO) or use a function that properly escapes your input values before you use them in your queries (ie. mysql_real_escape_string)

Cross-site scripting (XSS) attacks

If you take any input from the user and output it in another page (for instance, you might collect user data and then output a list of users), you could be vulnerable to an XSS attack. The way these work is by adding code (generally <script> tags) into form fields, and if they are not sanitized before being output, the attacker will have added their own Javascript into your page, which will run in the context of your page (and therefore, have access to things like your cookies).

How to prevent: Unless there is a good reason to be letting your users output HTML, every time you output something that comes from the user, it should be sanitized with htmlspecialchars, which will turn potentially dangerous characters (< and > for instance) into HTML entities. If you must let your user output HTML, you should have a specific set of tags that are allowed and ensure that only those tags are allowed through (using a DOM parser or strip_tags for example).

See also: The Cross-Site Scripting (XSS) FAQ

Cross-site request forgery (CSRF) attacks

This is an attack where an attacker tricks a user's browser into making a request on its own (for instance, by injecting code into your site, though the attack can actually originate from anywhere) that takes advantage of authentication cookies stored in the user's browser. For example, let's say you had created a banking application, an attacker could cause a legitimate user who still has an active authentication cookie for your site to request http://yourapp.com/transfer_funds.php?to=attacker, without knowing it.

How to prevent: GET requests should be idempotent (that is, should always have the same effect, or should not cause your application state to change). That means that any operations that the user can do (for example, CRUD operations) should be made through POST, not GET. Similarly, you should check $_POST, and not $_REQUEST for these operations, because $_REQUEST will contain values from both $_POST and $_GET.
However, your application can still be vulnerable to CSRF even if you're using POST. In order to protect better, many people use a system of challenge tokens, where the application generates a random string that is related to the user session. This challenge token is passed along with any relevant requests the application itself makes (by including it in the form) and then is verified before any operation is allowed to take place. Note that if your application has an XSS vulnerability, your challenge token can be compromised.

See also: The Cross-Site Request Forgery (CSRF/XSRF) FAQ

Exploiting eval or system commands

If you use eval along with user input, you are opening up your entire application environment (and beyond that, your server environment) to a potential attack, because if you aren't extremely careful (and even if you are), you are giving users the ability to run whatever arbitrary code they want. This could result in anything from modifying your database, changing your server environment, installing and running scripts or binaries on the server, deleting your PHP files... (this same sort of attack applies to any PHP function that makes a system call, including system, fopen, any of the functions that access the filesystem...so be very careful when you use user input!)

How to prevent: Do not use eval with user input. If you think you need to use eval with user input, there probably is a better (and safer) way to solve the problem.