mardi 5 mai 2015

Why does MySQL permit non-exact matches in SELECT queries?

Here's the story. I'm testing doing some security testing (using zaproxy) of a Laravel (PHP framework) application running with a MySQL database as the primary store for data.

Zaproxy is reporting a possible SQL injection for a POST request URL with the following payload:

id[]=3-2&enabled[]=on

Basically, it's an AJAX request to turn on/turn off a particular feature in a list. Zaproxy is fuzzing the request: where the id value is 3-2, there should be an integer - the id of the item to update.

The problem is that this request is working. It should fail, but the code is actually updating the item where id = 3.

I'm doing things the way I'm supposed to: the model is retrieved using Eloquent's Model::find($id) method, passing in the id value from the request (which, after a bit of investigation, was determined to be the string "3-2"). AFAIK, the Eloquent library should be executing the query by binding the ID value to a parameter.

I tried executing the query using Laravel's DB class with the following code:

$result = DB::select("SELECT * FROM table WHERE id=?;", array("3-2"));

and got the row for id = 3.

Then I tried executing the following query against my MySQL database:

SELECT * FROM table WHERE id='3-2';

and it did retrieve the row where id = 3. I also tried it with another value: "3abc". It looks like any value prefixed with a number will retrieve a row.

So ultimately, this appears to be a problem with MySQL. As far as I'm concerned, if I ask for a row where id = '3-2' and there is no row with that exact ID value, then I want it to return an empty set of results.

I have two questions:

  1. Is there a way to change this behaviour? It appears to be at the level of the database server, so is there anything in the database server configuration to prevent this kind of thing?

  2. This looks like a serious security issue to me. Zaproxy is able to inject some arbitrary value and make changes to my database. Admittedly, this is a fairly minor issue for my application, and the (probably) only values that would work will be values prefixed with a number, but still...

Aucun commentaire:

Enregistrer un commentaire