参数真的足以防止Sql注入吗?

发布于 2024-07-08 13:01:19 字数 556 浏览 4 评论 0原文

我一直在向我的同事和这里宣讲在 SQL 查询中使用参数的好处,尤其是在 .NET 应用程序中。 我什至承诺他们可以免受 SQL 注入攻击。

但我开始怀疑这是否属实。 是否有任何已知的 SQL 注入攻击能够成功针对参数化查询? 例如,您可以发送一个导致服务器缓冲区溢出的字符串吗?

当然,为了确保 Web 应用程序的安全,还需要考虑其他因素(例如清理用户输入等),但现在我正在考虑 SQL 注入。 我对针对 MsSQL 2005 和 2008 的攻击特别感兴趣,因为它们是我的主要数据库,但所有数据库都很有趣。

编辑:澄清参数和参数化查询的含义。 通过使用参数,我的意思是使用“变量”而不是在字符串中构建 sql 查询。
因此,我们不这样做:

SELECT * FROM Table WHERE Name = 'a name'

我们这样做:

SELECT * FROM Table WHERE Name = @Name

然后在查询/命令对象上设置 @Name 参数的值。

I've been preaching both to my colleagues and here on SO about the goodness of using parameters in SQL queries, especially in .NET applications. I've even gone so far as to promise them as giving immunity against SQL injection attacks.

But I'm starting to wonder if this really is true. Are there any known SQL injection attacks that will be successfull against a parameterized query? Can you for example send a string that causes a buffer overflow on the server?

There are of course other considerations to make to ensure that a web application is safe (like sanitizing user input and all that stuff) but now I am thinking of SQL injections. I'm especially interested in attacks against MsSQL 2005 and 2008 since they are my primary databases, but all databases are interesting.

Edit: To clarify what I mean by parameters and parameterized queries. By using parameters I mean using "variables" instead of building the sql query in a string.
So instead of doing this:

SELECT * FROM Table WHERE Name = 'a name'

We do this:

SELECT * FROM Table WHERE Name = @Name

and then set the value of the @Name parameter on the query / command object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

梓梦 2024-07-15 13:01:19

占位符足以防止注入。 您可能仍然对缓冲区溢出持开放态度,但这是与 SQL 注入完全不同的攻击方式(攻击向量不是 SQL 语法,而是二进制)。 由于传递的参数都将被正确转义,因此攻击者无法传递将被视为“实时”SQL 的数据。

您不能在占位符内使用函数,也不能将占位符用作列名或表名,因为它们会被转义并作为字符串文字引用。

但是,如果您在动态查询中使用参数作为字符串连接的一部分,您仍然容易受到注入,因为您的字符串不会被转义,而是会被文字化。 使用其他类型的参数(例如整数)是安全的。

也就是说,如果您使用 use input 来设置诸如 security_level 之类的值,那么有人就可以让自己成为您系统中的管理员并进行混战。 但这只是基本的输入验证,与 SQL 注入无关。

Placeholders are enough to prevent injections. You might still be open to buffer overflows, but that is a completely different flavor of attack from an SQL injection (the attack vector would not be SQL syntax but binary). Since the parameters passed will all be escaped properly, there isn't any way for an attacker to pass data that will be treated like "live" SQL.

You can't use functions inside placeholders, and you can't use placeholders as column or table names, because they are escaped and quoted as string literals.

However, if you use parameters as part of a string concatenation inside your dynamic query, you are still vulnerable to injection, because your strings will not be escaped but will be literal. Using other types for parameters (such as integer) is safe.

That said, if you're using use input to set the value of something like security_level, then someone could just make themselves administrators in your system and have a free-for-all. But that's just basic input validation, and has nothing to do with SQL injection.

诠释孤独 2024-07-15 13:01:19

不,每当您将未经验证的数据插入 SQL 查询时,仍然存在 SQL 注入的风险。

查询参数通过将文字值与 SQL 语法分开来帮助避免这种风险。

'SELECT * FROM mytable WHERE colname = ?'

这很好,但是将数据插入到不能使用查询参数的动态 SQL 查询中还有其他目的,因为它不是 SQL 值,而是表名、列名、表达式或其他语法。

'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')'
' ORDER BY ' + @colname'

无论您是使用存储过程还是直接从应用程序代码执行动态 SQL 查询,都没有关系。 风险依然存在。

这些情况下的补救措施是根据需要使用FIEO

  • 过滤输入:在之前验证数据是否看起来像合法的整数、表名、列名等。

  • 转义输出:在这种情况下,“输出”意味着将数据放入 SQL 查询中。 我们使用函数来转换 SQL 表达式中用作字符串文字的变量,以便对字符串中的引号和其他特殊字符进行转义。 我们还应该使用函数来转换用作表名、列名等的变量。至于其他语法,例如动态编写整个 SQL 表达式,这是一个更复杂的问题。

No, there is still risk of SQL injection any time you interpolate unvalidated data into an SQL query.

Query parameters help to avoid this risk by separating literal values from the SQL syntax.

'SELECT * FROM mytable WHERE colname = ?'

That's fine, but there are other purposes of interpolating data into a dynamic SQL query that cannot use query parameters, because it's not an SQL value but instead a table name, column name, expression, or some other syntax.

'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')'
' ORDER BY ' + @colname'

It doesn't matter whether you're using stored procedures or executing dynamic SQL queries directly from application code. The risk is still there.

The remedy in these cases is to employ FIEO as needed:

  • Filter Input: validate that the data look like legitimate integers, table names, column names, etc. before you interpolate them.

  • Escape Output: in this case "output" means putting data into a SQL query. We use functions to transform variables used as string literals in an SQL expression, so that quote marks and other special characters inside the string are escaped. We should also use functions to transform variables that would be used as table names, column names, etc. As for other syntax, like writing whole SQL expressions dynamically, that's a more complex problem.

眼眸印温柔 2024-07-15 13:01:19

该线程中关于“参数化查询”的定义似乎存在一些混乱。

  • SQL,例如接受参数的存储过程。
  • 使用 DBMS 参数集合调用的 SQL。

鉴于前一个定义,许多链接都显示了有效的攻击。

但“正常”的定义是后者。 根据这个定义,我不知道有任何 SQL 注入攻击会起作用。 这并不意味着不存在,但我还没有看到它。

从评论来看,我表达得不够清楚,所以这里有一个希望更清楚的例子:

这种方法对 SQL 注入开放

exec dbo.MyStoredProc 'DodgyText'

这种方法开放SQL注入

using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
    newParam.Value = "DodgyText";
    .....
    cmd.Parameters.Add(newParam);
    .....
    cmd.ExecuteNonQuery();
}

There seems to be some confusion in this thread about the definition of a "parameterised query".

  • SQL such as a stored proc that accepts parameters.
  • SQL that is called using the DBMS Parameters collection.

Given the former definition, many of the links show working attacks.

But the "normal" definition is the latter one. Given that definition, I don't know of any SQL injection attack that will work. That doesn't mean that there isn't one, but I have yet to see it.

From the comments, I'm not expressing myself clearly enough, so here's an example that will hopefully be clearer:

This approach is open to SQL injection

exec dbo.MyStoredProc 'DodgyText'

This approach isn't open to SQL injection

using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
    newParam.Value = "DodgyText";
    .....
    cmd.Parameters.Add(newParam);
    .....
    cmd.ExecuteNonQuery();
}
你曾走过我的故事 2024-07-15 13:01:19

用于构造动态查询的任何字符串类型(varchar、nvarchar 等)的 sql 参数仍然容易受到攻击,

否则参数类型转换(例如,转换为 int、decimal、date 等)应消除通过以下方式注入 sql 的任何尝试:参数

编辑:一个示例,其中参数@p1旨在作为表名

create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) 
AS
    SET NOCOUNT ON
    declare @sql varchar(512)
    set @sql = 'select * from ' + @p1
    exec(@sql)
GO

如果从下拉列表中选择@p1,则它是潜在的sql注入攻击向量;

如果@p1是以编程方式制定的,用户无法干预,那么它不是潜在的sql注入攻击向量

any sql parameter of string type (varchar, nvarchar, etc) that is used to construct a dynamic query is still vulnerable

otherwise the parameter type conversion (e.g. to int, decimal, date, etc.) should eliminate any attempt to inject sql via the parameter

EDIT: an example, where parameter @p1 is intended to be a table name

create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) 
AS
    SET NOCOUNT ON
    declare @sql varchar(512)
    set @sql = 'select * from ' + @p1
    exec(@sql)
GO

If @p1 is selected from a drop-down list it is a potential sql-injection attack vector;

If @p1 is formulated programmatically w/out the ability of the user to intervene then it is not a potential sql-injection attack vector

毁我热情 2024-07-15 13:01:19

缓冲区溢出不是 SQL 注入。

参数化查询可确保您免受 SQL 注入的威胁。 他们不保证您的 SQL 服务器中不会​​出现以错误形式出现的漏洞,但没有什么能保证这一点。

A buffer overflow is not SQL injection.

Parametrized queries guarantee you are safe against SQL injection. They don't guarantee there aren't possible exploits in the form of bugs in your SQL server, but nothing will guarantee that.

终难遇 2024-07-15 13:01:19

如果您以任何方式使用动态 SQL,您的数据都是不安全的,因为权限必须位于表级别。 是的,您限制了来自该特定查询的注入攻击的类型和数量,但不限制用户在找到进入系统的方法时可以获得的访问权限,并且您完全容易受到内部用户访问他们不应该访问的内容的影响。以实施欺诈或窃取个人信息进行出售。 任何类型的动态 SQL 都是一种危险的做法。 如果您使用非动态存储过程,则可以在过程级别设置权限,并且除了过程定义之外,任何用户都不能执行任何操作(当然系统管理员除外)。

Your data is not safe if you use dynamic sql in any way shape or form because the permissions must be at the table level. Yes you have limited the type and amount of injection attack from that particular query, but not limited the access a user can get if he or she finds a way into the system and you are completely vunerable to internal users accessing what they shouldn't in order to commit fraud or steal personal information to sell. Dynamic SQL of any type is a dangerous practice. If you use non-dynamic stored procs, you can set permissions at the procesdure level and no user can do anything except what is defined by the procs (except system admins of course).

少女的英雄梦 2024-07-15 13:01:19

存储过程可能容易受到通过溢出/截断的特殊类型 SQL 注入的攻击,请参阅:数据截断启用的注入:

http://msdn.microsoft.com/en-us/library/ms161953.aspx

It is possible for a stored proc to be vulnerable to special types of SQL injection via overflow/truncation, see: Injection Enabled by Data Truncation here:

http://msdn.microsoft.com/en-us/library/ms161953.aspx

陌生 2024-07-15 13:01:19

请记住,使用参数您可以轻松存储字符串,或者如果您没有任何策略,请输入用户名,"); drop table users; --"

这本身不会造成任何损害,但您最好知道在哪里和如何在您的应用程序中进一步使用该日期(例如存储在 cookie 中,稍后检索以执行其他操作。

Just remember that with parameters you can easily store the string, or say username if you don't have any policies, "); drop table users; --"

This in itself won't cause any harm, but you better know where and how that date is used further on in your application (e.g. stored in a cookie, retrieved later on to do other stuff.

救星 2024-07-15 13:01:19

您可以运行动态 sql 作为示例

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT  @ParameterDefinition = '@date varchar(10)'

SET @SQL='Select CAST(@date AS DATETIME) Date'

EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'

You can run dynamic sql as example

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT  @ParameterDefinition = '@date varchar(10)'

SET @SQL='Select CAST(@date AS DATETIME) Date'

EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文