writing secure php applications

29
How things can go wrong? How to prevent the disaster? Writing Secure PHP Applications

Upload: carina

Post on 20-Jan-2016

60 views

Category:

Documents


1 download

DESCRIPTION

Writing Secure PHP Applications. How things can go wrong? How to prevent the disaster?. Never, ever, trust user inputs. Input Validation. Always use server side validation as client side (javascript) validation can easily be bypassed Use white-listed values Use built-in escape functions - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Writing Secure PHP Applications

How things can go wrong?How to prevent the disaster?

Writing Secure PHP Applications

Page 2: Writing Secure PHP Applications

Never, ever, trust user inputs

Page 3: Writing Secure PHP Applications

Input ValidationAlways use server side validation as client

side (javascript) validation can easily be bypassed

Use white-listed valuesUse built-in escape functionsValidate for correct data types, like

numbersDon’t expect the return value from

selections, radio buttons or check boxes of a form to be the ones you mentioned. So, always revalidate.

Page 4: Writing Secure PHP Applications

PHP Error MessagesGreat tool for both developer and hacker.Can reveal server software and directory

structure, even database login information.Need to set error_reporting to 0 using php.ini

or .htaccess file in production server.Should have separate .htaccess files for

development and production servers.Use proper error handlers when necessary

(instead of just showing the error message and die()ing )

Further Reading : http://perishablepress.com/press/2008/01/14/advanced-php-error-handling-via-htaccess/

Page 5: Writing Secure PHP Applications

Bad Features of PHPRegister Globals Consider the following code -

test.php

if ($password == "my_password") { $authorized = 1;

} if ($authorized == 1) {

echo "Lots of important stuff."; }

test.php?authorized=1 will produce “Lots of important stuff.”

To disable register_globals using .htaccess file – php_flag register_globals 0

To disable register_globals using php.ini – register_globals = Off

Page 6: Writing Secure PHP Applications

Bad Features of PHPMagic QuotesOriginally introduced to save programmers the

trouble of using addslashes()Major problems associated with it is – a.When both magic quotes and addslashes() are

used, you end up with multiple slashes being added, causing errors

b.If you think magic quotes is turned on, but actually it is not, then inputs go unchecked.

c. It only escapes double and single quote, but there are other database-specific characters that need to be escaped

Page 7: Writing Secure PHP Applications

Bad Features of PHPMagic Quotes

Disabling using .htaccess – php_flag magic_quotes_gpc 0 php_flag magic_quotes_runtime 0

Disabling using php.ini – magic_quotes_gpc = Off magic_quotes_runtime = Off magic_quotes_sybase = Off

Page 8: Writing Secure PHP Applications

SQL Injection Most common and most destructive security hazard Lets see the common way to check username and password

entered into a form – $check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$_POST['username']."' and Password = '".$_POST['password']."'");

If we enter the following in the “username” input box and submit -' OR 1=1 #

The query that is going to be executed will now look like this –SELECT Username, Password FROM Users WHERE Username = '' OR 1=1 #' and Password = ''

As you can see, this query will return all the users from the database and as generally first user on a user table is the admin, the hacker will easily gain admin privilege.

We need to either use mysql_real_escape_string() on all database inputs (not just on string types) or use mysqli extension.

Page 9: Writing Secure PHP Applications

File ManipulationSome sites currently running on the web today

have URLs that look like this:index.php?page=contactus.html

The user can very easily change the "contactus.html" bit to anything they like. For example,

index.php?page=.htpasswdBy changing the URL, on some systems, to

reference a file on another server, they could even run PHP that they have written on your site.

When users download a file from your server, if the file name depends on user input, he can easily manipulate it to download system files by giving inputs like – “../../../etc/passwd”

Page 10: Writing Secure PHP Applications

File ManipulationTo prevent remote and system files inclusion,

make these changes in your php.ini file – 1.Correctly set “open_basedir”2.Set “allow_url_fopen” to Off

Always validate file names to make sure only valid characters are included – function isValidFileName($file) {

/* don't allow .. and allow any "word" character */

return preg_match('/^(((?:\.)(?!\.))|\w)+$/', $file); }

Use database and hidden, generated file names if possible for file downloads.

Page 11: Writing Secure PHP Applications

Using DefaultsMySQL uses default username of “root” and blank

passwordSQL Server uses “sa” as default user with a blank

passwordHackers will first try to use the default username,

password combination everywhere – be it a MySQL server or CMS like Wordpress, Joomla or Drupal.

Make sure first thing you do after installing any software on server is to change default username, passwords.

Also, create separate users other than “root” with appropriate permissions on MySQL.

Page 12: Writing Secure PHP Applications

Leaving Installation Files OnlineMany PHP programs come with installation

files. Many of these are self-deleting once run, and many applications will refuse to run until you delete the installation files.

Many however, will not pay the blindest bit of attention if the install files are still online. If they are still online, they may still be usable, and someone may be able to use them to overwrite your entire site.

Page 13: Writing Secure PHP Applications

PredictabilityIf a hacker wants to gain admin access of your

site, first location they will try to look into may be - http://www.yoursite.com/admin/

Make sure your admin area is not predictable. Use something like – http://www.yoursite.com/jsfh8sfsifuhsi8392/ 

Same goes with username and password. Don’t use an username ‘admin’ or ‘administrator’. Pick something unusual

Use a combination of lower and upper case letters along with digits to prevent dictionary attack.

Page 14: Writing Secure PHP Applications

File SystemsAlways disable directory listing by placing a

‘index.html’ file in every folder. You can also disable by using .htaccess or httpd.conf file, but using ‘index.html’ will make sure you’re protected even if your server settings are changed.

Don’t place common files in a directory like ‘www.mywebsite.com/includes/’. Use something out of web root for that and give it an unusual name.

Don’t give a file the extension ‘.inc’ as it is usually rendered as text and can reveal the whole source code (and maybe database login information too). If you must use ‘.inc’, use ‘.inc.php’ instead as it will be rendered as php file.

Page 15: Writing Secure PHP Applications

Session HijackingBy default, session information in PHP is written

to a temporary directory. The file itself contains the information in a fairly readable format.

As the file has to be readable and writable by the Web server user, the session files can create a major problem for anyone on a shared server. Someone other than you can write a script that reads these files so they can try to get values out of the session.

Encrypt everything that you put into session. It is not completely safe though.

Store session data in a different place, like a database.

Page 16: Writing Secure PHP Applications

Storing PasswordsDo not store password as plain textDo not try to invent your own password securityDo not encrypt passwords as they are

reversible. Security through obscurity is not sufficient.

Do not use MD5 – though this cryptographic hashing function is irreversible , it is quite easy to make a list of millions of hashed passwords (a rainbow table) and compare the hashes to find the original passwords. MD5 is also prone to brute forcing (trying out all combinations with an automated script) because of collisions. 

Page 17: Writing Secure PHP Applications

Storing PasswordsDo not use a single site-wide salt. A salt is a string

that is hashed together with a password so that most rainbow tables (or dictionary attacks) won’t work.$password = 'swordfish';

$salt = 'something random';  

$hash = md5($salt . $password);//Value: db4968a3db5f6ed2f60073c747bb4fb5

Use a cryptographically strong hashing function like SHA-1 or even SHA-256 (using PHP’s hash() function).

Use a long and random salt for each password.Use a slow hashing algorithm to make brute force

attacks near impossible.Regenerate the hash every time a users logs in.

Page 18: Writing Secure PHP Applications

Storing PasswordsCode to create the hash and salt

$username = 'Admin'; $password = 'gf45_gdf#4hg';   // Create a 256 bit (64 characters) long random salt // Let's add 'something random' and the username // to the salt as well for added security $salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username));  

// Prefix the password with the salt $hash = $salt . $password;  

// Hash the salted password a bunch of times for ( $i = 0; $i < 100000; $i ++ ) { $hash = hash('sha256', $hash); }  

// Prefix the hash with the salt so we can find it back later $hash = $salt . $hash;

Page 19: Writing Secure PHP Applications

Storing PasswordsCode to validate password

$username = 'Admin'; $password = 'gf45_gdf#4hg';   $sql = ' SELECT `hash` FROM `users` WHERE `username` = "' . mysql_real_escape_string($username) . '" LIMIT 1 ;';   $r = mysql_fetch_assoc(mysql_query($sql));  

// The first 64 characters of the hash is the salt $salt = substr($r['hash'], 0, 64);   $hash = $salt . $password;  

// Hash the password as we did before for ( $i = 0; $i < 100000; $i ++ ) {

$hash = hash('sha256', $hash); }   $hash = $salt . $hash;   if ( $hash == $r['hash'] ) {

// Ok! }

Page 20: Writing Secure PHP Applications

Login SystemsYou should add a turing test to your admin login page.

Have a randomly generated series of letters and numbers on the page that the user must enter to login. Make sure this series changes each time the user tries to login, that it is an image (rather than simple text), and that it cannot be identified by an optical character recognition script.

Add in a simple counter. If you detect a certain number of failed logins in a row, disable logging in to the administration area until it is reactivated by someone responsible. If you only allow each potential attacker a small number of attempts to guess a password, they will have to be very lucky indeed to gain access to the protected area. This might be inconvenient for authentic users, however is usually a price worth paying.

Make sure you track IP addresses of both those users who successfully login and those who don't. If you spot repeated attempts from a single IP address to access the site, you may consider blocking access from that IP address altogether.

Page 21: Writing Secure PHP Applications

Powerful CommandsPHP contains a variety of commands with access to

the operating system of the server, and that can interact with other programs. Unless you need access to these specific commands, it is highly recommended that you disable them entirely.

For example, the eval() function allows you to treat a string as PHP code and execute it. This can be a useful tool on occasion. However, if using the eval() function on any input from the user, the user could cause all sorts of problems. You could be, without careful input validation, giving the user free reign to execute whatever commands he or she wants. For example – eval("shell_exec(\"rm -rf {$_SERVER['DOCUMENT_ROOT']}\");");

Page 22: Writing Secure PHP Applications

Powerful CommandsThe php.ini file gives you a way to completely

disable certain functions in PHP - "disable_functions". This directive of the php.ini file takes a comma-separated list of function names, and will completely disable these in PHP. Commonly disabled functions include ini_set(), exec(),fopen(), popen(), passthru(), readfile(), file(), shell_exec() and system().

It may be (it usually is) worth enabling safe_mode on your server. This instructs PHP to limit the use of functions and operators that can be used to cause problems. If it is possible to enable safe_mode and still have your scripts function, it is usually best to do so.

Page 23: Writing Secure PHP Applications

Cross-Site Scripting (XSS)Unlike SQL Injection, which relies on the use of

delimiters in user-input text to take control of database queries, code injection relies on mistakes in the treatment of text before it is output.

Let's say you've not added a limit to username lengths. Someone could, if they wanted, create a user with the following username:

username<script type="text/javascript" src="http://www.website.com/malicious.js"></script>

Anyone that then views a page with that username on it will see a normal username, but a JavaScript has been loaded from another site invisibly to the user.

Page 24: Writing Secure PHP Applications

Cross-Site Scripting (XSS)It allows attackers to add keyloggers,

tracking scripts or porn banners on your site, or just stop your site working altogether. 

It can also used for cookie hijacking so that a real user can be faked.

Always use htmlentities() function to output user-generated texts.

Limit the character set that can used for a particular text type

Disallow HTML input if possible. If that is not an option, only allow limited HTML tags

Page 25: Writing Secure PHP Applications

Cross-Site Request Forgery (CSRF)CSRF attacks are exploits that take advantage of user

privileges to carry out an attack. In a CSRF attack, your users can easily become unsuspecting accomplices. For example – <img src="http://www.example.com/processSomething?id=123456789" />

CSRF attacks are often in the form of <img> tags because the browser unwittingly calls the URL to get the image. However, the image source could just as easily be the URL of a page on the same site that does some processing based on the parameters passed into it. When this <img> tag is placed with an XSS attack — which are the most common of the documented attacks — users can easily do something with their credentials without knowing it — thus, the forgery.

Page 26: Writing Secure PHP Applications

Cross-Site Request Forgery (CSRF)Never let the user do anything with a GET request -

always use POST. Confirm actions before performing them with a

confirmation dialog on a separate page - and make sure both the original action button or link and the confirmation were clicked.

Add a randomly generated token to forms and verify its presence when a request is made. 

Time-out sessions with a short timespan (think minutes, not hours). Encourage the user to log out when they've finished. 

Check the HTTP_REFERER header (it can be hidden, but is still worth checking as if it is a different domain to that expected it is definitely a CSRF request).

Page 27: Writing Secure PHP Applications

ReferencesHow to store passwords safely with PHP and MySQL –

http://elbertf.com/2010/01/store-passwords-safely-with-php-and-mysql/

Writing secure PHP series –http://www.addedbytes.com/writing-secure-php/writing-

secure-php-1/http://www.addedbytes.com/writing-secure-php/writing-

secure-php-2/http://www.addedbytes.com/writing-secure-php/writing-

secure-php-3/http://www.addedbytes.com/writing-secure-php/writing-

secure-php-4/Seven habits for writing secure PHP applications by IBM -

http://www.ibm.com/developerworks/opensource/library/os-php-secure-apps/index.html

5 Helpful Tips for Creating Secure PHP Applications - http://net.tutsplus.com/tutorials/php/5-helpful-tips-for-creating-secure-php-applications/

Page 28: Writing Secure PHP Applications

Finally, Be Completely and Utterly Paranoid

Page 29: Writing Secure PHP Applications

Thank you