防止SQL注入的ORDER BY子句(Prevent SQL Injection in ORDER

2019-08-06 19:14发布

在我们的数据库访问层,我们有一些动态查询创建。 举例来说,我们有建设的一部分,下面的方法ORDER BY子句:

protected string BuildSortString(string sortColumn, string sortDirection, string defaultColumn)
{
    if (String.IsNullOrEmpty(sortColumn))
    {
        return defaultColumn;
    }

    return String.Format("{0} {1}", sortColumn, sortDirection);
}

问题是, sortColumnsortDirection都来自外界的字符串,所以当然事情应该做,以防止可能的注入攻击。 没有任何人有任何想法,这可怎么办呢?

Answer 1:

如果你处理的字符串,然后白名单是你最好的选择。 首先, sortDirection应该是很微不足道的白名单:不区分大小写的比较"asc" / "desc" ,你应该设置。 对于其他人,我更倾向于将到白名单已知列 ,也许在预期传递Type的数据和验证。 但在绝对的紧要关头,你可以用正则表达式限制(比方说)强制执行他们都是严格的字母数字(在包括AZ,az,0-9范围-也许强调如果需要的话) -然后添加[]

return string.Format("[{0}] {1}", sortColumn, sortDirection);

但是:被称为列严格的白名单会好得多,因为会为方向的枚举。



Answer 2:

另一种解决方法,如果你可以改变你的方法接受int而不是string参数。

protected string BuildSortString(int sortColumn, int sortDirection, string defaultColumn)
{
    if (String.IsNullOrEmpty(sortColumn))
    {
        return defaultColumn;
    }
//sortdirection 0-> "ASC" else "DESC"
//sorColumn 1 for your firstcolumn, 2 for your second column etc.
    return String.Format("{0} {1}", sortColumn, sortDirection==0? " ASC " : " DESC ");
}

祝好运。



Answer 3:

您可以使用您的基于交换机关闭通过列名和方向的大CASE语句做到这一点。 有对一个SO回答这里 。 你会在看类似的代码:

SELECT
     *
FROM
     My_Table
WHERE
     Whatever = @something
ORDER BY
     CASE @sort_order
          WHEN 'ASC' THEN
               CASE @order_by
                    WHEN 'surname' THEN surname
                    WHEN 'forename' THEN forename
                    WHEN 'fullname' THEN fullname
                    ELSE surname
               END
          ELSE '1'
     END ASC,
     CASE @sort_order
          WHEN 'DESC' THEN
               CASE @order_by
                    WHEN 'surname' THEN surname
                    WHEN 'forename' THEN forename
                    WHEN 'fullname' THEN fullname
                    ELSE surname
               END
          ELSE '1'
     END DESC


Answer 4:

解决方案:cmd.Parameters或EscapedString ,但我更喜欢cmd.Parameters(总是工作和你喜欢的预期例外)

例:

cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID IN (?, ?)";
cmd.Parameters.Add("?ID1", OdbcType.VarChar, 250).Value = email1;
cmd.Parameters.Add("?ID2", OdbcType.VarChar, 250).Value = email2;

使用准备好的语句与参数可以帮助防范SQL注入的最常见的情况下,当你本来插值不受信任的内容转换为字符串,然后执行字符串作为SQL语句。

但查询参数接受一个值的地方。 不能使用查询参数作为一个动态表名替补,列名,值列表(例如,对于一个IN()谓词),表达式或SQL关键字。

对于这些情况,您可以像使用过滤或白名单技术,让你不插不受信任的内容到你的SQL字符串。

过滤是你去掉会引起麻烦的任何字符。 如果你知道你的动态列名只能是字母数字字符,然后在SQL中使用它之前,过滤器应用到您的变量。 要不然只是拒绝变量,如果它不匹配一个正则表达式如/ ^ [A-ZA-Z0-9] * $ /



Answer 5:

你可以这样做:

public string BuildSortString(string sortColumn, SortDirection direction, string defaultColumn)
{
    string sortDirection = direction.ToString();

    if (String.IsNullOrEmpty(sortColumn))
    {
        return VerifyColumn(defaultColumn);
    }

    return String.Format("{0} {1}", VerifyColumn(sortColumn), sortDirection);
}

private string VerifyColumn(string column)
{
    switch (column) // fill this with a whitelist of accepted columns
    {
        case "some_column":
            return column;
    }

    return String.Empty; // the column must be invalid (do whatever you want here)
}

public enum SortDirection
{
    ASC, DESC
}


文章来源: Prevent SQL Injection in ORDER BY clause