News for hackers. Stuff that matters.
Re:No-SQL injection in Mongo PHP by tptacek on Monday March 07, 2011 @07:46PM (#2299361)
For whatever it's worth, even in parameterized SQL queries, the query structure isn't always entirely fixed. There are injectable parameterized query constructs, and some of them are fairly common.
Re:No-SQL injection in Mongo PHP by bmm6o on Tuesday March 08, 2011 @02:16PM (#2302185)
I haven't heard of this before. Can you link to an example?
Re:No-SQL injection in Mongo PHP by tptacek on Tuesday March 08, 2011 @02:21PM (#2302206)
On-the-fly table selection is a simple example, but there are more subtle examples that happen even more often.
Re:No-SQL injection in Mongo PHP by bmm6o on Tuesday March 08, 2011 @05:15PM (#2302812)
Unless I'm misunderstanding you, changing the table doesn't affect the shape of the parse tree. (and I'm not trying to be pedantic - I'm genuinely curious about this).
Re:No-SQL injection in Mongo PHP by btilly on Tuesday March 08, 2011 @07:03PM (#2303156)
The issue isn't how you parse the query. The issue is how you choose to execute it.

I'm not sure what tptacek is thinking, but here is an important case where you really want the execution path to change.

Tables often have a very uneven distribution of data. This can mean that the right query plan will depend on the data provided. Consider the following query:

  SELECT ...
  FROM lease l
    JOIN property p
      ON p.id = l.property_id
    JOIN management_company c
      ON c.id = p.management_company_id
  WHERE l.created >= ?
    AND l.created < ?
    AND c.name = ?;
Pretty straightforward query, right? Now here is the question, should the query plan start by filtering leases on date then flow forward to finally filter on the management company, or by getting the right management company and then flow backwards to filter on dates.

It turns out that there is no right answer. You want to start with whichever restriction eliminates the most records, quickest. If the date range is wide, we want to start with the management company. If the date range is narrow, we want to start with that.

So let us simplify our life:

  SELECT ...
  FROM lease l
    JOIN property p
      ON p.id = l.property_id
    JOIN management_company c
      ON c.id = p.management_company_id
  WHERE l.created >= '2011-02-01'
    AND l.created < '2011-03-01'
    AND c.name = ?;
There is still no right answer! Let's suppose some company, call it 'AIMCO', has a huge number of properties with a lot of lease volume while other companies generally have 1-5. Then it is better to filter on dates first for 'AIMCO', and better to filter on the company first for anything else. Getting the order wrong gives an order of magnitude performance difference. (This is a real life example. I really did have a bug that basically read, "Make this report run for AIMCO." And this was exactly the problem.)

Most databases will pick one query plan and go with it. But Oracle allows you to turn on Adaptive Cursor Sharing. With this it will analyze the data, see that AIMCO should get special treatment, and actually execute a different query plan if you passed in 'AIMCO' than if you passed in something else.

So now you have a data dependent query plan.

Re:No-SQL injection in Mongo PHP by bmm6o on Tuesday March 08, 2011 @07:42PM (#2303270)
Ok, so your example consists of switching between semantically equivalent queries in the application layer to compensate for weaknesses in the DBMS execution planner. I get that CPU time is a valuable resource and you don't want to open yourself up to DOSing and all, but this isn't really anything like SQL injections. The attacker still can't subvert the structure of the query - changing the structure of the query was the solution to the problem.
Re:No-SQL injection in Mongo PHP by btilly on Tuesday March 08, 2011 @08:03PM (#2303320)
Ok, so your example consists of switching between semantically equivalent queries in the application layer to compensate for weaknesses in the DBMS execution planner.

Not quite. My example consists of the DBMS execution planner deciding that it will switch between different semantically equivalent query plans depending on the parametrized data passed. This switch should not be noticed in the application layer.

Back to the main thread, I suspect that you are interpreting tptacek as saying something he didn't. You seem to be looking for a potential security flaw. But he didn't ever say that there was one. He only said that the query structure can vary with the parameters passed to a parametrized query. I just described one way that this can happen.

Re:No-SQL injection in Mongo PHP by tptacek on Tuesday March 08, 2011 @11:43PM (#2303829)
Yeah these are great comments and all but I'm just saying that, last time I checked, you can't bind a table name as a parameter in the MySQL protocol; if your table names change at runtime based on input, you're back to concatenated queries.
Re:No-SQL injection in Mongo PHP by btilly on Wednesday March 09, 2011 @12:15AM (#2303929)
Oops, I had misunderstood. You're right. It makes no sense to bind table names as parameters, because if you do then the database really has no information from which it can generate possible query plans from.

The way that I solved that particular problem in the past is that I used a templating system to generate my SQL. User input was allowed in ifs in my templates, and as parameters for my queries, and that was it. At no point did I trust user data inside of my SQL.

Re:No-SQL injection in Mongo PHP by rbanffy on Wednesday March 09, 2011 @07:46AM (#2304679)
> you're back to concatenated queries.

Wouldn't it be safer to use a switch statement?

Re:No-SQL injection in Mongo PHP by bmm6o on Wednesday March 09, 2011 @12:31PM (#2305593)
In theory, it should be possible to enumerate your SQL queries ahead of time rather than ever generating one on the fly. In practice, that could be a huge pain of the O(2^n) variety, depending on the application type.
Re:No-SQL injection in Mongo PHP by rbanffy on Wednesday March 09, 2011 @01:23PM (#2305802)
I assume the choice of table names or query templates in the case mentioned (make a report for atypical client C run faster) would be limited to a handful of possible query templates.