【问题标题】:Prepared statement security while fetching获取时准备好的语句安全性
【发布时间】:2013-10-02 02:29:24
【问题描述】:

我只是不明白。在获取数据方面,准备好的语句比未准备好的语句更安全。我不是在谈论写入数据库,只是在获取数据。我看不出 userFname 和 userLname 比 userEmail 和 userPassword 更安全。提前致谢。

$stmt = $mysqli->stmt_init();
    if ($stmt->prepare("SELECT userFname, userLname FROM users WHERE userEmail = ? and userPassword = ?")) {
        $stmt->bind_param("ss", $userEmail, $userPassword);
        $stmt->execute();
        $stmt->bind_result($userFname, $userLname);
        while ($stmt->fetch()) {
            //Remember first name, last name, and email
            $_SESSION['Email']=$userEmail;
            $_SESSION['Fname']=$userFname;
            $_SESSION['Lname']=$userLname;
            $stmt->close();
            //go to dashboard page
            header ("location: dashboard.php");    
        }
        $error2="Email and Password do not match, please try again."; 
    }

【问题讨论】:

  • SQL 注入只是利用不正确转义的变量来修改您的查询。即使您不向数据库写入任何内容,它们仍然可能发生。
  • 使用准备好的语句是否更安全。它没有绑定,即使在准备好的语句中也是如此。

标签: mysqli sql-injection


【解决方案1】:

SQL注入领域有一座巨大的巴比伦塔。

每个人都在使用十几个词,几乎不理解它们的意思,更糟糕的是——对意思完全有自己的想法。

示例: 99% 的 PHP 用户会告诉您数据必须“转义”。虽然技术上的逃逸是一种非常特殊的动作,但在一种情况下不足以提供保护,而在另一种情况下无用和有害。

“清理”、“过滤”、“转义”、“准备好的语句”等列表中的所有其他单词也是如此。

因此,形象地说,每次谈话都会变成盲人和聋人之间的争论。

完全相同适用于名为 "input input" 的东西。这是另一个造成许多混乱和 - 更糟糕的是 - 漏洞的来源。而在其最明显的含义中,它与 SQL 注入完全无关

因此,阅读来自不同网站的建议时请记住,您必须了解术语,并且 - 不仅如此 - 了解作者的意思。

回到你的问题,答案很简单:

  1. 准备好的语句必须用于动态进入查询的一切
  2. 对于无法使用准备好的语句的情况,必须使用白名单代替。

这些规则很容易记住。所以 - 不要在其中添加任何复杂性! 不要用诸如“这些数据来自哪里?”之类的问题困扰自己。 “它在什么查询中进行?” - 它们没有用而且容易出错。

遵守这些规则并不容易,但这是另一个话题。

【讨论】:

  • ("SELECT userFname FROM users WHERE userEmail = ?")...太棒了!所以修剪所有输入,将 userFname 列入白名单(FILTER_SANITIZE_EMAIL - 删除除字母、数字和 !#$%&'*+-/=?^_`{|}~@.[] 之外的所有字符。不用担心 userEmail 然后htmlspecialchars() 用于所有输出。希望我做对了。谢谢!
【解决方案2】:

我是一名 MySQL 培训讲师。我正在向一群与会者讲述 SQL 注入的风险,其中一个人说,“告诉我”。

他递给我他的笔记本电脑,它的浏览器打开了他网站的登录屏幕(实际上它只是一个 QA 实例)。

对他的代码或数据库一无所知,我做出了一个有根据的猜测,他有一个像你这样的 SQL 查询,他没有使用查询参数,而且他没有正确地转义输入。我输入了一个用于登录的字符串,包括右引号和一些布尔表达式,然后我输入了随机击键作为密码。

他的应用程序验证了我的虚假登录,而我进入了。

我认为向您展示我是如何做到的并不合适,但这不是火箭科学——您只需要了解布尔代数的最低限度。

但重点是 SELECT 查询的 SQL 注入可以允许非法操作,就像修改数据的语句的 SQL 注入一样。


关于不良信息的建议:

查询参数确实不能被欺骗,也没有必要使用转义函数。

但查询参数仅在您通常使用单个字符串、日期或数字文字的地方起作用。查询参数不能用于动态表名、列名、值列表、SQL 关键字、表达式等。对于这些,您仍然需要将应用程序变量插入到 SQL 查询中在调用 prepare 之前 (),就像老式的、不安全的编程一样。因此,您仍然需要小心避免 SQL 注入漏洞。最好的方法是在将内容包含在 SQL 查询中之前将其列入白名单

查看我的演示文稿SQL Injection Myths and Fallacies 了解更多信息,或查看webinar of me presenting it(免费,但需要注册)。我还在我书中的一章SQL Antipatterns: Avoiding the Pitfalls of Database Programming 中写过关于 SQL 注入的文章。

【讨论】:

  • 我正在使用prepared statements 写入数据库,但我仍然需要使用prepared statements 来获取数据?谢谢。
  • 正如比尔提到的,您需要清理输入,无论是写入还是获取。在他的情况下,登录是检索数据(选择用户和密码是否正确,不需要写入数据库),但在这种情况下,他可以在没有正确用户和密码的情况下登录。
  • 许多编程网站说使用准备好的语句时不需要清理用户输入,但就像你们俩所说的那样,事实并非如此。许多像我这样的人在使用准备好的语句时可能会有一种错误的安全感。谢谢
  • 一个坏信息的例子:一个快速的谷歌搜索出现了这个; 使用以下步骤中的方法,您将不需要使用任何其他 SQL 注入过滤技术,例如 mysql_real_escape_string()。这是因为使用准备好的语句不可能进行常规的 SQL 注入。
  • user2734634:大多数网站作者都不知道。记住这一点。另外,一般人对“消毒”、“过滤”、“转义”、“准备好的陈述”等词一无所知,将它们视为一个(这显然是错误的)但每个都有自己的含义。以@rcs 的评论为例:他说“清理”,而准备好的语句不是“清理”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-21
  • 2012-08-12
  • 1970-01-01
  • 2012-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多