在我们的数据库访问层,我们有一些动态查询创建。 举例来说,我们有建设的一部分,下面的方法ORDER BY
子句:
protected string BuildSortString(string sortColumn, string sortDirection, string defaultColumn)
{
if (String.IsNullOrEmpty(sortColumn))
{
return defaultColumn;
}
return String.Format("{0} {1}", sortColumn, sortDirection);
}
问题是, sortColumn
和sortDirection
都来自外界的字符串,所以当然事情应该做,以防止可能的注入攻击。 没有任何人有任何想法,这可怎么办呢?
如果你要处理的字符串,然后白名单是你最好的选择。 首先, sortDirection
应该是很微不足道的白名单:不区分大小写的比较"asc"
/ "desc"
,你应该设置。 对于其他人,我更倾向于将到白名单已知列 ,也许在预期传递Type
的数据和验证。 但在绝对的紧要关头,你可以用正则表达式限制(比方说)强制执行他们都是严格的字母数字(在包括AZ,az,0-9范围-也许强调如果需要的话) -然后添加[]
即
return string.Format("[{0}] {1}", sortColumn, sortDirection);
但是:被称为列严格的白名单会好得多,因为会为方向的枚举。
另一种解决方法,如果你可以改变你的方法接受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 ");
}
祝好运。
您可以使用您的基于交换机关闭通过列名和方向的大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
解决方案: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] * $ /
你可以这样做:
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
}