views:

89

answers:

5

I'm currently recovering from a nasty XSS attack, and realized I never sanitized inputs on several of the forms on my site. I used Notepad++'s Find In Files feature to search for $_POST in all my PHP files, and got almost 5,000 results. Now, I really don't want to go and manually add strip_tags to every one of those results, but a replace-all wouldn't do the trick... and I'm a total noob when it comes to things like regular expressions.

Is there any way to make this a little less tedious?

+1  A: 

you can put this in a file (e.g safe.php)

foreach ($_POST as $key => $value) {
  $_POST[$key] = is_array($key) ? $_POST[$key]: strip_tags($_POST[$key]);
}

Then put require_once("safe.php"); in every each of your php files (or a file that all of your php file already included )
It's an ugly hack.. but it may save your time.

iKid
Awesome. This is exactly what I was looking for.
Mike Turley
This will fail to protect from XSS when there are form fields whith names like `foo[bar]` or `foo[]` which PHP automatically converts to arrays.
Tgr
@Tgr: yeah, this will absolutely fail like you said, but I think he got the idea to customize according to what he need
iKid
+2  A: 

Hmm, I think array_walk_recursive would do the trick:

function custom_strip(&$val, $index) {
   $val = strip_tags($val);
}
array_walk_recursive($_POST, 'custom_strip');
Jacob Relkin
A: 

Very simple. Put this on top of your every file OR in a common header file which gets called in the very beginning every time:

function mystriptag(&$item)
{
    $item = strip_tags($item);
}

array_walk($_POST, mystriptag);
shamittomar
This will fail to protect from XSS when there are form fields whith names like `foo[bar]` or `foo[]` which PHP automatically converts to arrays.
Tgr
+5  A: 

Just use array_map().

$Clean = array_map('strip_tags', $_POST);

Or if you want it to go back to the $_POST variable:

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

It's probably a better idea though to use a different variable and change all occurrence of $_POST to $Clean in your files.

sirlancelot
A: 

You could just array_map strip_tags to $_POST, but it is much nicer to write a custom function for obtaining data from it:

function post_data($name) {
    global $post_cache;
    if (in_array($name, $post_cache)) {
        return $post_cache[$name];
    }
    $val = $_POST[$name];
    if (is_string($val)) {
        $val = strip_tags($val);
    } else if (is_array($val)) {
        $val = array_map('strip_tags', $val);
    }
    $post_cache[$name] = $val;
    return $val;
}

This will make your code more readable (others looking into it will generally assume that $_POST['foo'] is the data in form field foo, not somethin you have already preprocessed), won't cause you problems with plugins or libraries which try to access $_POST directly, makes it easy to add more logic to $_POST preprocessing (unescape when magic quotes are enabled is a common one) without hunting down all the places in your code where you have used POST data, and saves you from huge headaches when you realize there are a few POST fields where you do need HTML tags. Generally, it is a really bad idea to directly change any of the superglobals.

Also, it is better to sanitize data on output, not on input. Different uses will require different methods, for example, if you use

<div class="user_photo">
   <img src="<?php echo photo_path($user_id) ?>" alt="<?php echo $user_name ?>" />
</div>

then $user_name is an XSS attack vector, and strip_tags does not help against it at all; you would need htmlspecialchars. If user data is used as an URL, you would need yet another method to defend against javascript: URLs and so on.

Tgr