When coding a cfqueryparam or cfprocparam, cfsqltype is optional. However, I've usually seen it coded. Are there any benefits to specifying cfsqltype?
The main benefit is an additional level of sanity checking for your query inputs, prior to passing it into your query. Also, in the case of date time values, I believe CF will properly translate datetime strings into the proper database format, if the cfsqltype="CF_SQL_DATE" or ="CF_SQL_TIMESTAMP" is specified.
In addition, I think it makes it more clear for future developers to see the types excepted when they read your code.
I would add to Jake's comment. In most RDBMS the database will need to run your variable through a type lookup to insure it's the proper type or can be cast to the proper type implicitly. A DB doesn't just throw a variable of "type Any" at a table or view. It has to build the proper typing into the execution plan. So if you don't provide a type you are asking the DB to "figure it out".
Whereas, when you specify the type you are pre-empting or pre-qualifying the data type. The engine knows the driver is presenting a variable of a certain type and can then use it directly or derive it directly.
Remember that, while security is a good reason to use cfqueryparam, it's only one reason. The other reason is to create correctly prepared statements that can executed efficiently - and ideally "pop" the execution plan cache on the DB server.
Related
The passwords and my SQL database are hashed. If the input is hashed, can the field be injected?
The hash is SHA256. My command is to be:
SELECT true FROM accounts WHERE password = '[hex digits]';
I suggest that you not ask this question, because maybe there is a way that you can be in danger, but probably there isn't. Instead, use SQL placeholders and bind variables because that's why they exist.
Any time you are building a SQL statement using data that you are not directly controlling, you are running a risk.
Prepared SQL statements with placeholders also have the benefit of being less work for the database.
Do you have a reason that you can't do it this way?
Strictly speaking, the example you give is safe. Similarly, if you have an application variable that can only be an integer, it is safe. Or even if it's a string, if your code is in control of the string, and you can be sure the string doesn't contain characters that would cause SQL injection (e.g. quote characters like ' or "), then it's safe.
But I agree with Andy Lester's answer — just use query parameters, and then you don't have to think about it. You don't have to wonder if there's an edge case where the input string may be out of your control. You don't have to ask if a string of hex digits is safe or not.
And even more importantly, you don't have to worry that not every developer on your team has the same understanding of how to tell if an input is safe or not. Many developers don't know how to tell safe inputs from non-safe inputs, so it's safest to just establish a policy that all inputs must be parameterized into an SQL query after it is parsed, instead of concatenated into the SQL query before it is parsed.
Imagine you are an electrician. You don't want to touch a live circuit, but if you're well trained you know if you touch it with the right kind of insulated protection, or if you're not grounded, or other conditions are true, then you're probably safe. Probably.
But what is safest is to just make sure the circuit has been disconnected from the power source. That's just a smart habit. It always works, and even if you work with other people who are not as smart as you, it still works.
I agree with the previous answers from Bill and Andy - it's safe, but you should still bind variables / parameterized query parameters. Doing so will:
Improve performance in many databases - the query string will only need to be parsed and cached once
Reduce false positives for human code reviewers and static code analysis
Reinforce the correct coding techniques for anyone reading the code
Future proof it against changes (for example if someone changes the hash output to include quotes)
I ask this question with a bit of sheepishness because I should know the answer. Could someone be kind and explain if and how injection could occur in the following code?
<cfquery>
select * from tableName
where fieldName = '#value#'
</cfquery>
I'm specifically curious about injection attempts and other malicious input, not about best practices or input validation for handling "normal" user input. I see folks strongly advocating use of CFQueryParam, but don't think I see the point. If user input has been validated for consistency to the database schema (e.g. so that input must be numeric for numerical database fields), is there anything else gained by using CFQueryParam? What does <cfqueryparam CFSQLType = "CF_SQL_VARCHAR"> do that '#value#' doesn't do?
Update:
While this answers part of your question, Peter's response is better, in that it directly addresses your question of "Why use cfqueryparam, when CF automatically adds protection by escaping single quotes?". Answer: In short, because the latter does not always work. Bind variables do.
It says in the docs "escapes string variables in single-quotation
marks" but doesn't CF already "magically" do this in CF query tag when
you wrap evaluated variables in single quotes?
Yes, most versions automatically escape single quotes as a protection measure for those not using cfqueryparam. However, as Scott noted above, it is better to use cfqueryparam (ie bind variables) because they ensure parameters are not executed as sql commands. Bind variables work, even in cases where the automatic escaping does not, as Peter's answer demonstrates.
That said, sql injection protection is really just a side effect of using bind variables. The primary reason to use bind variables is performance. Bind variables encourage databases to re-use query plans, instead of creating a new plan every time your #parameters# change. That cuts down on compilation time, improving performance.
Cfqueryparam also has a number of other benefits:
Provides data type checking (length, value, type, ...)
Provides attributes that simplify handling of "lists" and null values
Performs data type checking before any sql is sent to the database, preventing wasted database calls
While it does not really apply to string columns, IMO another big reason to use it is accuracy. When you pass a quoted string to the database, you are relying on implicit conversion. Essentially you are leaving it up to the database to figure out how to best perform the comparison, and the results are not always what you were expecting. (Date strings are a prime example). You may end with inaccurate results, or sometimes slower queries, depending on how the database decides to execute the sql. Using cfqueryparam avoids those issues by eliminating the ambiguity.
doesn't CF already "magically" do this in CF query tag when you wrap evaluated variables in single quotes?
Yep, it'll convert ' to '' for you.
Now guess what SQL you get from this code:
<cfset value = "\'; DROP TABLE tableName -- " />
<cfquery>
select * from tableName
where fieldName = '#value#'
</cfquery>
The cfqueryparam tag works; using query params solves SQL injection.
Any custom written attempts at validating, sanitizing, or escaping (all separate things, btw) are, at best, only as good as the developer's knowledge of the database system the code is running against.
If the developer is unaware of other escape methods, or if the values are modified between validation/escaping and them being rendered into SQL, or even if the codebase is ported to another database system and seems to be fine, there's a chance of custom code breaking down.
When it comes to security, you don't want chances like that. So use cfqueryparam.
To answer the first part of your question, setting your #value# variable to the following:
someValue'; DELETE FROM tableName WHERE '1' = '1
would result in this query being executed:
<cfquery>
select * from tableName
where fieldName = 'someValue'; DELETE FROM tableName WHERE '1' = '1'
</cfquery>
I'um using Gnome Data Access (libgda) to access a database in a C program.
I use the GdaSqlBuilder to build my queries.
Here is an exemple code for adding an equal condition on a field for a request :
GdaSqlBuilderId add_equal_condition(char* m_name, GValue* m_value)
{
GdaSqlBuilderId name, value, condition;
name = gda_sql_builder_add_id(builder, m_name);
value = gda_sql_builder_add_expr_value(builder, NULL, m_value);
condition = gda_sql_builder_add_cond(builder, GDA_SQL_OPERATOR_TYPE_EQUAL, name, value, 0);
return condition;
}
Does libgda protect itself against SQL injections or do I need to sanitize the input myself before I pass it to GDA ?
Thanks in advance for your answers.
This is explained in the foreword:
When creating an SQL string which contains values (literals), one can
be tempted (as it is the easiest solution) to create a string
containing the values themselves, execute that statement and apply the
same process the next time the same statement needs to be executed
with different values. This approach has two major flaws outlined
below which is why Libgda recommends using variables in statements
(also known as parameters or place holders) and reusing the same
GdaStatement object when only the variable's values change.
https://developer.gnome.org/libgda/unstable/ch06s03.html
Even if the current version is not vulnerable, that does not mean that every future version will not be vulnerable. You should always, without any exception, take care of what a user provides.
Same goes for interfaces from other systems of any kind. This is not limited to SQLi and not a question of SQLi or the libraries you use. You are responsible that a user can only enter the kind data that you want him/her to enter or reject it otherwise. You can not rely on other code to do that for you.
Generally: Nothing can protect itself completly against a certain type of attack. It will always be limited to the attackvectors known at the time of writing.
I have an ABAP class method, say, select_something. select_something has an exporting parameter, say, et_result. et_result is of type standard table because the type of et_result cannot be determined until runtime.
The method sometimes gives a short dump saying With ABAP/4 Open SQL array select, the output table is too small at "select * into table et_result from (lv_tablename) where..."
Error analysis:
......in this particular case, the database table is 3806 bytes wide, but the internal table is only 70 bytes wide.
I tried "any table" too and the error is the same.
You could return a data reference. Your query will no longer fail, and you can assign the data to a correctly typed field symbol afterwards.
" Definition
class-methods select_all
importing
!tabname type string
returning
value(results) type ref to data.
...
...
" Implementation
method select_all.
data dref type ref to data.
create data dref type standard table of (tabname).
field-symbols <tab> type any table.
assign dref->* to <tab>.
select * from (tabname) into table <tab>.
get reference of <tab> into results.
endmethod.
Also, I agree with #vwegert that dynamic queries (and programming for that matter) should be avoided when possible.
What you're trying to do looks horribly wrong on many levels. NEVER use SELECT FROM (whatever) unless someone points a gun at your head AND the door is locked tight. You'll loose every kind of static error checking the system might be able to provide you with. For example, the compiler will no longer be able to tell you "Hey, that table you're reading from is 3806 bytes wide." It simply can't tell, even if you use constants. You'll find that out the hard way, producing short dumps, especially when switching between unicode and NUC systems, quite likely some in production systems. No fun.
(Actually there are a few - very very VERY few - good uses for dynamic table names in the SELECT statement. I need them about once every two to three years, and I code quite a lot weird stuff. Just avoid them wherever you can, even at the cost of writing more code. It's just not worth the trouble fixing broken stuff later.)
Then, changing the generic formal parameter type does not do anything to the type of the actual parameter. If you pass a STANRDARD TABLE OF mandt WITH DEFAULT KEY to your method, that table will have lines of 3 characters. It will be a STANDARD TABLE, and as such, it will also be an ANY TABLE, and that's about it. You can twist the generic types anywhere you like, there's no way to enforce correctness using generic types the way you use them. It's up to the caller to make sure that all the right types are used. That's a bad way to fly.
First off, I agree with vwegert's response, try to avoid dynamic sql selections if you can
That said, check the short dump. If the error is an exception class, you can wrap the SELECT statement in a try/catch block and at least stop it from dumping.
You can also try "INTO CORRESPONDING FIELDS OF TABLE et_result". If ET_RESULT is dynamic, you might have to cast it into the proper structure using RTTS. This might give you some ideas...
Couldn't agree more to vwegert, but if there is absolutely no other way (and there usually is) of performing your task than using dynamic select statements and dynamically typed parameters, do some checks on the type of the table and the parameter at runtime.
Use CL_ABAP_TYPEDESCR and its subclasses to do so.
This way, you can handle errors at runtime without your program dumping,
But as vwegert said, this dynamic stuff is pure evil and will most certainly break at some point during runtime. Adding the necessary error handling will most likely be a lot more work and a lot harder than redesigning your code to none dynamic SQL and typed parameters
Can someone explain if not including the cfsqltype for cfqueryparam is still useful for SQL injection protection? And also what actually happens with cfqueryparam with the cfsqltype and w/o cfsqltype.
<!--- without cfsqltype--->
<cfqueryparam value="#someValue#">
<!--- with cfsqltype--->
<cfqueryparam value="#someValue#" cfsqltype="cf_sql_char">
To get a good idea of what cfsqltype is likley doing under the hood take a look at the Java / JDBC PreparedStatement class: http://download.oracle.com/javase/6/docs/api/java/sql/PreparedStatement.html
You will notice various setInt, setDate, etc. methods - my understanding is that the cfsqltype is matched up with a corresponding method when it creates the prepared statement.
If you specify a type then ColdFusion needs to be able to cast the variable into that type, and if it can't it will throw an exception before sending the query to the database.
When you omit the cfsqltype it probably calls either setObject or setString. The behavior of what happens next is dependent on the JDBC driver you are using at this point. I've seen some cases where omiting the type can cause an error even when you are passing in valid variables, one that comes to mind is working with date and datetime on MySQL.
Another thing to consider is that if you omit the cfsqltype on let's say an integer field, but you pass a non integer value, ColdFusion could have thrown the exception before connecting to the database and sending the query if you specified the cfsqltype, but without it you wasting the DB connection and execution time on the database server.
One of the benefits of cfqueryparam is type checking before values are sent to your database. For example, you specify cf_sql_integer, CF not only verifies the value is numeric, but that it is a whole number within a specific range. When you omit the cfsqltype, CF will use cf_sql_char. So you obviously lose type checking for things like dates and numbers.
Personally, I think you should supply a cfsqltype. However, even if you did not, using cfqueryparam means CF uses bind variables. A side benefit of bind variables is helping to protect your queries against sql injection. So in that sense, it is still a good thing.
I think it is useful but as "validation" not "sql query injection
protection".
Update: No, it still applies. The protection comes from using bind variables. Since CF will still use bind variables, even without a type, I believe the basic sql injection protection still applies.
That said, using cf_sql_char on something other than a char column may force your database to perform an implicit conversion to the data type of the target column, sometimes producing unexpected results. So generally I would say you should specify a cfsqltype.