Did you think your site validated input properly? Think again!

October 21, 2009 – 10:14 pm Tags: , ,

You’ve written a PHP based web app, and you’ve made sure it doesn’t cause errors if the user submits unexpected values via any URLs or forms.

But there’s something you quite likely forgot to test: What if the data that’s expected to be a singular value happens to be an array? If you assumed a GET or POST parameter will never be an array, your site probably joined the ranks of several high-profile sites that go into funny-mode when given unexpected arrays…

How are you submitting arrays when HTTP doesn’t support that?

It’s easy to overlook a simple PHP feature when writing forms or taking parameters in the URL: If you append any parameter name with [], PHP turns it into an array!

Take almost any PHP-based website which uses GET or POST, and modify the parameters into arrays and bang.

Example exploit

Let’s imagine you have a site which has a search feature. As is typical, your site takes the search phrase as a GET parameter like so:

www.mysite.com/search?query=ponies

Very innocent looking parameter there. But what if it was written like this…

www.mysite.com/search?query[]=ponies

Things will go wrong very fast from this point onwards!

The same applies to forms:

<form method="post" action="handler.php">
 <input name="name" />
 <input name="comment" />
 <input value="Send" type="submit" name="send" />
</form>

Quite a normal looking form there. But what if we were to change the code – for example by using Firebug or Opera’s source editor, which both are capable of changing a site’s code on-the-fly

<form method="post" action="handler.php">
 <input name="name[]" />
 <input name="comment[]" />
 <input value="Send" type="submit" name="send" />
</form>

Altering the form ever so slightly suddenly makes the POST parameters get turned into arrays, which may cause subtle problems…

What this “array injection” may cause?

Very typical problem caused by array injection is simply PHP error messages. Another is that your code behaves in slightly erroneous ways, and depending on the case, this may allow someone to abuse your code to do something you never intended it to do.

You’re vulnerable even if you use a framework

The annoying part of this is that unless you check for arrays, you won’t spot this.

Here’s some examples of usually okay parameter processing:

Plain PHP example

$foo = '';
if(!empty($_POST['foo'])) {
  $foo = $_POST['foo'];
}
 
//If you assume here that $foo is a string, you might be in for a surprise...

Zend Framework example

public function myAction() {
  $foo = $this->getParam('foo', '');
 
  //You're still vulnerable!
}

 

The solution

The solution to this issue is simple: Always check data type!

Remember to test your code with array inputs. You might be surprised – I have tested this with a bunch of PHP sites I quickly found, which included some big ones, and almost all of them had a bit weird behavior with this!

This may not sound very dangerous immediately, but better be safe than sorry, no? One possible problem coming from this is that it might be possible to screw up your database queries, possibly making for a Denial of Service attack, or worse.

Share this:

RSS feed Subscribe to my RSS feed

About the author

Jani is a 15 year veteran of the software industry. He's currently available for consulting

  1. 12 Responses to “Did you think your site validated input properly? Think again!”

  2. Frankly, I cannot thing of a single case where properly secured code would be vulnerable to PHP’s array creation from request params.

    If the application gives an unexpected error, it should already have a custom error-hander to handle them nicely. If it allows an attacker to mess with the database it just means that the code is vulnerable, not only to array params, but surely to a whole lot of other input parameters.

    By DrSlump on Oct 21, 2009

  3. The problem is the fact that attempting to validate arrays as strings may often pass. If the value is singular, it may not be exploitable. Passing it in as an array may trigger unexpected, exploitable, behavior. The nature of arrays makes it a bit difficult to actually find holes that would allow you to do something harmful, but it’s something I think people should consider when coding.

    Flickr is vulnerable, for example. Not seriously, but you do get a bit funny output (ie. it says “Array” etc.)

    By Jani Hartikainen on Oct 21, 2009

  4. Why is it that you have no actual examples of where this could lead to a vulnerability?

    By Reinis I. on Oct 21, 2009

  5. To put it another way, assume your code already checks is_string(), and a stranger suggests you can save 20 bytes of code! All you have to do is accept the possibility of attackers, at any time: generating NOTICEs, sending execution down long code paths leading to states with several variables having unexpected values, or passing arrays into 3rd party C functions that expect strings.

    This would be considered a terrible trade-off.

    By Steve Clay on Oct 22, 2009

  6. The 2 character solution: $foo = "$_POST['foo']";

    Of course, this is the kind of thing that would get “optimized” away by follow-up developers, so you’re back to committing time typing the comment “Don’t remove these quotes!” :)

    By Steve Clay on Oct 22, 2009

  7. Array injections ?

    My best trick yes, and as you say : you can’t imagine how many web sites are vulnerable and will display errors to screen (array injections + display_errors=on … ouch!)

    By jpauli on Oct 22, 2009

  8. Cast your inputs to the proper data types before using them, and this isn’t an issue.

    $string = (string) $_POST['foo'];

    By nathan coffield on Oct 23, 2009

  9. You are of course making the assumption that someone would interfere with your form, however taking measures to prevent this from happening would solve this issue as the form is simply refused.

    That is POST sorted, as for other HTTP methods, you should be stripping out any unexpected datatypes anyways – that really should be automated as us developers are lazy by our nature.

    By Les on Oct 23, 2009

  10. A quick way of dealing with this is:

    $value = (isSet ($_POST['var']) && is_string ($_POST['var']) ? $_POST['var'] : false);

    By Martin on Nov 11, 2009

  1. 3 Trackback(s)

  2. Oct 22, 2009: Jani Hartikainen’s Blog: Did you think your site validated input properly? Think again! | Webs Developer
  3. Oct 24, 2009: LimeSpace – IT » Der Wochenrückblick: Grafiken, PHP Kennwörter mit Salt, JQuery + Formulare.
  4. Oct 1, 2012: CSAW 2012 – Web 600 « team pong

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)