Php 这种创造性的输入净化方式可能会面临什么样的安全漏洞?(如有的话)

Php 这种创造性的输入净化方式可能会面临什么样的安全漏洞?(如有的话),php,security,input,Php,Security,Input,清理输入的标准方法是使用命令,例如 $url=preg_替换“\[^a-z0-9-~+.?=!&;/:%@$\\\\*\\\\\x80-\\xff]| i”,$url $strip=数组'%0d'、'%0a'、'%0d'、'%0a' preg_replace/[^A-Za-z0-9]/,美元字符串 回音$str 然而,我喜欢我的用户能够在他们的输入、评论/用户名/等等中使用括号、克拉、引号等好东西。因为HTML呈现了诸如&40;例如,我希望使用这种替代方法来净化他们的输入 在我开始编写一个函数来

清理输入的标准方法是使用命令,例如

$url=preg_替换“\[^a-z0-9-~+.?=!&;/:%@$\\\\*\\\\\x80-\\xff]| i”,$url

$strip=数组'%0d'、'%0a'、'%0d'、'%0a'

preg_replace/[^A-Za-z0-9]/,美元字符串

回音$str

然而,我喜欢我的用户能够在他们的输入、评论/用户名/等等中使用括号、克拉、引号等好东西。因为HTML呈现了诸如&40;例如,我希望使用这种替代方法来净化他们的输入


在我开始编写一个函数来为可能有害的字符(如或)执行此操作之前;或者在不分析代码的情况下,我可以告诉您,您很可能忽略了攻击者可以用来注入自己代码的内容

这里的主要威胁是——在将数据插入数据库时不需要进行清理。您可以使用参数化查询,也可以正确编码数据库查询语言在进入数据库时赋予其特殊含义的字符,例如“字符”。XSS通常是通过在输出点进行编码来处理的,但是如果您想要允许富文本,那么您需要采取一种不同的方法,我相信您希望在这里实现这一点

请记住,没有神奇的功能可以以通用的方式净化输入-这在很大程度上取决于如何以及在何处使用它来确定在该上下文中输入是否安全。这一点增加了,所以如果有人搜索并找到了这个答案,那么他们就会加快速度——我想你已经掌握了这一点

复杂性是安全的主要敌人。如果你不能确定你的代码是否安全,那就太复杂了,一个有足够时间的有足够动机的攻击者会找到绕过你的清理方法的方法

对此你能做些什么? 如果您想允许用户输入富文本,您可以允许用户通过自己的转换函数插入有限、安全的HTML子集,也可以允许HTML输入并通过经过测试的解决方案(如)运行内容。现在,HTML净化器不会是完美的,我相信在将来的某个时候会发现它的缺陷

如何防范?? 如果您在站点上实现了,这将阻止任何成功注入的脚本代码在浏览器中执行。请看这里。不要试图只使用这些方法中的一种——一个好的安全模型具有分层安全性,因此如果一个控件被绕过,另一个可以捕获它


确保收到的任何HTML电子邮件都不能尝试任何偷偷摸摸的方法来发起XSS攻击。

标准的输入清理方法?没有。当有人使用“净化”这个词时,10次中有9次——他们做了错事或至少被误导了。这个问题似乎也被误导了。所以。。。为什么不直接使用htmlentities呢?它不正是你想要它做的吗?一定要使用ENT_引号。你走的路完全错了。当然,有时候按摩你的输入不是很有意义。但大多数时候你需要做的是对输出进行正确编码。如果只是将其存储在数据库中,稍后再显示。然后1对输入使用准备好的查询,2使用“转义”htmlentities’在输出上。一切都会好的。如果你必须解释输入,那么一些“消毒”和“验证”是必不可少的。@cake:事实上,我喜欢这样看,你只关心你的输出。我更喜欢将存储在数据库中视为将输出发送到应用程序以外的系统,在本例中,应用程序恰好是数据库。这是你将一直做的事情。通常,当您需要验证或过滤时,您只需处理实际输入,例如从信用卡号中去掉空格,但这种情况并不常见。
function santitize_data($data)    {
//explode the string
//do a replacement for each character separately. Only do one replacement.
//dont do it with preg_replace because that function searches through a string in multiple passes 
//and replaces already-replaced characters, resulting in horrific mishmash.
//put it back together with + signs iterating through array variables   

$patterns = array();
$patterns[0] = "'";
$patterns[1] = '"';
$patterns[2] = '!';
$patterns[3] = '\\';
$patterns[4] = '#';
$patterns[5] = '%';
$patterns[6] = '&';
$patterns[7] = '$';
$patterns[8] = '(';
$patterns[9] = ')';
$patterns[10] = '/';
$patterns[11] = ':';
$patterns[12] = ';';
$patterns[13] = '|';
$patterns[14] = '<';
$patterns[15] = '>';
$patterns[16] = '{';
$patterns[17] = '}';

$replacements = array();
$replacements[0] = '&#39;';
$replacements[1] = '&#34;';
$replacements[2] = '&#33';
$replacements[3] = '&#92;';
$replacements[4] = '&#35;';
$replacements[5] = '&#37;';
$replacements[6] = '&#38;';
$replacements[7] = '&#36;';
$replacements[8] = '&#40;';
$replacements[9] = '&#41;';
$replacements[10] = '&#47;';
$replacements[11] = '&#58;';
$replacements[12] = '&#59;';
$replacements[13] = '&#124;';
$replacements[14] = '&lt;';
$replacements[15] = '&gt;';
$replacements[16] = '&#123;';
$replacements[17] = '&#125;';

$split_data = str_split($data);

foreach ($split_data as &$value) {
    for ($i=0; $i<17; $i++){
        //testing
        //echo '<br> i='.$i.' value='.$value.' patterns[i]='.$patterns[$i].' replacements[i]='.$replacements[$i].'<br>';
        if ($value == $patterns[$i]) { 
            $value = $replacements[$i];
            $i=17;    }    }    }
unset($value); // break the reference with the last element

$data = implode($split_data);

//a bit of commented out code .. was using what seemed more logical before ... preg_replace .. but it parses the string in multiple passes ):
//$data = preg_replace($patterns, $replacements, $data);

return $data;

} //---END function definition of santitize_data