【问题标题】:SQL injection prevention with 'AS QUERY'使用“AS QUERY”防止 SQL 注入
【发布时间】:2020-02-20 23:01:45
【问题描述】:

我有以下代码,看起来很标准,但是在查询中是另一个 SQL 语句,因此“AS QUERY”位于 SQL 字符串的末尾。我想知道是否有一种复杂的方法来参数化以下 SQL 命令,而不是将整个查询连接在一起。

我能想到的唯一解决方案是将查询作为字符串而不是将其作为SQLCommand 类型对象并启动2个命令。 1个可以,另一个显示数据的预览。

public static CommandStatus<int> GetQueryRecordCount(SqlConnection connection, String query)
{
    String sql = "SELECT COUNT(1) FROM (" + query + ") AS QUERY";
    SqlCommand cmd = new SqlCommand();
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = sql;
    cmd.Connection = connection;
    cmd.CommandTimeout = GetTimeout();

    try
    {
        SqlDataReader dataReader = cmd.ExecuteReader();
        dataReader.Read();

        String count = dataReader[0].ToString();
        dataReader.Close();

        return new CommandStatus<int>(Int32.Parse(count));
    }
    catch (Exception e)
    {
        return new CommandStatus<int>("Failed to GetQueryRecordCount[" + sql + "]:" + e.Message, e);
    }
}

String SQL 最终会变成这样

"SELECT COUNT(1) FROM (SELECT TOP 20 [RecordID],[Name],[SonsName],[DadsName],[MothersName],[DaughtersName] FROM [dbo].[sample] ) AS QUERY"

【问题讨论】:

  • 该字符串中没有值,因此除了TOP 返回的行数之外没有其他参数。 AS QUERY 不是关键字,它只是子查询的别名。无论如何,这段代码有什么意义?如果少于 20 个,它将返回 20 个或样本数。
  • “查询”参数从何而来?如果它是同一模块中的可用值之一,则 sql 注入的风险非常小。另一方面,如果它来自某些用户输入,则存在真正的 sql 注入风险。
  • 你也许可以使用 SqlParameter。这通常用于以“安全”的方式传递参数
  • @DanielSchmid 表名和列名不能作为 SQL 参数提供。
  • @Amy:好吧,他们可以,只要您随后动态构建生成的查询。 (我提到这并不是迂腐,而是因为将它们作为参数传递给存储过程,然后检查白名单是一种合法的业务方式,而不是必须动态构建整个事物并打开完全任意查询的大门.)

标签: c# sql-injection


【解决方案1】:

这个函数实际上是设计的 SQL 注入。

白名单此函数将接受的 SQL 查询是使其安全的唯一方法。

也就是说,调用者将无法注入任何 SQL 查询,他们只能从预先审查的固定查询列表中进行选择。该列表甚至可以在您显示的函数中定义为静态字符串数组。

但是他们不需要将整个查询作为字符串传递,他们只需要传递一个序数整数来标识要运行白名单中的哪个查询。

【讨论】:

    猜你喜欢
    • 2016-11-16
    • 2015-09-27
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 2017-12-08
    • 2017-11-11
    相关资源
    最近更新 更多