SQL注入漏洞

4

我正在处理一个项目,其中客户报告代码中有SQL注入漏洞。这是我的代码...

1 public int ExecuteNonQuery(string query, SqlParameter[] parameters)
2 {
3   using (SqlCommand command = CreateCommand(query, parameters))
4   {
5       int rowsAffected = command.ExecuteNonQuery();
6       return rowsAffected;
7   }
8 }

CreateCommand 方法的代码如下:

private SqlCommand CreateCommand(string commandText, SqlParameter[] parameters)
{
    SqlCommand retVal = this.connection.CreateCommand();
    retVal.CommandText = commandText;
    retVal.CommandTimeout = this.commandsTimeout;
    retVal.Parameters.AddRange(parameters);
    return retVal;
}

漏洞报告在第3行。由于这是控制台应用程序,我无法理解可能发生的攻击类型。但是我必须修复此漏洞,而我不知道如何修复它。

查询为

@"delete from {0} where runId in 
( select runId from {0}
  inner join 
    ( select sId as sId_last,
        wfId as wfId_last,
        max(runId) as runId_last from {0} where endTime is NULL
        group by sId, wfId ) t1
  on endTime is NULL and sId = sId_last and wfId = wfId_last
  and (runId <> runId_last or startTime < @aDateTime)
)";

感谢您的帮助。


4
你了解什么是SQL注入吗? - TZHX
是的,我明白。问题是它不是基于Web的应用程序。它是一个控制台应用程序,没有任何文本字段可以输入数据。 - NJMR
1
发布你的查询..可能存在漏洞。 - Tharif
@工具:我已经发布了查询。 - NJMR
3个回答

5
那段代码没有注入漏洞...但要注意的是,调用 ExecuteNonQuery 的方法可能会通过字符串组合构建query 造成注入攻击。
注入攻击发生在类似下面这样的情况下:
string name = ...; // A name selected by the user.
string query = "SELECT * FROM MyTable WHERE Name = '" + name + "'";

当您使用外部来源的文本片段组成查询时,请注意。

请注意,更微妙的注入攻击可能是多层的:

string name = // The result of a query to the db that retrieves some data
              // sadly this data has been manipulated by the attacker

string query = "SELECT * FROM MyTable WHERE Name = '" + name + "'";

通常情况下,您不需要用户界面来进行注入攻击...您可以从网站/数据库查询某些内容,并使用未经过净化的结果查询数据库(如最后一个示例中所示),从而导致注入攻击...甚至使用配置文件的内容也可能会导致注入攻击:修改配置文件所需的权限可能与在数据库上执行某些操作所需的权限不同,恶意用户可能具有修改配置文件的权限,但没有直接访问数据库的权限。因此,他可以将程序用作针对数据库的特洛伊木马。
关于查询:
该查询(由字符串组成)的弱点在于如何计算{0}。它是从一组固定字符串中选择的字符串吗?类似于:
string tableName;

if (foo)
   tableName = "Foo";
else if (bar)
   tableName = "Bar";

或者说这是更多由用户控制的内容吗?

如果表名在代码中是固定的,那么就不会有任何注入攻击的可能性。如果表名是从某些用户输入/其他用户可以访问的表中“提取”的,我们就会回到我之前展示的问题。


谢谢您的回答,但是我该如何验证查询。我需要验证参数吗? - NJMR
@NJMR SqlParameter是“安全的”。注入攻击只针对查询的“文本”部分。请注意,还有另一类攻击,例如用户发现如何直接通过Id进行查询,并能够查询他不应该查询到的信息...例如,假设您的网站具有以下地址:http://mysite.xxx/user/123,其中123是用户的id。用户可以尝试编写http://mysite.xxx/user/200并查看会发生什么...但正如我所说,这是另一类攻击。 - xanatos
1
值得一提的是,参数化查询并不是100%安全的,如果查询在参数上做了一些愚蠢的事情,仍然容易受到注入攻击的影响。我曾经见过一个存储过程,在字符串查询中连接了参数,例如 SET @query = 'SELECT * FROM foo WHERE name LIKE ''%' + @term+ '%'''。非常愚蠢,但这种情况比你想象的要多发生得多。 - DGibbs
@DGibbs 是的...我忘记了!如果你使用EXEC来执行一些东西,那就是自找麻烦 :-) - xanatos

2

您已经公开了一个public方法,可以被任何允许执行任何SQL表达式的代码访问。

我建议将该方法更改为internalprivate,以便不是所有代码都可以调用该方法。


2

第三行:

 using (SqlCommand command = CreateCommand(query, parameters))

这行代码中,查询和参数都是可用的。

不应该通过尝试验证输入来防止SQL注入攻击;相反,在将输入传递给数据库之前,应该对其进行适当的转义。

如何转义输入完全取决于您使用什么技术与数据库进行交互。

使用预处理语句和参数化查询。这些是SQL语句,与任何参数分开发送到并由数据库服务器解析。这样,攻击者就无法注入恶意SQL。

这里有关于SQL注入的课程供您参考。链接2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接