我目前正在从讨厌的 XSS 攻击中恢复过来,并意识到我从未对我网站上的几个表单上的输入进行清理。我使用 Notepad++ 的 Find In Files 功能在我所有的 PHP 文件中进行搜索$_POST
,得到了将近 5,000 个结果。现在,我真的不想手动添加strip_tags
到这些结果中的每一个,但是全部替换并不能解决问题……而且当涉及到正则表达式之类的东西时,我完全是个菜鸟。
有什么办法可以让这件事变得不那么乏味吗?
我目前正在从讨厌的 XSS 攻击中恢复过来,并意识到我从未对我网站上的几个表单上的输入进行清理。我使用 Notepad++ 的 Find In Files 功能在我所有的 PHP 文件中进行搜索$_POST
,得到了将近 5,000 个结果。现在,我真的不想手动添加strip_tags
到这些结果中的每一个,但是全部替换并不能解决问题……而且当涉及到正则表达式之类的东西时,我完全是个菜鸟。
有什么办法可以让这件事变得不那么乏味吗?
只需使用array_map()
.
$Clean = array_map('strip_tags', $_POST);
或者,如果您希望它返回$_POST
变量:
$_POST = array_map('strip_tags', $_POST);
尽管使用不同的变量并在文件中更改所有出现的$_POST
to可能是一个更好的主意$Clean
。
嗯,我认为array_walk_recursive
可以解决问题:
function custom_strip(&$val, $index) {
$val = strip_tags($val);
}
array_walk_recursive($_POST, 'custom_strip');
你可以把它放在一个文件中(例如safe.php)
foreach ($_POST as $key => $value) {
$_POST[$key] = is_array($key) ? $_POST[$key]: strip_tags($_POST[$key]);
}
然后放入require_once("safe.php");
每个 php 文件(或所有 php 文件已经包含的文件)
这是一个丑陋的 hack.. 但它可以节省你的时间。
很简单。把它放在你的每个文件的顶部,或者放在一个公共的头文件中,每次都在开始时调用它:
function mystriptag(&$item)
{
$item = strip_tags($item);
}
array_walk($_POST, mystriptag);
你可以这样做,但是编写一个自定义函数来从中获取数据要好得多:array_map
strip_tags
$_POST
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;
}
这将使您的代码更具可读性(其他人研究它通常会假设这$_POST['foo']
是表单字段中的数据foo
,而不是您已经预处理的东西),不会导致您尝试直接访问 $_POST 的插件或库出现问题,使很容易为$_POST
预处理添加更多逻辑(启用魔术引号时不转义是一种常见的逻辑),而无需查找代码中使用过 POST 数据的所有位置,并且当您意识到有一些 POST 时,可以让您免于头疼您确实需要 HTML 标记的字段。通常,直接更改任何超全局变量是一个非常糟糕的主意。
此外,最好对输出数据而不是输入数据进行清理。不同的用途将需要不同的方法,例如,如果您使用
<div class="user_photo">
<img src="<?php echo photo_path($user_id) ?>" alt="<?php echo $user_name ?>" />
</div>
then$user_name
是一个 XSS 攻击向量,strip_tags
对它完全没有帮助;你需要htmlspecialchars。如果将用户数据用作 URL,则需要另一种方法来防御javascript:
URL 等。