什么是 SQL 注入?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/601300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 01:19:22  来源:igfitidea点击:

What is SQL injection?

sqlsql-injectionsecurity

提问by

Can someone explain SQL injection? How does it cause vulnerabilities? Where exactly is the point where SQL is injected?

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

回答by Bill Karwin

Can someone explain SQL injecton?

有人可以解释SQL注入吗?

SQL injection happens when you interpolate some content into a SQL query string, and the result modifies the syntax of your query in ways you didn't intend.

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

It doesn't have to be malicious, it can be an accident. But accidental SQL injection is more likely to result in an error than in a vulnerability.

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

The harmful content doesn't have to come from a user, it could be content that your application gets from any source, or even generates itself in code.

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

How does it cause vulnerabilities?

它是如何导致漏洞的?

It can lead to vulnerabilities because attackers can send values to an application that they know will be interpolated into a SQL string. By being very clever, they can manipulate the result of queries, reading data or even changing data that they shouldn't be allowed to do.

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

Example in PHP:

PHP 中的示例:

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

Now suppose the attacker sets the POST request parameters to "password=xyzzy" and "id=account_id" resulting in the following SQL:

现在假设攻击者将 POST 请求参数设置为“ password=xyzzy”和“ id=account_id”,从而产生以下 SQL:

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

Although I expected $idto be an integer, the attacker chose a string that is the name of the column. Of course now the condition is true on everyrow, so the attacker has just set the password for everyaccount. Now the attacker can log in to anyone's account -- including privileged users.

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

Where exactly is the point where SQL is injected?

SQL 的注入点究竟在哪里?

It isn't SQL that's injected, it's content that's interpolated ("injected") into a SQL string, resulting in a different kind of query than I intended. I trusted the dynamic content without verifying it, and executed the resulting SQL query blindly. That's where the trouble starts.

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

SQL injection is a fault in the application code, not typically in the database or in the database access library or framework.

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

Most cases of SQL injection can be avoided by using query parameters. See How can I prevent SQL injection in PHP?for examples.

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

回答by Jim OHalloran

SQL Injection occurs when the user of an application is able to affect the meaning of database query. This often occurs when arbitary strings from user input are concatenated to create SQL which is fed to the database. For example lets say we had the following code (in PHP, but the same holds true for any language), which might be used to handle a user login.

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

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

The harm is done when the user enters something like

当用户输入类似的东西时就会造成伤害

administrator'; --

... for the username. Without proper encoding the query becomes:

...为用户名。如果没有正确编码,查询将变为:

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

The issue here is that the ' in the username closes out the username field then the -- starts a SQL comment causing the database server to ignore the rest of the string. The net result is the user can now log in as the administrator without having to know the password. SQL Inection can also be used to execute UPDATE, DELETE or DROP queries and really damage the database.

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

SQL Injection can be prevented by using parameterised queries, or applying your language/toolkit's escaping functions (such as mysql_real_escape_string() in PHP).

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

Once you understand SQL Injection you'll get the joke behind this cartoon.

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

回答by Sebastian Paaske T?rholm

SQL injection is when things that're supposed to be data are treated as SQL code unwillingly.

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

For instance, if you were to do

例如,如果你要做

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

Normally it'd get you the post with a given id, but assume that $postidis set to the string 10; DROP TABLE posts --; all of a sudden, the actual query you're sending is

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

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

This is quite a problem, as you'd be losing your entire posts table due to a malicious user - oh dear.

这是一个相当大的问题,因为恶意用户会丢失整个帖子表 - 哦,亲爱的。

The easiest way to prevent this is to use prepared statements, for instance through PDOor MySQLi.

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

The equivalent example in PDO would then be

PDO 中的等效示例将是

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

Doing this ensures that the database system knows that $postid is to be treated as data and not code, and will thus be handled appropriately.

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

回答by Bill Karwin

This question has been answered many times on StackOverflow, but it's an important topic for everyone to know about, so I'm not going to vote to close this question.

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

Here are links to some of my past answers on this topic:

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

I also gave a presentation at the MySQL Conference this month, and my slides are online:

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

回答by John Weldon

SQL injection is where a malicious user will put SQL into input fields to try and run the SQL on your server.

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

The #1 advice that I adhere to is to use parameterized stored procedures rather than building raw SQL in code.

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

Stored Procedure parameters don't get executed, making them safe in most cases.

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

回答by Chad Birch

I found this paper to be an extremely good read about SQL injection techniques (link is to PDF): Advanced SQL Injection In SQL Server Applications.

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

Despite the title saying "Advanced", it's quite readable even if you don't have much knowledge about SQL injection.

尽管标题是“高级”,但即使您对 SQL 注入知之甚少,它也很容易阅读。

回答by acrosman

To get some general background check out the Wikipedia article on SQL Injection.

要获得一些一般背景,请查看关于 SQL 注入维基百科文章

In short SQL injection attacks can leave you vulnerable to all manor of database data theft and destruction. The exact details of what can be done to your system depend on the details of the system itself.

简而言之,SQL 注入攻击会使您容易受到各种数据库数据盗窃和破坏的影响。可以对系统执行的操作的确切详细信息取决于系统本身的详细信息。

Any time you pass input from your users to your database you have a potential injection point. Web applications are often lacking in the this regard, as new programmers often do not understand the risks of handling input from users, and web applications are attacked by very smart people you never thought would find your program.

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

回答by SDReyes

You will like thisarticle from code project ; )

你会喜欢这个文章从代码项目; )

Summary

  • Encrypt sensitive data.
  • Access the database using an account with the least privileges necessary.
  • Install the database using an account with the least privileges necessary.
  • Ensure that data is valid.
  • Do a code review to check for the possibility of second-order attacks.
  • Use parameterised queries.
  • Use stored procedures.
  • Re-validate data in stored procedures.
  • Ensure that error messages give nothing away about the internal architecture of the application or the database.

概括

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

回答by thomasrutter

The point where SQL is injected is any point that your application accepts input from the user.

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

Whether this becomes a dangerous vulnerability for your web application depends on whether this input is later used as part of an SQL query without properly checking its type and escaping it if necessary.

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

Without proper escaping, some SQL code 'injected' by the user could be executed by the SQL engine as SQL code, rather than a simple string or value.

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