Some Database Management Systems (DBMSs) let you send multiple SQL statements in a single query. In many development environments-including ColdFusion, ASP, and CGI-URL or form variables in a dynamic query can append malicious SQL statements to existing queries. Be aware that there are potential security risks when you pass parameters in a query string.
When you let a query string pass a parameter, ensure that only the expected information is passed. The following ColdFusion query contains a WHERE clause, which selects only database entries that match the last name specified in the LastName field of a form:
<cfquery name="GetEmployees" datasource="CompanyInfo">
SELECT FirstName, LastName, Salary FROM Employee WHERE LastName='#Form.LastName#' </cfquery>
Someone could call this page with the following malicious URL:
http://myserver/page.cfm?Emp_ID=7%20DELETE%20FROM%20Employee
The result is that ColdFusion tries to execute the following query:
<cfquery name="GetEmployees" datasource="CompanyInfo">
SELECT * FROM Employee WHERE Emp_ID = 7 DELETE FROM Employee </cfquery>
In addition to an expected integer for the Emp_ID column, this query also passes malicious string code in the form of a SQL statement. If this query successfully executes, it deletes all rows from the Employee table-something you definitely do not want to enable by this method. To prevent such actions, you must evaluate the contents of query string parameters.
You can use the cfqueryparam
tag to evaluate query string parameters and pass a ColdFusion variable within a SQL statement. This tag evaluates variable values before they reach the database. You specify the data type of the corresponding database column in the cfsqltype
attribute of the cfqueryparam
tag. In the following example, because the Emp_ID column in the CompanyInfo data source is an integer, you specify a cfsqltype
of cf_sql_integer
:
<cfquery name="EmpList" datasource="CompanyInfo">
SELECT * FROM Employee WHERE Emp_ID = <cfqueryparam value = "#Emp_ID#" cfsqltype = "cf_sql_integer"> </cfquery>
The cfqueryparam
tag checks that the value of Emp_ID is an integer data type. If anything else in the query string is not an integer, such as a SQL statement to delete a table, the cfquery
tag does not execute. Instead, the cfqueryparam
tag returns the following error message:
Invalid data '7 DELETE FROM Employee' for CFSQLTYPE 'CF_SQL_INTEGER'.
When passing a variable containing a string to a query, specify a cfsqltype
of cf_sql_char
, as in the following example:
<cfquery name = "getFirst" dataSource = "cfsnippets">
SELECT * FROM employees WHERE LastName = <cfqueryparam value = "#LastName#" cfsqltype = "cf_sql_char" maxLength = "17"> </cfquery>
In this case, cfqueryparam
performs the following checks:
WHERE LastName = 'Anwar DELETE FROM MyCustomerTable'.
The following table lists the available SQL types against which you can evaluate the value
attribute of the cfqueryparam
tag:
BIGINT |
BIT |
CHAR |
DATE |
DECIMAL |
DOUBLE |
FLOAT |
IDSTAMP |
INTEGER |
LONGVARCHAR |
MONEY |
MONEY4 |
NUMERIC |
REAL |
REFCURSOR |
SMALLINT |
TIME |
TIMESTAMP |
TINYINT |
VARCHAR |