how to prevent coldfusion sql-injection on order by clause
Since cfqueryparam doesn't work in an order by, would using xmlformat stop sql 开发者_开发百科injections?
ORDER BY #xmlformat(myVariable)#
Thanks,
http://www.petefreitag.com/item/677.cfm
A good way to get around this limitation is to use the ListFindNoCase function, to limit the sortable column names, for example:
<cfset sortable_column_list = "age,height,weight,first_name">
<cfquery ...>
SELECT first_name, age, height, weight
FROM people
ORDER BY <cfif ListFindNoCase(sortable_column_list, url.sort_column)>#url.sort_column#<cfelse>first_name</cfif>
</cfquery>
This is from a stored procedure, but translate an @ORDER_BY value to an actual database column and a @SORT_ORDER value to a SQL command.
ORDER BY
CASE WHEN @ORDER_BY = 'LENDER' AND @SORT_ORDER = 'D' THEN l.tms_name END DESC,
CASE WHEN @ORDER_BY = 'LENDER' AND @SORT_ORDER != 'D' THEN l.tms_name END,
CASE WHEN @ORDER_BY = 'LOAN_NUMBER' AND @SORT_ORDER = 'D' THEN p.Loan_Number END DESC,
CASE WHEN @ORDER_BY = 'LOAN_NUMBER' AND @SORT_ORDER != 'D' THEN p.Loan_Number END,
XML Format won't handle all cases.
The column check is good, but I'm guessing that the advantage of letting the user define what the order by is, is because you can make it more complex than just a single column. For instance, you could add several columns and an Ascending, Descending etc...
I'd suggest you make a globally available function that strips out any character that isn't a number, letter or comma. If someone did attempt to do a SQL Injection it would just fail.
<cfif refindnocas('^\w+ ?(desc|asc)?$', myVariable)>
ORDER BY #myVariable#
</cfif>
or
<cfset columnList = 'col1,col2,etc' /> <!--- might want to use in select as well --->
<cfset regexColList = replace(columnList, ',', '|', 'all') />
<cfif not refindnocas('^(#regexColList#) ?(desc|asc)?$', myVariable)>
<cfset myVariable = "DefaultSort" />
</cfif>
ORDER BY #myVariable#
or
ORDER BY #query_sort(myVariable, columnList, defaultSort)#
...
<cffunction name="query_sort">
<cfargument name="sort" />
<cfargument name="columns" />
<cfargument name"default" />
<cfset var regexcolumns = replace(columns, ',', '|', 'all') />
<cfif refindnocas('^(#regexcolumns#) ?(desc|asc)?$', sort)>
<cfreturn sort />
<cfelse>
<cfreturn default />
</cfif>
</cfargument>
etc
Another option is a slight twist on the ListFindNoCase approach. Column information can be stored in a structure. The key
would be the publicly visible column name and the value
is the real column name. It is a little more complex. But I like the fact that it does not require you to expose your schema. It also supports more compound statements as Dave mentioned.
<cfset sortCols = { defaultCol="DepartmentName"
, date="ReportDate"
, type="DepartmentName"
, num="EmployeeID" } />
....
SELECT Columns
FROM TableName
ORDER BY
<cfif structKeyExists(sortCols, url.sort_column)>
#sortCols[url.sort_column]#
<cfelse>
#sortCols["defaultCol"]#
</cfif>
精彩评论