Search Google

Friday 13 November 2015

php security tutorial


This tutorial explains how hackers can use XSS (cross-site scripting) and code injection when your PHP code isn't properly secured. These are two of the most common vulnerabilities found in PHP scripts, and both of them are exploited by malicious input from users. Therefore it's important to remember never to thrust user's input.


XSS is a form of code injection by the user (attacker) into your webpage. XSS can happen anywhere where your website displays user generated data. If this data isn't validated or encoded, an attacker can input and run malicious code (usually javascript, but it can also be any other kind of script or html) on your visitor's webbrowsers. This code can, for example, access cookies and session tokens and forward this data to the attackers website. XSS attackers usually don't attack your website itself, but aim to attack your visitors. There are two types of XSS attacks. The non-persistent type is where an attacker doesn't actually alter the code of your page. The persistent type is when an attacker permanently changes the code of your page.

A classic example of non-persistent XSS vulnerability :

<?phpif  (isset($_GET["value"]))
echo "the value you entered : " $_GET["value"] ;
}?><br />
<br />
<a href="?value=<script src=></script>" >Click here to test for XSS on your browser</a>
This simple example displays any value you provide it with. If you enter <h3>hello</h3> you will see 'hello' displayed. But the page also reads the html tags and therefore display 'hello' in a larger fontsize.
This is a harmless example of XSS. A more problematic example would be if the users starts entering javascript. For example :

phpfile.php?value=<script src=> </script>

In this case xss.js is a script that posts a cookie to the attackers website:
alert ('Your cookie wil now be posted to the attackers website');
Using the example above, an attacker can make a user go to<script src=> </script> and it will redirect the users browser, stealing the users cookie in the process, to the attackers website.

An attacker does not necessarily need to post data. Sometimes it's enough for a global PHP variable to display information an attacker can affect:
<?phpecho "Page you requested : "  urldecode($_SERVER["REQUEST_URI"]);?><br />
<a href="?value=<SCRIPT SRC=></SCRIPT>"> Click here to test for XSS on your browser</a>
Using the phpfile above an URL request like phpfile.php?<script>alert(document.cookie);</script> would give an attacker the possibility to execute scripts.

Some browsers (Chrome,Safari and IE) have build in protection against non-persistent XSS attacks (firefox doesn't at the time of writing this). However, it isn't wise to rely on the users browsers to deal with XSS attacks on your website. Some users may use older browsers that don't have an XSS filter or use browsers where the XSS filter doesn't work properly. Also attackers are constantly trying to find ways to bypass XSS filters and often succeed. Furthermore, the filters don't work for persistent XSS attacks.

Persistent XSS attacks

An example of a persistent xss vulnerable code :
{$fp fopen('data.txt''w');fwrite($fp$_GET["message"]);fclose($fp);
}?><form action="" method="get">
Add to the guestbook: <input type="text" name="message" size="60" value="<script src=> </script>"  />
<input type="submit" />
<br />

Guest book data :
<?php include('data.txt');?>

An attacker could now add any javascript code into the guestbook and every visitor that visits the page will run it. This kind of XSS attack is more dangerous and not detectable by browsers.

Note that the example above is not only vulnerable to XSS attacks, but also to the much more dangerous PHP code injection (see below for more information on that subject).

How to prevent XSS attacks

There are good functions available in PHP to clean user input:


this function strips all '<' and '>' characters from a string.
Remeber that only removing certain tags won't help you much if you allow users to modify tag atributes.
For example displaying an image in a PHP file :

<img src="<php echo $user_uploaded_image ; ?>" >

Altering $user_uploaded_image to image1.jpg" onClick="alert('Hello!'); will result in the HTML of that page looking like:

<img src="image1.jpg" onClick="alert('Hello!');" >

Htmlspecialchars and htmlentities

An other PHP function you can use to prevent XSS attacks is htmlspecialchars. This function will translate the input and convert characters like & and < into &amp; and &lt; preventing your browser reading those characters as code. You should use this function when you want your users to be able to post tags on your pages. The htmlentities is identical to htmlspecialchars, except ALL characters which can be converted into HTML character entities are converted. I recommend using one of these two functions for input cleaning.

Probably the most secure way would be allowing only characters a-Z and 0-9 or filtering out any other unwanted characters. This can be done using the preg_match and preg_replace functions.

Securing cookies

If you have sensetive data in plain text in your cookie, it would be a good idea to encrypt it. An other way to secure your cookies is using the httponly flag (available since PHP 5.2.0). If you set this flag, client side scripts like javascript cannot access the cookie. To set a httponly-cookie use for example :
setcookie("cookiename", "value", NULL, NULL, NULL, NULL,TRUE);

Code injection

Code injection happens when an attacker manages to make the server execute PHP code he or she injected. This poses a much bigger security thread than XSS does.

You've already seen an example of code that is vulnerable to code injection in the guestbook example above. If, for example, you would add an entry to the guestbook looking like <?php phpinfo(); ?> , anybody can run any PHP code on your server.

File inclusion

Giving users the ability to provide input for an include or require function is always dangerous (specially if you allow remote file inclusions). Look at the following example:

   $language $_GET['language'] ;
   include( $language );?>

This function is supposed to include a language file e.g. english.php or dutch.php, but the user can provide input like: ../../../../../../../../etc/passwd and read your passwd file or any file that is readable by your webserver on your server.

Writing to files

If you allow users to write to a file that is included in a PHP page you should always remeber to check the input. You might think that the following PHP code looks okay:

$fp fopen("file.ext""w");

      fwrite($fp"<?php \$usr='$userdata'; ?>");          

include ('file.ext');
echo "the user data is : $usr";

As expected a user can input "hello" and the user data will be just hello. An attacker can make an URL like this :
phpfile.php?user_input=hello'%20;%20phpinfo()%20;%20$dummyvar='foobar and $userdata will still be "hello" , but also phpinfo(); is executed (to make the PHP code execute correctly, %20$dummyvar='foobar is added).

Dangerous functions

Code injection can also happen if you allow user input to be processed by other php functions. A couple of examples:

highlight_file ($_GET['arg3'])passthru("echo " $_GET['arg2']);$myvar 'some_value';$x $_GET['arg'];
eval('$myvar = ' $x ';');?>

An attacker could craft an URL like this:
phpfile.php?arg=phpinfo();&arg2=hello ;ls /etc&arg3=phpfile.php
and the result will be the page showing a) the source code of itself, b) a directory listing, c) information about your PHP installation.

I can't guarantee your PHP code will be hacker safe if you read and understood this tutorial, because only the most common security problems where handled in this tutorial, but it should at least make your PHP code a little safer.

If you want to know whether your PHP installation and php.ini settings are safe, take a look here.

No comments:

Post a Comment