Processing secure form data in PHP

Learning how to process form data in PHP is an essential requirement of any application. In PHP the good news is this is very simple to do with lots of options available to the developer. However there are plenty of ways to do it badly. What this series of posts is designed to do is to break down each component of processing form data, discuss the pros and cons of each and pass on some tips that will help you to decide the best fit for your application. We will also explore some best practices in helping you to write secure PHP outcomes.

Using $_GET

For this exercise we will create two files:

  • signup.html.php: This the view
  • process_signup.php: This is the controller

Note: We are using two different extensions here

.html.php

and

.php

You don’t have to do this but it’s good practice to try and categorise your code into processors and views.

Let’s start with the processor:

process_signup.php

<?php $name = $_GET['name']; echo 'Thank you for signing up, ' . $name . '!'; ?>

What’s happening?
Here we have created a processor that is using the $_GET PHP array to strip the data off a URL. Here’s how we might generate the URL parameter:

<p> <a href="process_signup.php?name=toby">Hi, I’m Toby and I want to signup for PHP training! </a?> </p>

What’s happening?
We have created a URL pointing to process_signup.php and embedded a name parameter using ‘?’ as a separator. Incidentally we can add further parameters using the ‘&’ like this:

<p> <a href="process_signup.php?name=Toby&username=Harris">Hi, I’m Toby and I want to signup for PHP training! </a?> </p>


The output will be:

Thank you for signing up, Toby!

Now – using $_GET is great for small amounts of data – BUT there is a potential problem well actually problems. These are:

  1. The data is available on the URL – anyone can see it so not great for sensitive data
  2. Bad guys can potentially inject what ever they like and PHP will process it unless validation is employed

Example of bad stuff:

 <p> <a href="process_signup.php?name=Toby&username=<h1>Harris</h1>">Hi, I’m Toby and I want to signup for PHP training! </a?> </p>

What’s happening?
Notice the h1 tags in the URL string? If you try this script in your own environment you will notice the H1 tag will get rendered. Scale this up to a MySQL statement and what you potentially have is a classic SQL injection or just straight PHP. As you can see this could be a massive security issue.

Sanitise your Data

As easy as it is to compromise your application it is just as easy to safe guard against it! It is often known in the trade as sanitising your data. In other words scanning the data to make sure its what its supposed to be (alpha-numeric, string etc) and striping out anything that looks dodgy.

Inroducing htmlspecialchars

What does htmlspecialchars do?

It’s a great foundation to sanitise your data – what it does is convert anything that could be used as a script parameter into encoded text. Here’s an example:

$name = $_GET['name'];
			echo 'Thank you for signing up, ' .
					htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '!';
					
		/*htmlspecialchars($name, ENT_QUOTES, 'UTF-8') has three parameters: 
		1.) is the variable taken from the get statement 
		2.) is a built in method in PHP to convert single double quotes and other special characters into normal text objects
		3.) Encoding data to UTF-8
		*/

Key considerations
htmlspecialchars($name, ENT_QUOTES, ‘UTF-8’) has three parameters:

  1. is the variable taken from the get statement
  2. is a built in method in PHP to convert single double quotes and other special characters into normal text objects
  3. Encoding data to UTF-8

So that’s it then?

htmlspecialchars is a great start but that should not be the only method for safeguarding your data. PHP is a loosely typed language – what that means is that variables can be defined anywhere in the code and carry any data type. Some languages such as C and JAVA require you to define your variables such as Varchar, int etc in PHP you do not. A way wound this is to use PHP’s inbuilt validation functions such as is_numeric which will test if the var is a string or a number.

is_numeric example

   if (is_numeric($age)) {
        echo "$age is not numeric";
    }

This then rules out straight away any possibility of using a script string to compromise your app.

A quick look at $_POST and $_REQUEST

So far we have focused on $_GET – let’s have a look at $_POST and $_REQUEST and see how they compare.

$_POST

$_POST does the same as $_GET in that it receives data from the client but unlike

$_GET

the data is not attached to URL but posted to the controlling script.

$_REQUEST

$_REQUEST can accept data either via the URL or data posted to it.

So what do I use and when?

For data that is not liable to lead to a compromise of your application $_GET is ideal. Certainly do not include highly sensitive details such as passwords in $_GET requests. $_GET is also well suited to small amounts of data – as a general rule I tend to limit URL strings to no more than four additional elements. Any more than that $_POST is a better option.

For sensitive information and large amounts of data – for example a shopping cart $_POST is ideal for capturing the data which leaves us with $_REQUEST. One could argue that $_REQUEST should just be used for everything because it does not care what method the data comes in. But this is a really bad idea! Similar to sanitising your variables it always makes sense from a security perspective to know precisely what format you expect the data to arrive in – $_GET or $_POST.

What happens if you don’t know what format the data will be in?

There are unique circumstances where you may not know how the data will arrive. Such examples could be search request that may come from different applications or domains or the processing of XSS feeds. In this instance $_REQUEST is a good fit – but take extra care of what format the data should be in. For example string or numeric or may be even using regular expressions if you expect data to be in a specific format such as a serial or part number.

An example of post in action:

Here’s a sample form:

<form action="post_example.php" method="post">
 <div ><label for="firstname">First name:
	<input type="text" name="firstname" id="firstname"/></label>
	  </div >
	     <div > <label for="lastname">Last name:
	        < input type="text" name="lastname" id="lastname"/></label > </div>
	        <div><input type="submit" value="GO"> </div>
	</form>

This is the processing script:

  /*Instead of using get we are using the POST method.  This has several advantages over GET:
    1.) It is more secure
    2.) You can transer a larger array of data
   */
			
   $firstname = $_POST['firstname'];
   $lastname = $_POST['lastname'];
   echo 'Welcome to our web site, ' .
	htmlspecialchars($firstname, ENT_QUOTES, 'UTF-8') . ' ' .
	htmlspecialchars($lastname, ENT_QUOTES, 'UTF-8') . '!';

What’s happening?

Notice we are using the same data as our earlier $_GET example but this time we are using $_POST to capture the data. We also use a form to initiate the $_POST request.

What have we explored in this post?

We have analysed secure and insecure forms of data. We have explored how we can sanitise data and identified the different techniques of transferring data using $_GET, $_POST and $_REQUEST.

It is important to stress in terms of protecting your application this is just the minimum that should be applied to validating your data. There are plenty more techniques that need to be considered such as hashing and salting, techniques often used in conjunction with interacting databases.

No Comments

Post a Comment