D. Base
D. Base

Reputation: 9

What pattern to check on an SQL query for possible injection?

I want to detect possible SQL injection atack by checking the SQL query. I am using PDO and prepared statement, so hopefully I am not in the danger of getting attacked by someone. However, what I want to detect is the possibility of input/resulting query string that may become a dangerous query. For example, my app--properly--will never generate "1=1" query, so I may check the generated query string for that, and flag the user/IP producing that query. Same thing with "drop table", but maybe I can check only by looping the input array; or maybe I should just check to the generated query all over again. I am using MySQL, but pattern for other drivers are also appreciated.

I have read RegEx to Detect SQL Injection and some of the comments are heading in this direction. To my help, I'm developing for users that rarely use English as input, so a simple /drop/ match on the query may be enough to log the user/query for further inspection. Some of the pattern I found while researching SQL injection are:

All of the above are easier to detect by looping the input values before the query string is generated because they haven't been escaped. But how much did I miss? (a lot, I guess) Any other obscure pattern I should check? What about checking the generated query? Any pattern that may emerge?

tl;dr: What pattern to match an SQL query (MySQL) to check for possible injection? I am using PDO with prepared statement and value binding, so the check is for logging/alert purposes.

Upvotes: -2

Views: 1358

Answers (3)

Rick James
Rick James

Reputation: 142503

Not possible.

You will spend the rest of your life in an armament race -- you build a defense, they build a better weapon, then you build a defense against that, etc, etc.

  • It is probably possible to write a 'simple' SELECT that will take 24 hours to run.
  • Unless you lock down the tables, they can look, for example, at the encrypted passwords and re-attack with a root login.
  • If you allow any type of string, it will be a challenge to handle the various combinations of quoting.
  • There are nasty things that can be done with semi-valid utf8 strings.
  • And what about SET statements.
  • And LOAD DATA.
  • And Stored procs.

Instead, decide on the minimal set of queries you allow, then parameterize that so you can check, or escape, the pieces individually. Then build the query.

Upvotes: 0

revo
revo

Reputation: 48751

But how much did I miss?

You guess right. Creating a huge blacklist wouldn't make your code immune. This approach is history. The other questions follow the same idea.

Your best bets are:

  • Validating input data (input doesn't necessarily come from an external party)
  • Using prepared statements.

Few steps but bulletproof.

Upvotes: 1

O. Jones
O. Jones

Reputation: 108806

In my shop we have two rules.

  1. Always use parameters in SQL queries.
  2. If for some reason you can't follow rule one, then every piece of data put into a query must be sanitized, either with intval() for integer parameters or an appropriate function to sanitize a string variable according to its application data type. For example, a personal name might be Jones or O'Brien or St. John-Smythe but will never have special characters other than apostrophe ', hyphen -, space, or dot. A product number probably contains only letters or numbers. And so forth.

If 2 is too hard follow rule 1.

We inspect code to make sure we're doing these things.

Upvotes: 2

Related Questions