这种创造性的消毒方式可能会面临什么样的安全漏洞? (如果有的话)

时间:2015-02-06 20:42:42

标签: php security input

清理输入的标准方法是使用

等命令

$url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);

$strip = array('%0d', '%0a', '%0D', '%0A');

preg_replace("/[^A-Za-z0-9 ]/", '', $string);

echo htmlentities($str);

然而,当我的用户能够在他们的输入,comments / usernames / etcetc中使用诸如括号,克拉,引号等的好东西时,我喜欢。由于HTML将诸如(之类的代码呈现为(之类的符号,因此我希望使用这种替代方法来清理其输入。

在我开始为可能有害的字符(例如(;<执行此操作之前,已经开始执行此操作(因此注入诸如偷偷摸摸eval()或{{ 1}}不起作用)我试图搜索以前人们尝试进行此类消毒的尝试。

我找不到。

这让我觉得我必须清楚地忽略了我的&#34;创意&#34;中一些非常明显的安全漏洞。消毒方法。

  1. 我不会将此功能用作保护mySQL数据库的主要方法。我有新的<text/javascript>类。添加这种消毒超越了mysqli输入和输出的分离。但是查询似乎是一个好主意。
  2. 我使用完全不同的功能来清理网址。那些需要不同的方法。
  3. 此功能用于在页面上显示的用户输入。
  4. 那么......我可能会错过什么?我知道这个想法有问题,因为没有其他人使用它,对吧?!是否有可能重新渲染渲染的文本&#34;或其他可怕而明显的东西?到目前为止我的功能很少:

    • 使用mysqli或类似的输入字符串 meep';) drop table

      alert(eval('document.body.inne' + 'rHTML'));
    • 吐出结果字符串,如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 meep&#39;&#59;&#41; drop table

    • 并且用户在浏览器中看到这些呈现的内容,如alert&#40;eval&#40;&#39;document.body.inne&#39; + &#39;rHTML&#39;&#41;&#41;&#59;meep';) drop table

1 个答案:

答案 0 :(得分:2)

如果不分析您的代码,我可以告诉您,您很可能忽略了攻击者可以用来注入自己代码的内容。

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

请记住,没有神奇的功能可以通用方式清理输入 - 它在很大程度上取决于它在何种情况下用于确定在该环境中是否安全。 (如果有人搜索并找到这个答案,那么这一点就增加了,那么他们就会加快速度 - 我认为你已经掌握了这一点。)

复杂性是安全的主要敌人。如果你无法确定你的代码是否安全,那么它太复杂了,而且有充足动力的攻击者有足够的时间来找到解决方法。

你能做些什么?

如果您希望允许用户输入富文本,您可以允许BBCode允许用户通过您自己的转换函数插入有限的,安全的HTML子集,或者您可以允许HTML输入并运行内容通过经过试验和测试的解决方案,例如HTML Purifier。现在,HTML Purifier将不会是完美的,我确信将来某个时候会发现(another)缺陷。

如何防范这个?

如果在您的网站上实施Content Security Policy,这将阻止任何成功注入的脚本代码在浏览器中执行。请参阅此处current browser support for CSP。不要试图只使用这些方法中的一种 - 一个好的安全模型具有分层安全性,所以如果一个控制被规避,另一个可以捕获它。

Google have now implemented CSP in Gmail以确保收到的任何HTML电子邮件都无法尝试任何偷偷摸摸来发起XSS攻击。