【问题标题】:MySQL injection protection and vulnerability signs using PHP [duplicate]使用PHP的MySQL注入保护和漏洞标志[重复]
【发布时间】:2010-10-07 08:27:07
【问题描述】:

防止 MySQL 注入的最佳方法是什么?我应该注意哪些弱点?

我知道它是什么,但我真的不知道我可能有多脆弱。尽管我已采取(我认为的)措施来保护自己和我的数据库。

有什么可靠的方法可以阻止某人吗?

顺便说一句...我用 PHP 编写:)

【问题讨论】:

    标签: php mysql database sql-injection


    【解决方案1】:

    经过一些实验,我为完全干净的 SQL 注入创建了两个函数。与准备好的语句搭配使用,效果完美。

    
        // Cleanup outer SQL
        protected static function escapeOuter( string $s ): string {
    
            return preg_replace(
    
                    ['/(\/\*\s*\w*\s*(?!.\/\*))/si', '/(\-\-\s*\w*\s*(?!.\-\-))/si', '/(or\s*\w*\s*=\s*\w(?!.*or)|\|\|\s*\w*\s*=\s*\w(?!.\|\|))/si'], 
    
                    [';', ';', ''],
    
                    str_replace(
    
                        [ '+--', '--+', '"', "\x1a", '%', 'qq ', '--', '/*!',],  
    
                        [ '', ';', '"', '\\Z', "\%", '--', '/*!'], 
    
                        trim( $s )
    
                    )
    
            );
    
        }
    
        // Cleanup inner SQL
        protected static function innerEscape( string $v ): string {
    
            // Secure stage means that inner SQL clauses fixed to be secure
            $secureStage = str_ireplace(
    
                ['ASCII', 'UNION', ' OR ', '||', ' AND ', '&&', ' ON ', "'", '+--', '--+', 'qq', '"', '--', '/*!', ], 
    
                ['', '', ' or ', ' || ', ' and ', ' && ', ' on ', '\'', '', ';', '', '"', '--', '/*!'],
    
                addslashes(
    
                    htmlspecialchars( $v )
    
                )
    
            );
    
            // Not available to use built in escape future when DB connection not established
            if( isset( self::$dbx_lnk[ 1 ] ) ) {
    
                if( (bool)self::$dbx_lnk[ 1 ]['CONNECTION'] ) {
    
                    return mysqli_real_escape_string( self::$dbx_lnk[ 0 ], $secureStage ); 
    
                }
                else {
    
                    return $secureStage;
    
                }
    
            }
            else {
    
                return $secureStage;
    
            }
    
        }
    
    

    这个函数是我自己DataBase driver的一部分。

    例如,您必须使用 innerEscape 未来来清理字段值,而使用 escapeOuter 未来来清理完整的 MySQL 查询。过滤后必须使用 PDO 或 MySQLi 的预处理语句。

    【讨论】:

      【解决方案2】:

      这似乎是常识,但我有一段时间被绊倒了。

      编码 htmlentities()转义 mysql_real_escape_string() 之间存在差异。我认为它们是可以互换的。然而,没有......常识会告诉你。 :) 通常最好同时应用它们,例如先编码,然后转义。

      然后,当拉出数据时,反向过程,取消转义(如果需要)然后取消编码。请注意,具体执行(和反转)步骤的方式将避免很多麻烦和双重逃避的麻烦。

      【讨论】:

        【解决方案3】:

        不要相信任何人!

        根据数据类型清理所有输入——filter_var() 或正则表达式或in_array() 的有效值或混合策略。

        “输入”是指您不直接控制的任何输入源——不仅仅是表单!

        对您从$_GET$_POST$_SESSION$_COOKIE 返回的任何东西进行消毒——任何可能被污染的东西。

        使用准备好的语句

        【讨论】:

        • $_SESSION?这些数据不是在服务器上存储、写入和读取的吗?
        • 是的。而且很多网站都在托管的共享服务器上……不相信任何人。
        【解决方案4】:

        在我尝试在任何代码(MySQL 查询、数据显示等)中使用它之前,我在所有输入上都使用了这个 PHP 函数。它可能还不完整,但它应该会阻止所有入侵系统的基本尝试:

        //$linkID is the link ID of the connection to the MySQL database
        function clean_input($input)
        {
            GLOBAL $linkID;
            if(get_magic_quotes_gpc())
            {
                //Remove slashes that were used to escape characters in post.
                $input = stripslashes($input);
            }
            //Remove ALL HTML tags to prevent XSS and abuse of the system.
            $input = strip_tags($input);
            //Escape the string for insertion into a MySQL query, and return it.
            return mysql_real_escape_string($input,$linkID);
        }
        

        【讨论】:

          【解决方案5】:

          如果您没有使用为您提供清理工具的框架 PHP 有一个内置的字符串转义器,您应该从那里开始。您可以在 within the PHP docs for mysql real escape string 上找到文档。如果您查看示例 3,您会很好地了解可以遵循的基础知识。

          我遵循的另一种方法是确保在适当的位置转换变量。例如,如果我希望用户的输入是整数,我将执行以下操作:

          $age = (int)$age;
          

          此外,如果一列应该被限制为一个或两个值(例如性别列),请确保在将其放入数据库之前在 PHP 中强制执行。

          【讨论】:

            【解决方案6】:
            【解决方案7】:

            您可能遇到问题的迹象是直接接受用户输入并将其放入您的 SQL 命令中。

            例如,您询问他们的用户名。如果你拿着它然后简单地说

            "Select * From Users Where Username = '$USERNAME';"

            然后用户可以添加“JOE'; Drop Table...”等等。

            在 perl 中你可以这样说

            my $sth2 = $dbh->prepare("Insert Into HostList (HostName,PollTime,Status) values (?,?,?);");
            $sth2->execute($Hostname,$myDate,$Status);
            

            execute 方法然后会寻找上述漏洞利用并正确转义。

            【讨论】:

              【解决方案8】:

              您必须清理所有输入。 如何做到这一点取决于您使用的编程语言和/或框架。

              编辑:

              如果您使用 php,您正在寻找的函数是 mysql_real_escape_string($string)。您应该在从客户端收到的所有应该进入数据库的内容上使用它。

              【讨论】:

              • 除非绝对无法避免,否则切勿使用转义。转义函数可能并且曾经是错误的,允许注入通过。 DB 实现者几乎不可能在参数化语句中犯这样的错误,因此它们更可靠。
              • 话虽如此,如果你必须使用转义(意味着 mysqli_* 无论出于何种原因都不可能),mysql_real_escape_string 确实是要走的路。
              猜你喜欢
              • 2013-02-19
              • 2011-06-10
              • 1970-01-01
              • 1970-01-01
              • 2019-05-25
              • 2014-12-19
              • 2014-10-13
              • 2014-11-14
              • 1970-01-01
              相关资源
              最近更新 更多