Support Forums

Full Version: [Guide] Security: Prevent SQLi and XSS Attacks
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Input Of Data

I have also seen a lot of security problems in open source scripts, and in general posts on forums like this. Security is one of the fundamental things that every programmer must learn, which is why im going to make a quick guide here.

Upon input (protecting against SQL Injection), you should only need to use one of the following functions below (you can use other functions, such as trim() but it’s not necessary for security):
PHP Code:



So let’s go through each of the functions listed above.

You will have noticed I grouped them. The first three functions, is_numeric(), intval() and ctype_alnum() are used to limit the users input, there for preventing any malicious input. The functions above are pretty self explanatory, but I will quickly brush over them:
  • is_numeric() will make sure that a number has a numerical value. It can contain only one full stop (for a decimel place). If your string does not apply with the above, it will fail and return FALSE.
  • intval() will only allow integer values (whole numbers), and if it finds anything else, then it will stop and take the numbers it has found (if any):
    PHP Code:
    $a '123sd987.h4';
    //outputs 123 
  • ctype_alnum() restricts the users input to only alphanumerical characters (0-9, A-Z, a-z).
The function addslashes() just literally adds a backslash before single quotes, double quotes, other backslashes and NUL to escape them. However, if you are using MySQL, then it is actually advised you use the function that is specific to the database, so you would use mysql_real_escape_string(). You would only ever need to use one or the other.

Lastly we have the hash() function. The first parameter you pass to it is the type of hash, and the second is what you would like hashed. This is mainly done upon passwords for security:
PHP Code:
$pws '123abc';
//you can also salt the password, but I will leave that out for now
$secured hash('sha512'$pws); 
We do not need to sanitise the output of that because it will regurgitate a hexadecimal string only (0-9, a-f).

Output Of Data

Next, we have output from the database. This is to prevent Cross-Site Scripting (XSS) attacks. There are one of two functions you can use for this:
PHP Code:

The only difference between htmlspecialchars() and htmlentites() is that the former function translates only special characters (&, ', ", <, >). Whereas the latter function translates all characters which have HTML character entity equivalents (into those entities).

I have always been taught to only escape data upon input to the database, and then to properly sanitise it (with functions such as htmlspecialchars()) upon output of data from the database.
What the hell is that syntax highlighting I can hardly read what your code says!
I think someone has to change it to look like the hackforums highlighting..
Nice guide. Easy to understand and read Smile
Thank you for this guide..It is very nice..
No problem. Let me know if you'd like to see anything else covered.
Great guide, thanks for taking the time to make this. I do agree more programmers need to focus on being more specific when your making your functions, especially the input functions which can be a huge security vulnerability if done poorly on almost all sites.
Awesome little tutorial that you compiled together here. I'm sure it will help a lot of website developers making their site more secure.
Thanks for this guide, however, you should also add that using mysqli_* or PDO is more secure as mysql_* if you use it correctly. Smile
This guide is wrong. So, so very wrong.

The correct way to prevent SQL injection is to use prepared statements. Full stop. There are attacks that can bypass mysql_real_escape_string().

Cross-Site Scripting is a much harder problem than this guide alludes to. For one, context matters a lot! If you're escaping within an HTML attribute, just using htmlspecialchars() or htmlentities() is not enough!

PHP Code:
// This can be hacked:
echo '<input type="text" name="username" value="'htmlentities($_GET['username']), '" />'"\n"

PHP Code:
// This can be hacked too:
echo '<input type="text" name="username" value="'htmlspecialchars($_GET['username']), '" />'"\n"

The 0day on this construct? /form.php?username=text%22%20onload%3D%22alert(%27XSS!%27)%3B

Neither function works the way you want it to work unless you pass the ENT_QUOTES flag.

PHP Code:
// This is safe:
header('Content-Type: text/html;charset=UTF-8');

// ... 

echo '<input type="text" name="username" value="'htmlspecialchars($_GET['username'], ENT_QUOTES'UTF-8'), '" />'"\n";
// Notice the charset matches the header? This is important. 

You can learn more about how to prevent XSS in PHP from our engineering blog, but forewarning: It's a complicated topic.

Also, don't use hash() for passwords.