21

I'm testing for resilience against injection attacks on an SQL Server database.

All table names in the db are lower case, and the collation is case-sensitive, Latin1_General_CS_AS.

The string I can send in is forced to uppercase, and can be a maximum of 26 characters in length. So I can't send in a DROP TABLE because the table name would be in uppercase and thus the statement would fail due to the collation.

So - what's the maximum damage I could do in 26 characters?

EDIT

I know all about parameterised queries and so forth - let's imagine that the person who developed the front end that builds the query to send in didn't use params in this case.

I'm also not trying to do anything nefarious, this is a system built by somebody else in the same organisation.

  • 1
    Are we imagining or are you actually pen testing and have requirements that disallow you to avoid injection? Are you looking for a way to break his lack of security? – LowlyDBA Jan 30 '18 at 14:56
  • 41
    Why is it even an option that the door is to be left open? This seems like you've already spent more time contemplating this than it would cost to bolt the door shut. I sense this as a fruitless exercise - if you come up with 10 vulnerabilities, they'll say, we'll plug those 10 vulnerabilities, and there certainly won't be an 11th. This is where "cleansing" strings got us. /facepalm – Aaron Bertrand Jan 30 '18 at 15:23
  • 5
    This is insanely vague and arbitrary question, and it can't even theoretically be addressed. There other native mitigating features of SQL Injection (permissions, sandbox, firewalls etc), and you'd have to account for all of those things in order to answer this question. – Evan Carroll Jan 30 '18 at 15:47
  • 2
    What's enforcing the 26 character limit? The application? – Jonathan Fite Jan 30 '18 at 17:48
  • 7
    Stop it. Just stop it. If parameterized queries are remotely an option, use them. If someone else doesn't know how to use them, find a decent resource and have them read it. If they don't listen, notify a manager or supervisor they're producing critical security vulnerabilities (A nondestructive demo wouldn't hurt.) and refuse to be educated. – jpmc26 Jan 30 '18 at 23:13
38

Easy:

GRANT EXECUTE TO LowlyDBA

Or, I guess in this case it'd be

grant execute to lowlydba 

Take your pick of variations on this.

In all likelihood you may be able to test this now against your current system, but any number of small changes in the database over time could invalidate your testing. The character string could change, someone could create a lower case stored procedure that has destructive potential - anything. You can never say with 100% confidence that there isn't a destructive 26 character attack someone could construct.

I suggest you find a way to make the developer follow basic industry standard best security practices, if only for your own sake as someone who I presume is at least partially responsible should security breaches happen.

Edit:

And for maliciousness/fun, you could try enabling every trace flag. This would be interesting to observe. Feels like a blog post Brent Ozar would make...

DBCC TRACEON(xxxx, -1)
  • 1
    Besides enabling trace flags: changing various random settings: SET LOCK_TIMEOUT 0;, SET LANGUAGE Malaysian;, SET ANSI_NULLS OFF: ... – ypercubeᵀᴹ Jan 30 '18 at 16:05
  • 2
    @ypercubeᵀᴹ they would all only affect your own session. – Martin Smith Jan 30 '18 at 16:06
  • 2
    @MartinSmith thnx. If SET affects only session settings, how are satabase and server settings changed (ALTER DATABASE ...; ?) DROP DATABASE ..; would inflict more damage then, if it succeeded ;) – ypercubeᵀᴹ Jan 31 '18 at 13:04
  • 1
    Alter database and sp_configure mostly for DB and Server level settings. Though you might hit the 26 character limit with these. Also these specific settings at database level are only used if the client connection doesn't set them. And by default most or all do. – Martin Smith Jan 31 '18 at 13:24
  • 7
    I resemble that remark. – Brent Ozar Feb 2 '18 at 19:20
22

The SHUTDOWN command or KILL Command (pick a random number over 50) both take significantly less than 26 characters, though the account executing the application queries hopefully doesn't have sufficient permissions to run these.

  • Usually the account wouldn't need drop table either... – Greg Jan 30 '18 at 21:45
  • 3
    @Greg yep. Though you can surmise an environment that is considering allowing SQL injection as long as the length is short isn't following security best practices and the accounts may well not be configured with minimal permissions. – Martin Smith Jan 30 '18 at 22:08
14

You could create a table that you then fill up until the end of time or disk space runs out whichever comes first.

declare @S char(26);

set @S = 'create table t(c char(99))';
exec (@S);

set @S = 'insert t values('''')'
exec (@S);

set @S = 'insert t select c from t'
exec (@S);
exec (@S);
exec (@S);
exec (@S);
-- etc
  • 19
    @AlanB Well, then you would need something that prevents me from exploiting the weakness more than once. – Mikael Eriksson Jan 30 '18 at 15:12
  • 1
    tarnations... while 1=1 insert t values('') is 30 ... create table x(i int) => while 1=1 insert t select 0 is 27 – WernerCD Jan 30 '18 at 18:39
  • 1
    Could you use this to build up a longer command than the character limit, and then execute that? – Lawtonfogle Jan 30 '18 at 18:43
  • 1
    @MartinSmith I thought I would just leave like this but now I just have to try it :). Will let you know if I figure it out. – Mikael Eriksson Jan 30 '18 at 19:01
  • 7
    @WernerCD x:insert t select 0 GOTO x is exactly 26 though. – Martin Smith Jan 31 '18 at 18:18
4

Depending on your definition of damage, you could run this: WAITFOR DELAY '23:59' To be truly evil, you could use a load-testing tool to run that from 32,768 clients.

3

Variation based on @MikaelEriksson's answer and @MartinSmith's reply to my initial comment:

declare @S char(26);

set @S = 'create table x(i int)';
exec (@S);

Initially I had tried to do a WHILE statement, but the best I could do was 27 characters:

set @S = 'while 1=1 insert t select 0'; -- fails at 27 characters
exec (@S);

But Martin pointed out GOTO:

set @S = 'x:insert t select 0 GOTO x';
exec (@S);

GOTO... the root of all evil and creator of an infinite-loop insert statement in 26 characters.

With that said... it might be advantageous to stick with CHAR(99) instead of int as that would use more space. Other options either use longer names and would smash the 26 character limit... or use less storage space per row.

Full Test Code:

declare @S char(26);
set @S = 'drop table t;';
exec (@S);
GO

declare @S char(26);

set @S = 'create table t(c CHAR(99))';
exec (@S);

set @S = 'x:insert t select 0 GOTO x';
exec (@S);
GO
  • 1
    set @S = 'x:insert t;select 0;GOTO x'; for future compatibility of your injection attack ;) – ypercubeᵀᴹ Jan 31 '18 at 19:13
  • @ypercubeᵀᴹ You added two ;s... the second one is fine - replaces a space and is functional if not needed. The first one breaks the query - separates the INSERT statement from the SELECT statement. – WernerCD Jan 31 '18 at 19:19
  • Ah yes. That's what happens when one doesn't use separators! We don't know where each query ends and when the next starts! – ypercubeᵀᴹ Jan 31 '18 at 20:54
  • 1
    @WarnerCD I know. It was more a joke on the depreciating procedure in SQL Server. It seems to take for ever. Still, it's good practice to use semicolons between statements and not only where it is required. – ypercubeᵀᴹ Feb 1 '18 at 1:16
  • 2
    @yper I doubt that it will ever be enforced. Probably there is a ton of legacy code that would need missing semi colons added with no particular business value of doing so. And it might be embedded in applications difficult or not possible to update. – Martin Smith Feb 1 '18 at 12:41
0
XP_CMDSHELL 'SHUTDOWN -PF'

Depending on how damaging you consider a power-down to be. :-)

This does require xp_cmdshell to be enabled on the server, something that is not the case for the last few version of SQL Server. It also requires that the service account have the shutdown right, which it may or may not have.

Enabling xp_cmdshell probably goes outside your 26 character limit. Would you allow multiple injections?

SP_CONFIGURE 'SHOW ADV',1

RECONFIGURE

SP_CONFIGURE 'XP', 1

RECONFIGURE
  • 1
    The EXEC is only optional if this is the first statement in the batch. Which probably won't be the case here. – Martin Smith Feb 1 '18 at 12:32
  • @Martin Smith, good comment. EXEC adds 5 characters to each procedure call line, which pushes most of them over 26 characters. I wonder if CREATE ALIAS would help here? – Greenstone Walker Feb 1 '18 at 19:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.