什么是SQL注入?

时间:2009-03-02 04:50:50

标签: sql sql-injection security

  

可能重复:

     

How does the SQL injection from the "Bobby Tables" XKCD comic work?
  https://stackoverflow.com/search?q=sql+injection

有人可以解释SQL注入吗?它是如何导致漏洞的?注入SQL的确切位置在哪里?

9 个答案:

答案 0 :(得分:79)

有人可以解释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注入情况。有关示例,请参阅How can I prevent SQL injection in PHP?

答案 1 :(得分:27)

当应用程序的用户能够影响数据库查询的含义时,就会发生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注入,你就会得到this cartoon背后的笑话。

答案 2 :(得分:13)

SQL注入是指那些应该是数据的东西被不情愿地视为SQL代码。

例如,如果你要做

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

通常情况下,它会为您提供具有给定ID的帖子,但假设$postid设置为字符串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将被视为数据而不是代码,因此将被妥善处理。

答案 3 :(得分:11)

StackOverflow已经多次回答了这个问题,但这是一个让每个人都知道的重要话题,所以我不打算投票来关闭这个问题。

以下是我过去对此主题的一些回答的链接:

我本月也在MySQL大会上做了一个演讲,我的幻灯片在线:

答案 4 :(得分:6)

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

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

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

答案 5 :(得分:4)

我发现本文是关于SQL注入技术的非常好的读物(链接到PDF):Advanced SQL Injection In SQL Server Applications

尽管标题为“高级”,但即使您对SQL注入知之甚少,它仍具有可读性。

答案 6 :(得分:1)

要获得一些一般背景,请查看Wikipedia article on SQL Injection

简而言之,SQL注入攻击可能会让您容易受到数据库数据被盗和破坏的影响。可以对系统执行的操作的具体细节取决于系统本身的详细信息。

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

答案 7 :(得分:1)

您希望来自代码项目的this文章; )

  

<强>摘要

     
      
  • 加密敏感数据。
  •   
  • 使用权限最少的帐户访问数据库   必要的。
  •   
  • 使用具有最少权限的帐户安装数据库   必要的。
  •   
  • 确保数据有效。
  •   
  • 进行代码审查以检查二阶可能性   攻击。
  •   
  • 使用参数化查询。
  •   
  • 使用存储过程。
  •   
  • 重新验证存储过程中的数据。
  •   
  • 确保错误消息不会泄露内部信息   应用程序的体系结构或   数据库中。
  •   

答案 8 :(得分:0)

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

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

如果没有正确的转义,用户“注入”的一些SQL代码可以由SQL引擎作为SQL代码执行,而不是简单的字符串或值。