防止仅INSERT查询的SQL注入。这是一个大问题吗?

时间:2012-02-07 00:50:37

标签: php mysqli sql-injection prepared-statement executequery

这是我第一次创建一个PHP表单,它将使用INSERT INTO运行MySQL查询,以便在生产数据库中存储数据。这会通过“安全”还是过度杀人?

$orderText = $mysqli->real_escape_string(stripslashes(htmlentities((!isset($_POST["order_text"])?"undefined":$_POST["order_text"]))));
$stmt = $mysqli->prepare("INSERT INTO testtable (order_text) VALUES (?)");
$stmt->bind_param('s',$orderText);
$stmt->execute();

我不确定缺少SELECT *会如何影响我打开自己的风险,但似乎只使用INSERT的脚本更安全。真?

4 个答案:

答案 0 :(得分:2)

您在第3行执行的变量绑定足以防止注入攻击。绑定是一个好主意,在我看来,总是完成。它不仅具有安全优势,而且还可以提高性能。

我认为在第1行执行额外的解析实际上是一个缺点: 它增加了复杂性,一些攻击利用了已知的数据转换,尽管使用绑定也可以减轻这些转换。

答案 1 :(得分:2)

你的问题中有很多错误的假设。

  1. 这当然是一种矫枉过正 让我们来看看非常难以阅读的zillion-nested-operator 语句:

    • 存储单词'undefined'毫无意义。数据库具有未定义字段的特殊标记 - NULL值。或者只是一个空字符串就足够了。
    • 无条件striplashes不会增加任何安全性,但可能破坏数据。
    • htmlentities与SQL安全无关,可能有助于其他方面的站点安全,也可能破坏数据。
    • 转义不会增加任何安全性,并会破坏数据。
  2. 你从错误的一端解决问题 您的主要目标是正确格式化查询。不要为想象中的“攻击者”辩护,而是用最诚实的数据来防止故障。虽然正确格式化的查询对于各种攻击都是无懈可击的,只是作为副作用 比方说,real_escape_string与安全性无关。它仅用于格式化字符串。查询中没有字符串(数据用引号括起来) - 因此这个函数完全没用(甚至有害)。

  3. 事实上,通过INSERT进行注入与通过SELECT进行注入同样具有灾难性。

  4. 最后,正确的代码是

    $stmt = $mysqli->prepare("INSERT INTO testtable (order_text) VALUES (?)"); 
    $stmt->bind_param('s',$_POST["order_text"]); 
    $stmt->execute(); 
    

    将订单文本打印回网站时,请使用htmlspecialchars()

    就是这样。

答案 2 :(得分:1)

我会建议将来自客户,访客的所有内容视为威胁。不要放松,只关注一些SQL查询。实践好习惯没有限制。

答案 3 :(得分:1)

我同意Charles的看法,通过绑定param,你已经正确地逃避变量,消除了SQL注入攻击的可能性,而第1行的复杂性是过度的。当你跳转到PDO时会出现这种情况,因为没有特定的$ dbo-> escape()调用,因为使用prepare()/ bind()调用已经完成了转义工作。