Question

As I understand, most SQL injection is done by inserting a malicious piece of SQL and commenting out the remainder of the query.

Of course this would only be an additional layer on top of known and proven best practices but is it possible to simply change the comment tags from the defaults of #, --, and /*...*/ to something a little less attacker friendly as in noInject (remainder of comment here)? so that the query throws an error rather than completing?

And further by changing the ; delimiter to something like eol or \|/

I'm using MySQL, but as a general question would this be worth the effort?

Was it helpful?

Solution

Even if such a change were possible (which it's not, unless you fork the MySQL source code and compile your own—not feasible with SQL Server) and would cause some injections to fail, it wouldn't catch them all.

Let's imagine a PHP-driven website through which users can view their medical records. To enable the user to filter his records for those related to a particular illness, one permits the illness to be specified by its id as a query parameter:

http://www.example.com/health/fetchmyrecords.php?illness=123

The developer, relying on the fact that the server has been modified, makes no further effort to protect against SQL injection, so then does something like this:

print_r(
  $pdo->query("
    SELECT *
    FROM   health_records
    WHERE  user    = $_SESSION[uid]
       AND illness = $_GET[illness]
  ")
  ->fetchAll()
);

Now suppose that user 987 requests the following URI:

http://www.example.com/health/fetchmyrecords.php?illness=123+OR+1%3D1

Consequently the RDBMS will receive the following query:

SELECT *
FROM   health_records
WHERE  user    = 987
   AND illness = 123 OR 1=1

SQL successfully injected! In this particular example the injection is fatal, since the RDBMS will parse that WHERE clause as:

WHERE (user = 987 AND illness = 123) OR 1=1

…so it will actually return every health record of every user in the database!

Good luck affording the legal fees that will come out of that. It's a reasonable guess that your business will collapse, your personal finances will be ruined, your house will be repossessed, your wife will leave you, your kids won't speak to you and your cat will run away!

The explanation (for the injection, not your cat's disappearance) is that none of the tokens that you modified were required!

But let's suppose that you went further and modified every single token in order that any previously valid SQL injection would now result in an error: you still haven't protected against SQL injection, as an attacker need merely alter his attack to use your customised SQL variant. You have achieved little more than security through obscurity, which is not secure at all.

As @Nanne has stated, parameterising your queries is the correct way to defeat SQL injection attacks (at least, those that attack literal values—if you accept untrusted values into other language tokens you will need to protect yourself in some other way, although that's a rare requirement and well beyond the scope of this answer).

OTHER TIPS

As I understand, most SQL injection is done by inserting a malicious piece of SQL and commenting out the remainder of the query.

Your assumption is plain wrong.

Although it is required that the resulting SQL is valid, using comments is just one (and probably the easiest) way of skipping parts of the SQL. However, one can still build perfect SQL via injection without any comments.

Better stick to the known and proven best practices.

It is not worth the effort. The best way to prevent this kind of injection is to separate code (SQL) from content (your data).

The data is the stuff they put the comments in, so if you know is may not be SQL, you don't have a problem.

This is called parametrization, and that is your first step to winning the internet :)

What you do is tell the function that puts stuff in SQL that

  1. this is my code (sql), for instance SELECT * FROM stuff WHERE something = ?
  2. the ? means: here comes data!
  3. You then say what dat should be on the place of the ? in a functions that is made to do that.
  4. ...
  5. profit!

No, it is not possible to change the statement delimiter in MySQL multi-query. The DELIMITER command only affects the statement delimiter in the mysql client, not in server-side dynamic SQL parsing. So DELIMITER is not recognized by the server, and therefore is not usable as you write code in any application language like PHP, Java, Ruby, Python, etc. DELIMITER works only in SQL scripts you run with the mysql client.

http://dev.mysql.com/doc/refman/5.6/en/c-api-multiple-queries.html says:

MySQL 5.6 also supports the execution of a string containing multiple statements separated by semicolon (“;”) characters.

But the presence of semicolons in multi-query syntax is far from the only way, or even the most common way, that SQL injection can harm your system. Even if you could change the delimiter in dynamic SQL, it wouldn't be much of a defense.

Use the usual recommended defenses, and semicolons won't be a threat anyway:

  • Parameterized queries
  • Whitelisting identifiers
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top