Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using a for-loop on submitted POST data in PHP safe?

Tags:

ajax

security

php

I'm always a worry-wart about security in my PHP applications, and I just (potentially) thought of a way a hacker could kill my script. Currently my application takes form data and submits it as an array to a PHP script via AJAX, then loops through this array.

foreach($_POST['form_data'] as $field => $value){
   //Do something here.
}

However, what if a hacker were to forge an AJAX request, and repeatedly submit the 'form_data' array with 100000000000 random elements? The loop would have to iterate through each element, possibly causing a DoS (or at least slow down service), correct?

I'm not entirely educated here, so I may have some incorrect assumptions. Thanks for any input!

like image 772
ACobbs Avatar asked Mar 05 '12 15:03

ACobbs


3 Answers

This will not be an issue: PHP limits the maximum number of POST vars using the max_input_vars directive, which defaults to 1000 variables.

This limit is actually enforced to prevent a much more serious type of DOS attack than the one you are thinking about (really, iterating a few thousand array elements is like nothing), namely hash table collision based attacks (often referred to as HashDOS). For more info on that issue see my article Supercolliding a PHP array.

like image 156
NikiC Avatar answered Nov 10 '22 08:11

NikiC


The loop would have to iterate through each element, possibly causing a DoS (or at least slow down service), correct?

That's true (although the web server's POST size limit, and the script's memory limit will probably put a stop to things long before 100000000000 items).

Also as @duskwulf points out, PHP >= 5.3.9 has the max_input_vars variable which is set to 1000 by default.

You could still do a size check to be safe.

like image 6
Pekka Avatar answered Nov 10 '22 08:11

Pekka


I generally use array_key_exists() for this kind of thing.

If you want to maintain your current loop, try this:

$allowed = array('name', 'address', 'phone', 'etc');
foreach($_POST['form_data'] as $field => $value)
{
  if(array_key_exists($field, $allowed))
    {
     //do something here
    }
}

or look into something like this:

$vals = array_intersect($allowed, $_POST)
like image 3
Adrian Avatar answered Nov 10 '22 07:11

Adrian