10

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

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

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

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

4

8 回答 8

15

使用准备好的语句而不是混合语句和实际的有效负载数据。

您可能还对http://shiflett.org/articles/sql-injectionhttp://shiflett.org/blog/2007/sep/the-unexpected-sql-injection感兴趣

于 2009-02-13T00:45:47.427 回答
8

没有人相信!

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

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

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

使用准备好的语句

于 2009-02-13T01:14:31.600 回答
1

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

编辑:

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

于 2009-02-13T00:42:47.540 回答
1

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

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

$age = (int)$age;

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

于 2009-02-13T00:50:11.923 回答
1

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

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

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

于 2009-02-13T01:14:49.180 回答
0

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

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

“从用户名中选择 * 用户名 = '$USERNAME';”

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

在 perl 你可以说类似

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

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

于 2009-02-13T00:50:21.673 回答
0

经过一些实验,我为完全干净的 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;

        }

    }

这个函数是我自己的数据库驱动程序的一部分。

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

于 2021-01-20T05:25:58.023 回答
-1

在我尝试在任何代码(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);
}
于 2009-02-13T01:05:31.870 回答