php - SQL - SQL 注入(inject)的真正危险是什么?

标签 php mysql sql-injection

NOTE: This is not a question about what is SQL Injection, but rather a question to clear up what the actual vulnerability, particularly given some specific test cases.

Background: Please see this video by a group called Modern Rouge. Or, you can ignore it, as it's kind of oversimplified for people who don't have technical skills and aren't already familiar with SQL Injection. I will point our the important part when it's needed.

所以,对于那些不知道什么是 SQL 注入(inject)的人(我只是为了完整性而添加这个,并为我的特定问题提供背景),假设我有这样的 PHP 代码:

$query = "SELECT * FROM users WHERE username='$username'";

这段代码很容易受到攻击,因为假设恶意最终用户将他们的用户名输入为 ' 或 1=1;--,这可能会导致最终查询

SELECT * FROM users WHERE username='' or 1=1;--'

这没有达到预期的效果。

那么,现在观看有关 the 4:00 mark 的视频.

他们在测试网站上给出的 SQL 注入(inject)示例,他们使用 SQL 注入(inject)来绕过密码检查。

这是我不明白的,在现实生活中,我不会改为在 PHP 中检查密码,从而使这个特定示例变得毫无用处吗?例如:

if($userRecordFromDB["pwd"] == $pwd) { // User authenticated.

SQL 注入(inject)无法绕过我的 PHP 身份验证,我说得对吗?这里的漏洞是什么?除非我将密码检查与我的查询相关联(我承认本示例可以这样做),否则即使我有易受攻击的查询,我的网站也不应该易受攻击。

第二个相关问题:视频继续暗示单个漏洞可能允许攻击者访问我的整个数据库!我假设他们的意思是攻击者可以做这样的事情:

SELECT * FROM users WHERE username='' or 1=1; SELECT * FROM creditInformationTable where 1=1--'

$username 当然是 ' 或 1=1; SELECT * FROM creditInformationTable where 1=1--

然而,这也让我感到困惑。除非我将这些数据放入一个漂亮的表或其他东西中,否则数据不会永远不会离开后端,即使查询是易受攻击的吗?除非我不小心给了他们这些信息,否则他们怎么可能得到这些信息?

这让我想到了一个更大的问题:SQL 注入(inject)的危险是什么?这纯粹是理论上的,还是存在攻击者可以通过纯 SQL 注入(inject)执行登录或访问数据库中的所有表等操作的真实案例?

编辑:从头开始。让我缩小一点。

它如何离开后端?即使某些东西查询了错误的东西,我的攻击者怎么会得到它? PDO 和 SQLI 等数据库 API 将信息返回给 PHP,不是结果页面。一个编写良好的 PHP 脚本难道不应该捕捉到错误的数据,或者至少不应该将其全部回显给用户吗?

最佳答案

SQL 注入(inject)不是理论上的。几乎每个月都有关于使用 SQL 注入(inject)实现的真实数据泄露的新闻报道。有一个收集它们的好网站:https://codecurmudgeon.com/wp/sql-injection-hall-of-shame/

这是上个月的一个不错的:

https://motherboard.vice.com/en_us/article/vba5nb/fornite-login-hack-epic-games-website

Bugs on Epic Games Site Allowed Hackers to Login to Any ‘Fortnite’ Player’s Account

...

That page, which is now offline, contained two vulnerabilities that are often found in websites: an SQL Injection (or SQLi), and a Cross-Site Scripting (or XSS), according to Check Point researchers.

关于您提供的示例,我确实建议在应用程序代码中验证密码。然后你可以区分“找不到帐户”和“找到帐户,但密码错误”(你不想向用户透露这个,但你可能想记录错误,如果他们可能会锁定帐户密码尝试失败次数太多)。

但无论如何,SQL 语句容易受到 SQL 注入(inject)攻击。不仅使用您展示的“OR 1=1”技巧,而且如果您可以欺骗查询运行基于 UNION 的 SQL 查询:

$query = "SELECT * FROM users WHERE username='' UNION ALL SELECT * FROM INFORMATION_SCHEMA.TABLES -- '";
                                              ^^ $username ...

如果攻击者可以在您的应用程序中找到 SQL 查询(不一定是按帐户名搜索),他们就可以使用此技术来查询您的所有表。然后他们可以进一步使用 UNION 技术来查询所有表中的数据,一旦他们知道他们的名字。


关于您的后续问题:

“数据如何离开后端?”

考虑一下您的密码检查代码(针对上述查询)是否如下所示:

$query = "SELECT id, username, password_hashed FROM users WHERE username='$username'";

$stmt = $pdo->query($query);
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
  if (!password_verify($password, $row['password_hashed'])) {
    die("Invalid login for user {$row['username']}");
  }
}

看到了吗? SQL 查询的结果输出给用户。对于此代码的开发人员来说,很明显,因为他们只是查询了 $username,所以这就是查询将返回的值。他们认为 $row['username'] 可以安全使用。

但它不是——它是来自 UNION 另一部分的一些数据。通过使用 CONCAT() 和 GROUP_CONCAT(),攻击者甚至可以将多行的多列放在一起。 他们确实这样做了。他们可能需要多次尝试才能让他们的攻击查询在正确的位置有正确数量的列,但他们显然没有更好的事情可做。

关于php - SQL - SQL 注入(inject)的真正危险是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54917328/

相关文章:

php - 如何在 codeigniter 中使用 find_in_set 和 join

php - PDO 错误 : General error: 2031

mysql - 这个create table哪里出错了?

php - 如何防止 PHP 中的 SQL 注入(inject)?

php - 如何使用 PHP 设置自动提醒邮件?

php - MySQL 从 3 个表中选择并将其放入 PHP 数组中

php - 如何传递ajax返回值php变量

mysql - 用于获取表列数的 hibernate 查询

Java - 转义字符串以防止 SQL 注入(inject)

php - 我可以在prepare()函数中连接字符串以插入到指定的表中吗