Prevent SQL Injection in ORDER BY clause

自闭症网瘾萝莉.ら 提交于 2019-12-06 20:20:41

问题


In our DB access layer we have some dynamic query creation. For instance, we have the following method for building a part of an ORDER BY clause:

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

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

The problem is, sortColumn and sortDirection both come from outside as strings, so of course something should be done to prevent possible injection attacks. Does anybody have any idea how this can be done?


回答1:


If you have to deal in strings, then white-listing is your best bet. Firstly, sortDirection should be pretty trivial to white-list: a case-insensitive compare to "asc" / "desc" and you should be set. For the others, my preference would be to white-list to known columns, perhaps by passing in the expected Type for the data and validating. But at an absolute pinch, you could restrict with regex to (say) enforce they are all strictly alpha-numeric (in the a-z, A-Z, 0-9 range - maybe underscore if needed) - and then add [], i.e.

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

But: strict white-list of known columns would be much better, as would an enum for the direction.




回答2:


Another solution if you can change your method to accept int instead of string parameters.

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 ");
}

Good luck.




回答3:


You can do this using a large CASE statement where you switch based off the passed column name and direction. There's an SO answer on that here. You're going to be looking at code like:

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



回答4:


Solution: cmd.Parameters or EscapedString, but I prefer cmd.Parameters (always work and you enjoy the Exceptions expected)

example:

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;

Using prepared statements with parameters helps to defend against SQL injection in most common cases, when you would otherwise interpolate untrusted content into a string and then execute the string as an SQL statement.

But a query parameter takes the place of a single value. You can't use a query parameter as a substitute for a dynamic table name, column name, list of values (e.g. for an IN() predicate), expressions, or SQL keywords.

For those cases, you can use techniques like filtering or whitelisting so you don't interpolate untrusted content into your SQL strings.

Filtering is where you strip out any characters that would cause trouble. If you know your dynamic column name should only be alphanumeric characters, then apply a filter to your variable before using it in SQL. Or else just reject a variable if it doesn't match a regular expression like /^[A-Za-z0-9]*$/




回答5:


You could do something like this:

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
}


来源:https://stackoverflow.com/questions/14317341/prevent-sql-injection-in-order-by-clause

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!