0

这是我第一次创建一个 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

4 回答 4

2

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

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

于 2012-02-07T00:56:39.350 回答
2

您的问题中有大量错误的假设。

  1. 这当然是矫枉过正。
    让我们检查一下您极其难以阅读的 zillion-nested-operator语句:

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

  3. 事实上,通过 INSERT 注入的灾难性不亚于通过 SELECT。

最后,正确的代码是

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

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

就这样。

于 2012-02-07T03:04:22.983 回答
1

我建议将来自客户、您的访客的所有内容都视为威胁。不要放松,只关注一些sql查询。养成一个好习惯是没有限制的。

于 2012-02-07T00:54:27.470 回答
1

我同意查尔斯的观点,通过绑定参数,您已经正确地转义了变量,消除了 SQL 注入攻击的机会,并且第 1 行的复杂性是多余的。当您跳转到PDO时,这一点会很明显,因为没有特定的 $dbo->escape() 调用,因为转义工作已经通过 prepare() / bind() 调用完成。

于 2012-02-07T01:07:11.557 回答