what is a good method to sanitize the whole $_POST array in php?

Viewed 65127

I have a form with a lot of variables which is then sending an email, rather than sanitizing each $_POST value with filter_var($_POST['var'], FILTER_SANITIZE_STRING); I was after a more simple piece of code. I came up with the below, which seems to work as I believe the default action is FILTER_SANITIZE_STRING, but I was just wondering what peoples opinions are, and if this is not good practice, perhaps you could tell me why? The $_POST values are then individually embedded into new variables, so I would only be using array_map just at the start to sanitize everything...

$_POST = array_map('filter_var', $_POST);

Thank you for your replies, to give you a little more information, basically:

I have 20-30 input fields in a form which are being captured, the data is then displayed to the user to check their input, variables are then sanitized, the user is then sent an email and then finally the details are entered into a db.

currently I am sanitizing using the above array_map function, as well as FILTER_SANITIZE_EMAIL on the email address before sending an email and then escaping the input using mysql_real_escape_string() before the insert into the db. Without getting into prepared statements etc.. do you think I should be doing anything additionally? thanks again!

9 Answers

Just use filter_input_array() from the filter extension.

/* prevent XSS. */
$_GET   = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
$_POST  = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);

This will sanitize your $_GET and $_POST.

You can use strip_tags() with array_map()

<?php  
$a = array(
'title' => 'Title',
'data' => array(
    'hdr' => 'Header',
    'bdy' => 'Body'
    ),
'foo' => array(1, 23, 65)
);

$b = array_map("strip_tags", $a);
print_r($b);
?>

Update for 2D array:

function array_map_r( $func, $arr )
{
    $newArr = array();

    foreach( $arr as $key => $value )
    {
        $newArr[ $key ] = ( is_array( $value ) ? array_map_r( $func, $value ) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value ) ) );
    }

    return $newArr;
}

Usage:

$a = array(
'title' => 'Title',
'data' => array(
    'hdr' => 'Header',
    'bdy' => 'Body'
    ),
'foo' => array(1, 23, 65)
); 

$ar =array_map_r('strip_tags', $a);
print_r($ar);

Note I found this just by searching the comments for Dimension

function strip($string, $allowed_tags = NULL)
{
    if (is_array($string))
    {
        foreach ($string as $k => $v)
        {
            $string[$k] = strip($v, $allowed_tags);
        }
        return $string;
    }

    return strip_tags($string, $allowed_tags);
}

Just an example of a recursive function, for stripping tags in this case.

$arr = strip($arr);

This looks ok, but please comment if it can be improved or has any misgivings:

$_GET =filter_var_array($_GET);
$_POST=filter_var_array($_POST);

To apply specific filters on multiple fields, use a switch statement.

$post  = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);

foreach($post as $k => $v) {
    switch ($k) {
        case 'int_1':
        case 'int_2':
            $post[$k] = filter_var($v, FILTER_SANITIZE_NUMBER_INT) * 1;
            break;
        case 'float_1':
        case 'float_2':
            $post[$k] = filter_var($v, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) * 1;
            break;
        default:
            break;
    }
}

Note: My IDE (NetBeans) warns about using global $_POST anywhere as a security violation, so I've just gotten into the habit of using a local $post variable instead. If you choose not to do the blanket string sanitation first, FILTER_SANITIZE_STRING could be used for the default: case.

Related