你能破解这种输入消毒功能吗?

时间:2013-02-14 17:13:33

标签: php forms input sanitize

我还在学习PHP和SQL。我正在尝试为网站的事件列表创建一个简单的内容管理系统。所有输入表单字段都是文本区域或文本框(是的,我希望他们这样),我想让用户除了这些字段中的文本之外还能够添加HTML链接。以下函数似乎是开始消除用户输入的一个好地方,但由于我是新手,我想得到更多知识渊博的开发人员的意见。我还应该做些什么来尝试保护数据库?

P.S。感谢CSS-Tricks这些功能。

function cleanInput($input) {

    $search = array(
         '@<script[^>]*?>.*?</script>@si',   // Strip out javascript
         '@<style[^>]*?>.*?</style>@siU',    // Strip style tags properly
         '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments
    );

    $output = preg_replace($search, '', $input);
    return $output;
}

function sanitize($input) {
    if (is_array($input)) {
       foreach($input as $var=>$val) {
          $output[$var] = sanitize($val);
       }
    }
    else {
       if (get_magic_quotes_gpc()) {
          $input = stripslashes($input);
       }
       $input  = cleanInput($input);
   $output = htmlentities($output);
       $output = mysql_real_escape_string($input);
     }
     return $output;
}

2 个答案:

答案 0 :(得分:0)

很容易:

$testinput = "<script>alert('p0wned');</script >\n
    <a href='http://example.org' onclick=\"alert('p0Wned again!)\">Click me!</a>";

var_export(cleanInput($testinput));

此外,htmlescape几乎总是使用错误的东西 - 它会破坏utf8输入。此外,您不应该在数据库中存储html转义数据。我甚至不确定你为什么要在这里使用它 - 你不得不 unescape html来显示它吗?

然而,你的方式是错误的。

  1. 不要使用正则表达式解析/清理html。使用真正的html解析器,例如DOMDocumenthtml5lib甚至tidylib。不幸的是,PHP似乎没有像Bleach on Python那样精彩的东西,所以你必须自己动手。带有白名单的XSLT样式表似乎可能是处理这种特定清理条件的好方法。 更新:另一位用户指出HTML Purifier,这也是一个基于白名单的html清理程序。我从来没有使用它,但它看起来像“Bleach in PHP”。你一定要调查。
  2. 首选转发进行清理。 PHP文化对清理工作有一种痴迷,这实际上只是简单的错误。在应用程序边界(输出和数据库)转义数据。在您的应用程序的核心,您的数据应该是原生形式,而不会有任何转义。
  3. 处理的一般概要如下:

    1. 输入

      1. 在php设置中关闭魔术引号。在应用程序顶部添加代码,以便在启用时失败:if (get_magic_quotes_gpc()) die ('TURN OFF MAGIC QUOTES!!!!');
      2. 根据每个字段的预期类型验证并标准化/清理输入的特定字段。例如,“美元金额”具有与白名单html片段字段不同的验证标准。 (可能你应该找到并使用验证库。)
      3. 如果有错误,请使用适当的HTTP响应代码将其发回给用户。
      4. 使用支持参数绑定的数据库库将数据保存到数据库,例如带有预准备语句的PDO库。这样您就不需要记住手动转义数据了。
      5. 成功时,将(代码303)重定向到显示已创建或修改记录的页面。
    2. 输出

      1. 从数据库中检索数据。
      2. 将数据提供给模板,该模板是处理数据结构的html显示的PHP代码。它不应该知道如何检索数据或包含任何“应用程序驱动”行为的细节。将模板视为接受数据结构并返回字符串的函数。
      3. 在模板中转义 。您的数据的各个字段需要以不同方式进行转义。在输出之前,您几乎总是需要通过htmlspecialchars运行它;您这样做的唯一情况是,您需要显示的数据是已经 html(即白名单清理的html字段)。定义这样的辅助函数并在模板中使用它:

        function h($str) {
            return htmlspecialchars($str, ENT_QUOTES, 'utf-8');
        }
        

        更好的是,尝试使用自动转义字符串的模板库,这需要您明确地转换 off 转义。 (常见的情况应该是简单的,以避免错误,并且必须逃避是常见的情况!)

      4. 您的html页面是从模板返回的字符串。您现在可以将其显示给用户。

答案 1 :(得分:0)

虽然不必清理在浏览器中显示或存储在数据库中的自己的字符串数据,但必须清理您的网站通过INPUT元素,TEXTAREA元素获得的所有用户输入,从键盘通过JavaScript / DOM事件,从上传的文件以及我忘记列出的所有其他来源获取。

虽然数据库清理已得到充分证明,并且在最新版本的服务器端语言(如PHP)中得到了部分实施,但仍然没有一种普遍接受的方法来对我列出的其他用户输入资源进行清理。

我自己的贡献是这小段PHP代码,它允许任何用户输入显示在网页上,或者通过GET或POST控件以及FORM元素中的字段或通过Ajax发送到另一个网页,而无需打开您的网站来恶意使用:

function HTMLToSafeHTML($Str)
    {
    return str_replace(['&','<','>','"','\''], ['&amp;','&lt;','&gt;','&quot;','&apos;'], $Str);
    } // HTMLToSafeHTML

要正确使用此功能,必须标识并跟踪所有用户输入,然后在显示或以其他方式允许用户输入解释为Web处理或编程的一部分之前调用此功能。识别用户输入后,您只能调用一次此功能。多次调用它会显示其难以阅读的编码,这对于文本没有用。

例如,如果您要显示一条错误消息,以粗体显示一些用户输入,则必须在用户输入上调用HTMLToSafeHTML(可以给它一个较短的名称),然后再将其包含在<strong>...</strong>中,以使其大胆。虽然显示“ <strong>”是无害的,但显示用户输入却是无害的,这可能是恶意用户故意地闯入您的网站以传播病毒或其他恶魔的结果。目的。