Help - Search - Members - Calendar
Full Version: The Security Checklist
Zymic Webmaster Forums > Zymic Free Web Hosting > Tutorials
PDNWorkshop
Sanitise user input before sending content to database
Use addslashes() to add a "\" to all special characters before user input is sent to the database. This will minimize the risk of a cracking technique known as SQL injection in which SQL commands are inserted into text to change functionality. Adding slashes should prevent a cracker ending SQL quotes. It is also important to ensure all numeric values are, in fact, numeric, as addslashes() cannot prevent SQL injection in this case given that numeric values are given outside of quotes.

Only allow known FileTypes to be uploaded
If you allow file uploads in your website you should ensure you only allow types known to be safe. If you do not the user could upload a PHP file with their own commands and give them the same level of control as any other PHP file. Additionally, if you wish to allow upload files of questionable format safety, such as .dll, force the user to place it in a ZIP archive.

Authenticate users when an action requiring their credentials is to be performed
While sessions can be useful for storing login data, and your application should verify credentials when the user logs-in to ensure you warn them of an incorrect password, remember that given that the PHP session functionality is stored in a cookie, authentication at that point is for the sake of the user, not security and should not be trusted as a valid login. You should authenticate users from login data stored in sessions each time such an action is to be performed and confirmation that a user has been sucessfully authenticated is with variables sourced from that page. Additionally you should remember to perform addslashes() each time such data is retrieved from a client-controlled medium such as this.

Remove HTML tags from any data displayed on a page
It is vital that all HTML tags are removed from data displayed on pages. If this is neglected, what stops a user from setting up a redirect for admins to the URL that deleted a page?

Require sanitised password to be sent as a POST parameter to command pages
If there is a page on your website that deletes a page, it is vital that this page requires a valid password to be sent as a POST command. If you only rely on sessions to get the password to validate then a cracker can easily give a moderator a rouge link to such a URL and see the page deleted. No amount of confirmation can supplement this as a page refresh is still required.

Ensure any pages that accept URLs properly sanitise the input.
If you have a download script that downloads files from a certain directory you should prevent the forward slash being used as this could change the directory and allow the cracker to download your full PHP scripts as well as any file, probably with your database password somewhere within. I also recommended you only allow file extensions of needed FileTypes as an added precaution.

Hash and tweak all passwords to be stored
It is important that you not only md5 any passwords to be stored in a database, but also tweak them with some algorithm to decrease the likelyhood of falling victim to hash tables available on the web if someone cracks your website.

Backup your site and database regularly
Finally, it is important to backup your website and database regularly, in case you do fall victim to being cracked, at least this will allow your site to go back online, although if this happens I urge you to contact your site's security professional for an urgent meeting before doing so to ensure this does not happen again and convince your users you are working tirelessly to prevent future attacks.

Disclaimer: I am not a security expert and this page is merely intended to be an alternative to no security precautions. It is recommended that you consult a qualified security expert if you are serious about your website.
Alex
Just catching up with these tutorials...

QUOTE(PDNWorkshop @ Jun 24 2008, 11:51 PM) *
Sanitise user input before sending content to database
Use addslashes() to add a "\" to all special characters before user input is sent to the database. This will minimize the risk of a cracking technique known as SQL injection in which SQL commands are inserted into text to change functionality. Adding slashes should prevent a cracker ending SQL quotes. It is also important to ensure all numeric values are, in fact, numeric, as addslashes() cannot prevent SQL injection in this case given that numeric values are given outside of quotes.


Validation before sanitisation, and if you /are/ sanitising data to a database, when you should not use addslashes(), you should use a database specific sanitisation function or use prepared queries. Ideally the latter, but since some database drivers in PHP don't support them (like the standard mysql driver) you should use the specific sanitisation functions, for example mysql uses mysql_real_escape_string().


QUOTE(PDNWorkshop @ Jun 24 2008, 11:51 PM) *
Only allow known FileTypes to be uploaded
If you allow file uploads in your website you should ensure you only allow types known to be safe. If you do not the user could upload a PHP file with their own commands and give them the same level of control as any other PHP file. Additionally, if you wish to allow upload files of questionable format safety, such as .dll, force the user to place it in a ZIP archive.


Largely true, though something that should definitely be mentioned is that you should either upload them to a directory below the document root or within a directory set to deny access to all via .htaccess, that prevents the user from directly accessing the file which would be an issue with things like uploaded PHP documents.


QUOTE(PDNWorkshop @ Jun 24 2008, 11:51 PM) *
Remove HTML tags from any data displayed on a page
It is vital that all HTML tags are removed from data displayed on pages. If this is neglected, what stops a user from setting up a redirect for admins to the URL that deleted a page?


If you're targetting a known admin with a known delete URL, then you don't need to inject HTML, merely lure that admin into loading a file which contains <img src="http://site.com/path/to/delete" alt="">, this is known as CSRF by the way and I'll get on to a way of preventing it in a second. First though, you should still be stripping unwanted HTML, but that's more because of threat of injecting script tags for stealing cookies.

Anyhoo, a method you can use to stop CSRF-style attacks by getting an authenticated admin to request a deletion page would be to make the links non-static, forcing them to require a randomly generated string that changes each time a protected action is linked to or executed. You would store this string in session data, and then check that it is correct before executing the protected action, that way you have an unpredictable URL for protected actions that cannot be trivially beaten. You can also make them require post data to require more user interaction, but that can still be suspect.


QUOTE(PDNWorkshop @ Jun 24 2008, 11:51 PM) *
Require sanitised password to be sent as a POST parameter to command pages
If there is a page on your website that deletes a page, it is vital that this page requires a valid password to be sent as a POST command. If you only rely on sessions to get the password to validate then a cracker can easily give a moderator a rouge link to such a URL and see the page deleted. No amount of confirmation can supplement this as a page refresh is still required.


Given the above CSRF avoidance technique, this is unnecessary, and would be tedious and somewhat dangerous to be sending the password so often on a non SSL secured session. I would much rather keep password transmission to a minimum and use alternative (equally effective, less irritating) methods to prevent CSRF.


QUOTE(PDNWorkshop @ Jun 24 2008, 11:51 PM) *
Ensure any pages that accept URLs properly sanitise the input.
If you have a download script that downloads files from a certain directory you should prevent the forward slash being used as this could change the directory and allow the cracker to download your full PHP scripts as well as any file, probably with your database password somewhere within. I also recommended you only allow file extensions of needed FileTypes as an added precaution.


ALWAYS validate or sanitise any user input, the fact it's a URL makes no difference tongue.gif. I am not sure why this is a separate point.


QUOTE(PDNWorkshop @ Jun 24 2008, 11:51 PM) *
Hash and tweak all passwords to be stored
It is important that you not only md5 any passwords to be stored in a database, but also tweak them with some algorithm to decrease the likelyhood of falling victim to hash tables available on the web if someone cracks your website.


I would definitely recommend not using md5 or even sha1 ideally. They have known security vulnerabilities which can break certain numbers of rounds of each, and vastly improve brute force attacks. They're also very common and you can find rainbow tables for them. I would personally recommend using a cryptographic hashing algorithm from the SHA2 family of algorithms that being sha256 and sha512 primarily (the others are truncated versions of those two algorithms with different seed inputs).

Multi-passing is recommended and you should be using at least one salt for each input password. A very simplistic "more secure" way to hash a password might be:

CODE
<?php

// blah code...
// we assume we've got a function that generates suitable random strings (hexadecimal range preferred so you can hide the resulting salt easily in the result) called strrand()

$saltA = strrand(5); // 5 character random strings
$saltB = strrand(5);

$hash = hash('sha256', $saltB . hash('sha256', $_POST['password'] . $saltA)) . $saltB . $saltA;

// blah...
?>


We store the salts with the password in the database, and then when comparing an input password for validity we extract the salts from the database entry and perform the same hashing operation. The reason for this is that it obfuscates which part is the actual password hash, and means that even if they were to brute force each sha256-length segment of the database entry it's incredibly unlikely that any of the results would be the password required to authenticate (the probability is so small it's negligible I'd say). Of course you can trivially make that a bit more complicated by breaking up the salt in different places in the result, padding out to a sha512-length result with random ignored characters and other such things, but you should have your own method anyway, don't just copy/paste and implement this one. wink.gif
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2012 Invision Power Services, Inc.