在Select X语句中防止SQL注入

时间:2017-01-01 23:50:59

标签: php mysql sql-injection

我不了解SQL注入及其工作原理。当您拥有用户输入的信息时,我首先开始阅读它,并且您从数据库中选择数据,其中输入的信息与数据库中的信息匹配。例如:

SELECT email FROM users WHERE username=?

现在,我知道你设置了一个参数,我能够成功地完成它,但是,我不明白是否可以从" SELECT电子邮件"中注入SQL。部分,想象电子邮件是一个可以破坏数据库的字符串,不应该是一个问题吗?如果是这样,有没有解决方法呢?

我希望我能得到很好的解释,我的英语不是最好的,但如果你有一些,我可以提出你的问题。此外,我确实试图搜索这个但是不太确定如何把它用于单词,所以我没有找到类似于这个的问题。

3 个答案:

答案 0 :(得分:2)

对(真实)问题完全公平,我不是为了获得回报,而是回答这个问题。

As per a comment I left:

“想象电子邮件是一个可以破坏数据库的字符串”

现在,电子邮件是“您”选择的列,而不是用户/输入选择的列,如果有的话。如果没有用户干预,那么您可以使用SELECT email FROM table而没有任何问题。

您是否使用过SELECT $email并使用GET / POST数组定义它并没有将其转义(注意:您无法绑定表/列,请参阅脚注),然后可能会执行一些操作它,但你可以使用MySQLi的real_escape_string()函数或使用安全列表来逃避它,你只是不能用准备好的语句,句号。

SELECT ? FROM ? // is not allowed/not supported in any prepared statement API

但是,如果查询不涉及某个形式的WHERE子句,其中该变量未被转义,那么它确实可以被操纵,但只需要一个简单的{{1}就可以感觉到它是最小的但是,这仍然不足以造成任何伤害。

<强>脚注:

关于为什么你不能绑定表/列的相对链接,我觉得这是你真正想要实现的:

关于SQL注入:

答案 1 :(得分:1)

SQL注入是一种风险,其中不受控制的值可以成为查询的一部分。 &#39; SELECT电子邮件&#39;在此特定示例中,查询的一部分没有风险,因为电子邮件列中的值不是查询的一部分。

这是一个可怕的可怕例子:

var query = "SELECT email FROM users WHERE username = '" + userInput + "'"

在该示例中,userInput的值成为查询的一部分 - 用户可以输入&#34; Blah&#39 ;; DROP TABLE Users&#34;这不是一个美好的一天。但是,电子邮件列中的值不是查询的一部分。

答案 2 :(得分:0)

考虑到MySQL中的列名仅为very limited subset of characters(虽然请参见本答案底部的编辑),您可以很容易地连接到SQL字符串,但首先正则表达式删除无效字符,如:

//use single quotes due to dollar sign
$column = preg_replace('/[a-z_-0-9$]/i','',$_POST['column']);

然后确保它包含在引文中:

$column = ' `'.$column.'` ';

所以你可以这样做:

$sql = 'SELECT '.$column.' FROM users WHERE username=?'; 

然后将此字符串放入您的Bind查询中,这应该是完全安全的。

或者,在语句的SELECT部分中,您只需删除任何特殊字符,即*.,空格和反引号操作符。

所以你可以轻松做到:

$column = preg_replace("/[*`.\s]/","",$_POST['column']);   

这意味着查询的SELECT部分​​只能SELECT并且滥用这将导致查询失败(例如,使用两个WHERE关键字等。)

顺便说一下,让人们可以选择他们想要调用的列有很多陷阱的潜力,而且我发现它在野外非常普遍。为什么开发人员在选择选项时不清楚要选择哪些列?

编辑:你也可以使用扩展列名字符,这不应该影响这种方法,但值得注意。但是,正如我上面所说,我认为用户无论如何都应该能够在99.999%的情况下命名列。