102

有人可以解释 SQL 注入吗?它是如何导致漏洞的?SQL 的注入点到底在哪里?

4

9 回答 9

91

有人可以解释 SQL 注入吗?

当您将一些内容插入到 SQL 查询字符串中时,就会发生 SQL 注入,结果会以您不希望的方式修改查询的语法。

它不一定是恶意的,它可能是一个意外。但是意外的 SQL 注入更可能导致错误而不是漏洞。

有害内容不一定来自用户,它可以是您的应用程序从任何来源获取的内容,甚至可以在代码中自行生成。

它是如何导致漏洞的?

它可能导致漏洞,因为攻击者可以将值发送到他们知道将被插入 SQL 字符串的应用程序。通过非常聪明,他们可以操纵查询结果、读取数据甚至更改他们不应该做的数据。

PHP 中的示例:

$password = $_POST['password'];
$id = $_POST['id'];
$sql = "UPDATE Accounts SET PASSWORD = '$password' WHERE account_id = $id";

现在假设攻击者将 POST 请求参数设置为 " password=xyzzy" 和 " id=account_id" 导致以下 SQL:

UPDATE Accounts SET PASSWORD = 'xyzzy' WHERE account_id = account_id

虽然我希望$id是一个整数,但攻击者选择了一个字符串作为列的名称。当然,现在每一行的条件都为真,所以攻击者刚刚为每个帐户设置了密码。现在攻击者可以登录到任何人的账户——包括特权用户。

SQL 的注入点到底在哪里?

注入的不是 SQL,而是插入(“注入”)到 SQL 字符串中的内容,导致查询类型与我的预期不同。我信任动态内容而不对其进行验证,并盲目地执行生成的 SQL 查询。这就是麻烦开始的地方。

SQL 注入是应用程序代码中的错误,通常不在数据库或数据库访问库或框架中。

使用查询参数可以避免大多数 SQL 注入情况。请参阅如何防止 PHP 中的 SQL 注入?举些例子。

于 2009-03-02T07:31:08.453 回答
28

当应用程序的用户能够影响数据库查询的含义时,就会发生 SQL 注入。当连接来自用户输入的任意字符串以创建馈送到数据库的 SQL 时,通常会发生这种情况。例如,假设我们有以下代码(在 PHP 中,但对于任何语言都适用),它可能用于处理用户登录。

$sql = "SELECT  FROM users WHERE username='".$_GET['username']."' AND password='".$_GET['password']."'";

当用户输入类似的内容时,就会造成伤害

administrator'; --

...对于用户名。如果没有适当的编码,查询将变为:

SELECT * FROM users WHERE username='administrator'; -- AND password=''

这里的问题是用户名中的 ' 关闭了用户名字段,然后 -- 启动 SQL 注释,导致数据库服务器忽略字符串的其余部分。最终结果是用户现在无需知道密码即可以管理员身份登录。SQL Inection 也可用于执行 UPDATE、DELETE 或 DROP 查询并真正损坏数据库。

可以通过使用参数化查询或应用您的语言/工具包的转义函数(例如 PHP 中的 mysql_real_escape_string())来防止 SQL 注入。

一旦你了解了 SQL 注入,你就会明白这幅漫画背后的笑话。

于 2009-03-02T06:43:35.230 回答
14

SQL 注入是指本应是数据的事物被不情愿地视为 SQL 代码。

例如,如果你要做

mysql_query("SELECT * FROM posts WHERE postid=$postid");

通常它会给你一个给定 id 的帖子,但假设它$postid被设置为 string 10; DROP TABLE posts --;突然之间,您发送的实际查询是

mysql_query("SELECT * FROM posts WHERE postid=10; DROP TABLE posts --");

这是一个相当大的问题,因为您会因为恶意用户而丢失整个帖子表 - 天哪。

防止这种情况的最简单方法是使用准备好的语句,例如通过PDOMySQLi

PDO 中的等效示例将是

$statement = $db->prepare('SELECT * FROM posts WHERE postid = :postid');
$statement->bindValue(':postid', $postid);
$statement->execute();

这样做可以确保数据库系统知道 $postid 将被视为数据而不是代码,因此将得到适当的处理。

于 2010-05-01T00:16:40.527 回答
12

这个问题在 StackOverflow 上已经回答过很多次了,但它是每个人都知道的重要话题,所以我不会投票结束这个问题。

以下是我过去关于该主题的一些答案的链接:

我也在这个月的 MySQL Conference 上做了一个演讲,我的幻灯片在网上:

于 2010-05-01T00:13:26.300 回答
7

SQL 注入是恶意用户将 SQL 放入输入字段以尝试在您的服务器上运行 SQL 的地方。

我坚持的 #1 建议是使用参数化存储过程,而不是在代码中构建原始 SQL。

存储过程参数不会被执行,因此在大多数情况下它们是安全的。

于 2010-04-30T23:58:57.090 回答
5

我发现这篇论文是一本关于 SQL 注入技术的非常好的读物(链接是 PDF):SQL Server 应用程序中的高级 SQL 注入

尽管标题写着“高级”,但即使您对 SQL 注入了解不多,它也很容易阅读。

于 2009-03-02T04:57:20.977 回答
2

要获得一些一般背景信息,请查看关于 SQL 注入的 Wikipedia 文章

简而言之,SQL 注入攻击会使您容易受到所有数据库数据盗窃和破坏的威胁。可以对系统执行的操作的确切细节取决于系统本身的细节。

每当您将用户的输入传递到数据库时,您就有一个潜在的注入点。Web 应用程序在这方面经常缺乏,因为新程序员通常不了解处理用户输入的风险,并且 Web 应用程序会受到非常聪明的人的攻击,你从未想过会找到你的程序。

于 2009-03-02T04:58:55.513 回答
1

您会喜欢代码项目中的这篇文章;)

概括

  • 加密敏感数据。
  • 使用具有最低必要权限的帐户访问数据库。
  • 使用具有最低必要权限的帐户安装数据库。
  • 确保数据有效。
  • 进行代码审查以检查二阶攻击的可能性。
  • 使用参数化查询。
  • 使用存储过程。
  • 重新验证存储过程中的数据。
  • 确保错误消息不会泄露应用程序或数据库的内部架构。
于 2010-05-01T00:02:45.890 回答
0

注入 SQL 的点是您的应用程序接受用户输入的任何点。

这是否会成为您的 Web 应用程序的危险漏洞取决于此输入是否稍后用作 SQL 查询的一部分,而没有正确检查其类型并在必要时对其进行转义。

如果没有适当的转义,用户“注入”的某些 SQL 代码可能会被 SQL 引擎作为 SQL 代码执行,而不是简单的字符串或值。

于 2009-03-02T05:49:35.280 回答