【问题标题】:The ultimate clean/secure function终极清洁/安全功能
【发布时间】:2011-05-12 13:25:06
【问题描述】:

我有很多来自$_GET$_POST 的用户输入...目前我总是写mysql_real_escape_string($_GET['var'])..

我想知道您是否可以立即创建一个保护、转义和清理 $_GET/$_POST 数组的函数,这样您就不必在每次处理用户输入时都处理它等等。

我在想一个函数,例如cleanMe($input),在它里面,它应该做mysql_real_escape_stringhtmlspecialcharsstrip_tagsstripslashes(我认为这就是让它干净和安全的全部内容) 然后返回$input

那么这可能吗?制作一个适用于所有$_GET$_POST 的函数,所以你只需要这样做:

$_GET  = cleanMe($_GET);
$_POST = cleanMe($_POST);

所以在你以后的代码中,当你使用例如 $_GET['blabla']$_POST['haha'] 时,它们是安全的、剥离的等等?

试了一下自己:

function cleanMe($input) {
   $input = mysql_real_escape_string($input);
   $input = htmlspecialchars($input, ENT_IGNORE, 'utf-8');
   $input = strip_tags($input);
   $input = stripslashes($input);
   return $input;
}

【问题讨论】:

  • stripslashes() 之后 mysql_real_escape_string() ...我的眼睛!
  • 我认为数据安全取决于他们做什么以及他们来自哪里。不一定需要您的所有治疗。
  • 使用一次性主清理功能不是正确的解决方案。这就是magic quotes 失败的原因。逃避(或使用更好的解决方案,如准备好的语句)如果和何时你需要它。否则,你会发现你在错误的时间逃跑,而且往往不止一次。所有这些函数都有非常不同的用途,其中几个(例如mysql_real_escape_stringstripslashes)本质上是相反的。请参阅 [使用 PHP 清理用户输入的最佳方法是什么? ](stackoverflow.com/questions/129677) 了解更多信息。
  • 哇哇,cleanMe() 不会停止所有 xss,也不会因为 stripslashes() 而停止 sqli。这是代码很痛苦。

标签: php security xss sql-injection


【解决方案1】:

通用卫生功能的想法是一个错误的概念。

一种适合各种用途的正确卫生方法。在字符串上不加选择地运行它们通常会破坏它 - 为 SQL 查询转义一段 HTML 代码会破坏它以在网页中使用,反之亦然。应使用数据之前应用卫生设施:

  • 在运行数据库查询之前。正确的卫生方法取决于您使用的图书馆;它们列在How can I prevent SQL injection in PHP?

  • htmlspecialchars() 用于安全的 HTML 输出

  • preg_quote() 用于正则表达式

  • escapeshellarg() / escapeshellcmd() 用于外部命令

  • 等。等等。

使用“一刀切”的卫生功能就像在植物上使用五种剧毒杀虫剂,根据定义,这种杀虫剂只能含有一种虫子 - 只是发现你的植物被第六种虫害,任何杀虫剂都不起作用。

始终使用一种正确的方法,最好是在将数据传递给函数之前直接使用。 除非需要,否则不要混合方法。

【讨论】:

  • 我们已经通过 magic_quotes 完成了“自动卫生”。再也不会了。
  • @Mchl +1 这可能是 PHP 解决方案不安全的第一个原因。它基本上鼓励了程序员的无知:)
  • 我要补充一点,使用准备好的语句(PDO 或 mysqli)代替数据库查询是非常值得考虑的。
  • +1 你一针见血,漏洞完全取决于数据的使用方式。
  • @Toby 如果您认为适合否决有效(顺便说一句,接受)答案,因为您不喜欢它的用词选择,那么这当然是您的特权。但我个人认为这很愚蠢。
【解决方案2】:

简单地通过所有这些函数传递输入是没有意义的。所有这些功能都有不同的含义。通过调用更多的转义函数,数据不会变得“更干净”。

如果你想在 MySQL 中存储用户输入,你只需要使用mysql_real_escape_string。然后将其完全转义以安全地存储在数据库中。

编辑

还要注意使用其他功能时出现的问题。例如,如果客户端向服务器发送一个用户名,并且该用户名包含一个 & 符号 (&),那么您不希望在将其存储到数据库之前调用 htmlentities,因为这样数据库中的用户名将包含&.

【讨论】:

    【解决方案3】:

    您正在寻找filter_input_array()。 但是,我建议仅将其用于业务风格的验证/清理,而不是 SQL 输入过滤。

    为了防止 SQL 注入,请使用带有 mysqliPDO 的参数化查询。

    【讨论】:

      【解决方案4】:

      问题是,清洁或安全的东西用于一种用途,不会用于另一种用途:清理路径的一部分、mysql 查询的一部分、html 输出(如 html、javascript 或输入的value),因为 xml 可能需要不同的东西,这些东西相互矛盾。

      但是,可以做一些全球性的事情。 尝试使用filter_input 来获取用户的输入。并使用 prepared statements 进行 SQL 查询。

      尽管您可以创建一些类来管理您的输入,而不是一个全能功能。类似的东西:

      class inputManager{
        static function toHTML($field){
          $data = filter_input(INPUT_GET, $field, FILTER_SANITIZE_SPECIAL_CHARS);
          return $data;
        }
        static function toSQL($field, $dbType = 'mysql'){
          $data = filter_input(INPUT_GET, $field);
          if($dbType == 'mysql'){
            return mysql_real_escape_string($data);
          }
        }
      }
      

      在这种情况下,如果您在代码中看到任何 $_POST、$GET、$_REQUEST 或 $_COOKIE,您就知道必须对其进行更改。如果有一天您必须更改过滤输入的方式,只需更改您创建的类即可。

      【讨论】:

        【解决方案5】:

        如果您使用的是 apache 并且可以完全访问服务器,我可以建议安装“mod_security”吗?!
        它确实解决了我的大部分问题。但是不要只依赖一两个解决方案,始终编写安全代码;)
        更新 找到了这个 PHP IDS (http://php-ids.org/);看起来不错:)

        【讨论】:

        【解决方案6】:
        <?php
        function sanitizeString($var)
        {
            $var = stripslashes($var);
            $var = strip_tags($var);
            $var = htmlentities($var);
            return $var;
        }
        
        function sanitizeMySQL($connection, $var)
        {
            $var = $connection->real_escape_string($var);
            $var = sanitizeString($var);
            return $var;
        }
        ?>
        

        【讨论】:

          【解决方案7】:

          我使用了传递数组或获取,发布

          function cleanme(&$array)
          { 
           if (isset($array))
           {
               foreach ($array as $key => $value)
               {
                    if (is_array($array[$key]))
                    {
                     secure_array($array[$key]);
                    }
                    else 
                    {
                      $array[$key] = strip_tags(mysql_real_escape_string(trim($array[$key])));
                    }
               }
           }
          }
          

          用法:

          cleanme($_GET);   
          cleanme($_POST);
          

          【讨论】:

          • this 的返回类型是什么
          • 数组是通过引用传递的,所以直接修改,不返回数据,会更新答案。
          猜你喜欢
          • 2010-10-01
          • 2011-06-22
          • 1970-01-01
          • 2011-09-16
          • 2015-03-03
          • 2011-06-08
          • 2015-11-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多