Joel Coehoorn
Joel Coehoorn

Reputation: 415705

Enforce query restrictions

I'm building my own clone of http://statoverflow.com/sandbox (using the free controls provided to 10K users from Telerik). I have a proof of concept available I can use locally, but before I open it up to others I need to lock it down some more. Currently I run everything through a stored procedure that looks something like this:

CREATE PROCEDURE WebQuery 
    @QueryText nvarchar(1000)
AS
BEGIN
    -- no writes, so no need to lock on select
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

    -- throttles
    SET ROWCOUNT 500 
    SET QUERY_GOVERNOR_COST_LIMIT 500

    exec (@QueryText)

END

I need to do two things yet:

  1. Replace QUERY_GOVERNOR_COST_LIMIT with an actual rather than estimated timeout, so no query runs longer than say 2 minutes.
  2. Right now nothing stops users from just putting their own 'SET ROWCOUNT 50000;' in front of their query text to override my restriction, so I need to somehow limit the queries to a single statement or (preferrably) disallow the SET commands inside the exec function.

Any ideas?

Upvotes: 3

Views: 198

Answers (3)

Remus Rusanu
Remus Rusanu

Reputation: 294237

You really plan to allow users to run arbitrary Ad-Hoc SQL? Only then can a user place in a SET to override your restrictions. If that's the case, you're best bet is to do some basic parsing using lexx/yacc or flex/bison (or your favorite CLR language tree parser) and detect invalid SET statements. Are you going to allow SET @variable=value though, which syntactically is a SET...

If you impersonate low privileged users via EXECUTE AS make sure you create an irreversible impersonation context, so the user does not simply execute REVERT and regain all the privileges :) You also must really understand the implications of database impersonation, make sure you read Extending Database Impersonation by Using EXECUTE AS.

Another thing to consider is deffering execution of requests to a queue. Since queue readers can be calibrated via MAX_QUEUE_READERS, you get a very cheap throttling. See Asynchronous procedure execution for a related article how to use queues to execute batches. This mechanism is different from resource governance, but I've seen it used to more effect that the governor itself.

Upvotes: 3

MartW
MartW

Reputation: 12538

On a very basic level, how about blocking any statement that doesn't start with SELECT? Or will other query starts be supported, like CTE's or DECLARE statements? 1000 chars isn't too much room to play with, but i'm not too clear what this is in the first place.

UPDATED

Ok, how about prefixing whatever they submit with SELECT TOP 500 FROM (

and appending a ). If they try to do multiple statements it'll throw an error you can catch. And to prevent denial of service, replace their starting SELECT with another SELECT TOP 500.

Doesn't help if they've appended an ORDER BY to something returning a million rows, though.

Upvotes: 0

David Andres
David Andres

Reputation: 31781

Throwing this out there:

The EXEC statement appears to support impersonation. See http://msdn.microsoft.com/en-us/library/ms188332.aspx. Perhaps you can impersonate a limited user. I am looking into the availability of limitations that may prevent SET statements and the like.

Upvotes: 0

Related Questions