我不了解SQL注入及其工作原理。当您拥有用户输入的信息时,我首先开始阅读它,并且您从数据库中选择数据,其中输入的信息与数据库中的信息匹配。例如:
SELECT email FROM users WHERE username=?
现在,我知道你设置了一个参数,我能够成功地完成它,但是,我不明白是否可以从" SELECT电子邮件"中注入SQL。部分,想象电子邮件是一个可以破坏数据库的字符串,不应该是一个问题吗?如果是这样,有没有解决方法呢?
我希望我能得到很好的解释,我的英语不是最好的,但如果你有一些,我可以提出你的问题。此外,我确实试图搜索这个但是不太确定如何把它用于单词,所以我没有找到类似于这个的问题。
答案 0 :(得分:2)
对(真实)问题完全公平,我不是为了获得回报,而是回答这个问题。
“想象电子邮件是一个可以破坏数据库的字符串”
现在,电子邮件是“您”选择的列,而不是用户/输入选择的列,如果有的话。如果没有用户干预,那么您可以使用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%的情况下命名列。