Snippets Of Defense Pt.III
This article is part of a series of posts about small and easy to understand code fragments you can use on your site for protection against certain kinds of attacks. Also this series is targeted to help you understand better what tricks are used by attackers to break into your site and how to avert them. If you have a Snippet of defense yourself and you want to share it, feel free to contact us. Self-defense with a Walking-stick.
The snippet - sanitize your input recursively
This time we are going to show a PHP snippet which you can use to filter your input recursively - working for PHP4 and PHP5 and being pretty copy&paste ready. Furthermore, the snippet shows how you can defeat XSS on your application without being too aggressive and not forbidding the user to use certain characters. Several large applications use this method or similar ones - although, of course, it is not suitable for all platform out there.
You can use this snippet to secure existing applications by embedding it via auto_prepend_file or using it at a centralized position in your application's index.php. It doesn't rely on any external software or extensions so it should be running fine on most PHP environments without any problems. And of course don't use it sightlessly - but that goes for all snippets of this series.
/**
* Initial filter method
*
* @param array $to_filter
* @return array
*/
function filter($to_filter) {
if (!empty($to_filter)) {
foreach ($to_filter as $key => $value) {
$filtered[$key] = iterate($key, $value);
}
}
return $filtered;
}
/**
* Iterates recursively of the array to
* be filtered
*
* @param string $key
* @param string $value
* @return mixed
*/
function iterate($key, $value) {
if (!is_array($value)) {
if (is_string($value)) {
$filtered[$key] = sanitize($value);
}
} else {
foreach ($value as $subKey => $subValue) {
$filtered[$key][$subKey] = sanitize($subValue);
}
}
return $filtered[$key];
}
/**
* The sanitization method
*
* @param string $string
* @return string
*/
function sanitize($string) {
$search = array('"', "'");
$replace = array('"', '''); // ” and ’ are used here
/**
* Remind that the replacement is just one way of many.
* You can also use html_special_chars() or htmlentities() - but
* don't forget the third parameter :)
*/
return strip_tags(str_replace($search, $replace, $string)
}
/**
* overwrite the original request array with the filtered one
*/
$_REQUEST = filter($_REQUEST);
We hope that you enjoy the trick - please tell us what you think. Till the next time.
Archived Comments
return strip_tags(str_replace($search, $replace, $string)
should be
return strip_tags(str_replace($search, $replace, $string));
Furthermore editing $_REQUEST does not change the values in $_GET, $_POST, $_COOKIE, etc. SO you would need to do this to every array you want to sanitize, and then reconstruct $_REQUEST from your already filtered initial arrays.
This is purely IMO, but $_REQUEST seems like a bad idea, since you don't know where the stuff your working with came from, especially considering it relies on the variables_order directive.
Anyway, this seems pretty much identical to magic_quotes so I'm not going to bother criticising it since the arguments for/against magic_quotes have been rehashed enough times already. $var) {
$safe_html[$key]=recurs_escape_html($var);
}
} else {
return htmlentities($data, ENT_QUOTES, 'ISO-8859-1');
}
return $safe_html;
}
?>
> I use the iconv function to force an encoding set on the supplied data > I loop through each $_POST and $_GET and set the values that way (as kuza55 suggested [cookie not included as this is only an idea to get you going])Finally, there is a small bug in my code (intentional for this post) so post back if you can find how to make it throw an error, should be easy :) oh and as a final thought, generally you might want to trim the string straight up to a fixed length you know you can handle it with whatever you want to do.
$value){
$_POST[$name] = santize($value);
}
}
// Clean any supplied get values
if(isset($_GET)) {
foreach($_GET as $name => $value){
$_GET[$name] = santize($value);
}
}
?>
$_GET = filter($_GET);
$_POST = filter($_POST);
$_COOKIE = filter($_COOKIE);