Tell me more ×
IT Security Stack Exchange is a question and answer site for IT security professionals. It's 100% free, no registration required.

Are prepared statements actually 100% safe against SQL injection, assuming all user-provided parameters are passed as query bound parameters?

Whenever I see people using the old mysql_ functions on StackOverflow (which is, sadly, way too frequently) I generally tell people that prepared statements are the Chuck Norris (or Jon Skeet) of SQL injection security measures.

However, I've never actually seen any documentation that categorically states "this is 100% safe". My understanding of them is that they separate the query language and parameters all the way to the front door of the server, which then treats them as separate entities.

Am I correct in this assumption?

share|improve this question

1 Answer

up vote 11 down vote accepted

Guarantee of 100% safe from SQL injection? Not going to get it (from me).

In principle, your database (or library in your language that is interacting with the db) could implement prepared statements with bound parameters in an unsafe way susceptible to some sort of advanced attack, say exploiting buffer overflows or having null-terminating characters in user-provided strings, etc. (You could argue that these types of attacks should not be called SQL injection as they are fundamentally different; but that's just semantics).

I have never heard of any of these attacks on prepared statements on real databases in the field and strongly suggest using bound parameters to prevent SQL injection. Without bound parameters or input sanitation, its trivial to do SQL injection. With only input sanitation, its quite often possible to find an obscure loophole around the sanitation.

With bound parameters, your SQL query execution plan is figured out ahead of time without relying on user input, which should make SQL injection not possible (as any inserted quotes, comment symbols, etc are only inserted within the already compiled SQL statement).

The only argument against using prepared statements is you want your database to optimize your execution plans depending on the actual query. Most databases when given the full query are smart enough to do an optimal execution plan; e.g., if the query returns a large percentage of the table, it would want to walk through the entire table to find matches; while if its only going to get a few records you may do an index based search [1].

share|improve this answer
Slightly off the security side, but SQL server provides option (recompile) to force a new compilation and it will use the current parameter values when choosing a plan. Although I don't know for sure, I expect other RDBMS provide a similar function. So no excuse for not using parameterised queries! – pipTheGeek May 21 '12 at 17:52
Exactly what I'd figured, then. As close to 100% as you can guarantee, ignoring implementation exploits. – Polynomial May 21 '12 at 18:13
@pipTheGeek - Interesting. I use postgresql as my rdbms of choice (free software) and cannot find this option, and MySQL specifically says they do not support 'WITH RECOMPILE'. I think you may be able to do something similar in postgres if you first wrote a stored procedure and then did a prepared statement calling it--but not sure it would recompile execution plan (would need to check). – dr jimbob May 21 '12 at 18:34
Sorry, I'm a bit dense today. How does Lateral SQL Injection (databasesecurity.com/dbsec/lateral-sql-injection.pdf) fit into this? – Bruce Ediger May 22 '12 at 15:45
2  
@BruceEdiger - Lateral SQL injection in your link can't happen if you use prepared statements with bound parameters. In pseudocode, if one defines sql_str = "SELECT name FROM all_objects WHERE created = ?" and then did prepared_stmt = db_cursor.prepare(sql_str), prepared_stmt.execute_with_param(SYSDATE), you can't use SYSDATE to inject code to alter the execution plan as the execution plan was determined in the prepare() step independent of SYSDATE's value. (Unless there's another vulnerability). The lateral flaw is doing naive string processing to construct an SQL statement. – dr jimbob May 22 '12 at 16:10
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.