注意::这不是关于什么是 SQL Injection的问题,而是一个问题,是要弄清实际的漏洞是什么,尤其是经过一些特定的测试之后案例。
背景:请参阅名为 Modern Rouge 的小组的this video。或者,您可以忽略它,因为对于没有技术技能并且还不熟悉SQL Injection的人来说,它过于简单了。我将在需要时指出我们的重要部分。
因此,对于那些不知道什么是SQL注入的人(我只是为了完整性起见,并为我的特定问题提供背景知识),假设我有这样的PHP代码:
$query = "SELECT * FROM users WHERE username='$username'";
此代码容易受到攻击,因为假设一个恶意的最终用户将其用户名输入为' or 1=1;--
,这可能会导致最终查询
SELECT * FROM users WHERE username='' or 1=1;--'
没有预期的效果。
因此,现在观看the 4:00 mark周围的视频。
他们在测试网站上给出的SQL注入示例,他们使用SQL注入绕过密码检查。
这是我没有得到的,在现实生活中,我是否会检查PHP中的密码,从而使此特定示例无效?例如:
if($userRecordFromDB["pwd"] == $pwd) { // User authenticated.
我对吗,SQL注入不能绕过我的PHP身份验证?这里的漏洞是什么?除非我将密码检查附加到查询中(我承认本示例中可能已经完成),否则即使我有一个易受攻击的查询,我的网站也不会受到攻击。
第二个相关问题:视频继续暗示单个漏洞可能允许攻击者访问我的整个数据库!我假设他们的意思是攻击者可以这样做:
SELECT * FROM users WHERE username='' or 1=1; SELECT * FROM creditInformationTable where 1=1--'
$username
当然是' or 1=1; SELECT * FROM creditInformationTable where 1=1--
但是,这也使我感到困惑。除非我将这些数据放入一个漂亮的表中或为它们存储的东西,否则即使查询易受攻击,数据也永远不会离开后端?除非我不经意间给了他们,他们怎么可能得到这些信息?
哪个使我想到了一个更大的问题:SQL注入的危险是什么?纯粹是理论上的,还是在实际情况下攻击者可以通过纯SQL注入执行诸如登录或访问数据库中所有表之类的操作?
修改:全部完成。让我缩小一点。
它如何离开后端?即使有什么问题出了错,我的攻击者也将如何得到它?诸如PDO和SQLI之类的DB API将信息返回给PHP,否返回结果页面。编写良好的PHP脚本不应该发现错误的数据,或者至少不将其全部回显给用户?
答案 0 :(得分:4)
SQL注入不是理论上的。几乎每个月都有关于使用SQL注入进行真实数据泄露的新闻报道。有一个很棒的网站可以收集它们:https://codecurmudgeon.com/wp/sql-injection-hall-of-shame/
这是上个月的好人:
https://motherboard.vice.com/en_us/article/vba5nb/fornite-login-hack-epic-games-website
Epic Games网站上的错误允许黑客登录到任何“ Fortnite”玩家的帐户
...
根据Check Point研究人员的说法,该页面现已离线,其中包含两个漏洞,这些漏洞通常在网站上发现:SQL注入(或SQLi)和跨站点脚本(或XSS)。
关于您给出的示例,我建议您验证应用程序代码中的密码。然后,您可以区分“未找到帐户”与“未找到帐户,但密码错误”(您不想向用户透露此密码,但是您可能希望记录错误,并且如果他们将其锁定,则可以锁定该帐户尝试密码失败的次数过多。
但是无论如何,SQL语句容易受到SQL注入的攻击。不仅可以使用显示的“ 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(),攻击者甚至可以将多行中的多列放在一起。 而且他们做到了。他们可能要花几次尝试才能使攻击查询的位置和位置的列数正确,但是显然他们没有更好的事情要做。