sqlmap 0.6.3-rc4: minor enhancement to be able to specify extra HTTP headers

by providing option --headers. By default Accept, Accept-Language and
Accept-Charset headers are set.
Added support to get the injection payload prefix and postfix from user.
Minor bug fix to exclude image files when parsing (-l) proxies log files.
Minor code adjustments.
Updated documentation.
This commit is contained in:
Bernardo Damele 2008-12-08 21:24:24 +00:00
parent 15542d2772
commit 9dbad512f1
15 changed files with 365 additions and 232 deletions

View File

@ -27,10 +27,11 @@ sqlmap (0.6.3-1) stable; urgency=low
* Minor enhancemet to support also --regexp, --excl-str and --excl-reg * Minor enhancemet to support also --regexp, --excl-str and --excl-reg
options rather than only --string when comparing HTTP responses page options rather than only --string when comparing HTTP responses page
content; content;
* Minor enhancement to be able to specify extra HTTP headers by providing
option --headers. By default Accept, Accept-Language and Accept-Charset
headers are set;
* Minor improvement to be able to provide CU (as current user) as user * Minor improvement to be able to provide CU (as current user) as user
value (-U) when enumerating users privileges or users passwords; value (-U) when enumerating users privileges or users passwords;
* Minor improvement to set by default in all HTTP requests the standard
client HTTP headers (Accept, Accept-Encoding, etc);
* Minor improvements to sqlmap Debian package files: sqlmap uploaded * Minor improvements to sqlmap Debian package files: sqlmap uploaded
to official Debian project repository, on queue at the moment; to official Debian project repository, on queue at the moment;
* Minor improvement to use Python psyco (http://psyco.sourceforge.net/) * Minor improvement to use Python psyco (http://psyco.sourceforge.net/)

View File

@ -377,6 +377,7 @@ Options:
--referer=REFERER HTTP Referer header --referer=REFERER HTTP Referer header
--user-agent=AGENT HTTP User-Agent header --user-agent=AGENT HTTP User-Agent header
-a USERAGENTSFILE Load a random HTTP User-Agent header from file -a USERAGENTSFILE Load a random HTTP User-Agent header from file
--headers=HEADERS Extra HTTP headers '\n' separated
--auth-type=ATYPE HTTP Authentication type, value: Basic or Digest --auth-type=ATYPE HTTP Authentication type, value: Basic or Digest
--auth-cred=ACRED HTTP Authentication credentials, value: name:password --auth-cred=ACRED HTTP Authentication credentials, value: name:password
--proxy=PROXY Use a HTTP proxy to connect to the target url --proxy=PROXY Use a HTTP proxy to connect to the target url
@ -386,8 +387,14 @@ Options:
Injection: Injection:
-p TESTPARAMETER Testable parameter(s) -p TESTPARAMETER Testable parameter(s)
--string=STRING String to match in page when the query is valid
--dbms=DBMS Force back-end DBMS to this value --dbms=DBMS Force back-end DBMS to this value
--prefix=PREFIX Injection payload prefix string
--postfix=POSTFIX Injection payload postfix string
--string=STRING String to match in page when the query is valid
--regexp=REGEXP Regexp to match in page when the query is valid
--excl-str=ESTRING String to be excluded before calculating page hash
--excl-reg=EREGEXP Regexp matches to be excluded before calculating page
hash
Techniques: Techniques:
These options can be used to test for specific SQL injection technique These options can be used to test for specific SQL injection technique
@ -1263,11 +1270,66 @@ back-end DBMS: MySQL >= 5.0.0
</P> </P>
<H3>String match</H3> <H3>Force the database management system name</H3>
<P>Option: <CODE>--string</CODE></P> <P>Option: <CODE>--dbms</CODE></P>
<P>By default the distinction of a True query by a False one (basic concept <P>By default sqlmap automatically detects the web application's back-end
database manangement system.
At the moment the fully supported database management system are four:</P>
<P>
<UL>
<LI>MySQL</LI>
<LI>Oracle</LI>
<LI>PostgreSQL</LI>
<LI>Microsoft SQL Server</LI>
</UL>
</P>
<P>It is possible to force the name if you already know it so that sqlmap
will skip the fingerprint with an exception for MySQL to only identify if
it is MySQL &lt; 5.0 or MySQL &gt;= 5.0.
To avoid also this check you can provide instead <CODE>MySQL 4</CODE> or
<CODE>MySQL 5</CODE>.</P>
<P>Example on a <B>PostgreSQL 8.2.7</B> target:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&amp;cat=2" -v 2 \
--dbms "PostgreSQL"
[...]
[hh:mm:31] [DEBUG] skipping to test for MySQL
[hh:mm:31] [DEBUG] skipping to test for Oracle
back-end DBMS: PostgreSQL
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>In case you provide <CODE>--fingerprint</CODE> together with <CODE>--dbms</CODE>,
sqlmap will only perform the extensive fingerprint for the specified
database management system, read the following section for further
details.</P>
<P>Note that this option is <B>not</B> mandatory and it is strongly
recommended to use it <B>only if you are absolutely sure</B> about the
back-end database management system. If you do not know it, let sqlmap
automatically identify it for you.</P>
<H3>Custom injection payload</H3>
<P>Options: <CODE>--prefix</CODE> and <CODE>--postfix</CODE></P>
<P>TODO</P>
<H3>Page comparison</H3>
<P>Options: <CODE>--string</CODE> and <CODE>--regexp</CODE></P>
<P>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 for standard blind SQL injection attacks) is done comparing injected pages
content MD5 hash with the original not-injected page content MD5. Not content MD5 hash with the original not-injected page content MD5. Not
always this concept works because sometimes the page content changes at always this concept works because sometimes the page content changes at
@ -1410,53 +1472,6 @@ content that changes itself at each refresh without modifying the user's
input</EM>.</P> input</EM>.</P>
<H3>Force the database management system name</H3>
<P>Option: <CODE>--dbms</CODE></P>
<P>By default sqlmap automatically detects the web application's back-end
database manangement system.
At the moment the fully supported database management system are four:</P>
<P>
<UL>
<LI>MySQL</LI>
<LI>Oracle</LI>
<LI>PostgreSQL</LI>
<LI>Microsoft SQL Server</LI>
</UL>
</P>
<P>It is possible to force the name if you already know it so that sqlmap
will skip the fingerprint with an exception for MySQL to only identify if
it is MySQL &lt; 5.0 or MySQL &gt;= 5.0.
To avoid also this check you can provide instead <CODE>MySQL 4</CODE> or
<CODE>MySQL 5</CODE>.</P>
<P>Example on a <B>PostgreSQL 8.2.7</B> target:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&amp;cat=2" -v 2 \
--dbms "PostgreSQL"
[...]
[hh:mm:31] [DEBUG] skipping to test for MySQL
[hh:mm:31] [DEBUG] skipping to test for Oracle
back-end DBMS: PostgreSQL
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>In case you provide <CODE>--fingerprint</CODE> together with <CODE>--dbms</CODE>,
sqlmap will only perform the extensive fingerprint for the specified
database management system, read the following section for further
details.</P>
<P>Note that this option is <B>not</B> mandatory and it is strongly
recommended to use it <B>only if you are absolutely sure</B> about the
back-end database management system. If you do not know it, let sqlmap
automatically identify it for you.</P>
<H2><A NAME="ss5.4">5.4</A> <A HREF="#toc5.4">Techniques</A> <H2><A NAME="ss5.4">5.4</A> <A HREF="#toc5.4">Techniques</A>
</H2> </H2>

Binary file not shown.

View File

@ -335,6 +335,7 @@ Options:
--referer=REFERER HTTP Referer header --referer=REFERER HTTP Referer header
--user-agent=AGENT HTTP User-Agent header --user-agent=AGENT HTTP User-Agent header
-a USERAGENTSFILE Load a random HTTP User-Agent header from file -a USERAGENTSFILE Load a random HTTP User-Agent header from file
--headers=HEADERS Extra HTTP headers '\n' separated
--auth-type=ATYPE HTTP Authentication type, value: Basic or Digest --auth-type=ATYPE HTTP Authentication type, value: Basic or Digest
--auth-cred=ACRED HTTP Authentication credentials, value: name:password --auth-cred=ACRED HTTP Authentication credentials, value: name:password
--proxy=PROXY Use a HTTP proxy to connect to the target url --proxy=PROXY Use a HTTP proxy to connect to the target url
@ -344,8 +345,14 @@ Options:
Injection: Injection:
-p TESTPARAMETER Testable parameter(s) -p TESTPARAMETER Testable parameter(s)
--string=STRING String to match in page when the query is valid
--dbms=DBMS Force back-end DBMS to this value --dbms=DBMS Force back-end DBMS to this value
--prefix=PREFIX Injection payload prefix string
--postfix=POSTFIX Injection payload postfix string
--string=STRING String to match in page when the query is valid
--regexp=REGEXP Regexp to match in page when the query is valid
--excl-str=ESTRING String to be excluded before calculating page hash
--excl-reg=EREGEXP Regexp matches to be excluded before calculating page
hash
Techniques: Techniques:
These options can be used to test for specific SQL injection technique These options can be used to test for specific SQL injection technique
@ -1205,12 +1212,71 @@ back-end DBMS: MySQL >= 5.0.0
</verb></tscreen> </verb></tscreen>
<sect2>String match <sect2>Force the database management system name
<p> <p>
Option: <tt>--string</tt> Option: <tt>--dbms</tt>
<p> <p>
By default sqlmap automatically detects the web application's back-end
database manangement system.
At the moment the fully supported database management system are four:
<itemize>
<item>MySQL
<item>Oracle
<item>PostgreSQL
<item>Microsoft SQL Server
</itemize>
<p>
It is possible to force the name if you already know it so that sqlmap
will skip the fingerprint with an exception for MySQL to only identify if
it is MySQL &lt; 5.0 or MySQL &gt;= 5.0.
To avoid also this check you can provide instead <tt>MySQL 4</tt> or
<tt>MySQL 5</tt>.
Example on a <bf>PostgreSQL 8.2.7</bf> target:
<tscreen><verb>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&amp;cat=2" -v 2 \
--dbms "PostgreSQL"
[...]
[hh:mm:31] [DEBUG] skipping to test for MySQL
[hh:mm:31] [DEBUG] skipping to test for Oracle
back-end DBMS: PostgreSQL
</verb></tscreen>
<p>
In case you provide <tt>--fingerprint</tt> together with <tt>--dbms</tt>,
sqlmap will only perform the extensive fingerprint for the specified
database management system, read the following section for further
details.
<p>
Note that this option is <bf>not</bf> mandatory and it is strongly
recommended to use it <bf>only if you are absolutely sure</bf> about the
back-end database management system. If you do not know it, let sqlmap
automatically identify it for you.
<sect2>Custom injection payload
<p>
Options: <tt>--prefix</tt> and <tt>--postfix</tt>
<p>
TODO
<sect2>Page comparison
<p>
Options: <tt>--string</tt> and <tt>--regexp</tt>
<p>
TODO
By default the distinction of a True query by a False one (basic concept 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 for standard blind SQL injection attacks) is done comparing injected pages
content MD5 hash with the original not-injected page content MD5. Not content MD5 hash with the original not-injected page content MD5. Not
@ -1354,55 +1420,6 @@ content that changes itself at each refresh without modifying the user's
input</em>. input</em>.
<sect2>Force the database management system name
<p>
Option: <tt>--dbms</tt>
<p>
By default sqlmap automatically detects the web application's back-end
database manangement system.
At the moment the fully supported database management system are four:
<itemize>
<item>MySQL
<item>Oracle
<item>PostgreSQL
<item>Microsoft SQL Server
</itemize>
<p>
It is possible to force the name if you already know it so that sqlmap
will skip the fingerprint with an exception for MySQL to only identify if
it is MySQL &lt; 5.0 or MySQL &gt;= 5.0.
To avoid also this check you can provide instead <tt>MySQL 4</tt> or
<tt>MySQL 5</tt>.
Example on a <bf>PostgreSQL 8.2.7</bf> target:
<tscreen><verb>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&amp;cat=2" -v 2 \
--dbms "PostgreSQL"
[...]
[hh:mm:31] [DEBUG] skipping to test for MySQL
[hh:mm:31] [DEBUG] skipping to test for Oracle
back-end DBMS: PostgreSQL
</verb></tscreen>
<p>
In case you provide <tt>--fingerprint</tt> together with <tt>--dbms</tt>,
sqlmap will only perform the extensive fingerprint for the specified
database management system, read the following section for further
details.
<p>
Note that this option is <bf>not</bf> mandatory and it is strongly
recommended to use it <bf>only if you are absolutely sure</bf> about the
back-end database management system. If you do not know it, let sqlmap
automatically identify it for you.
<sect1>Techniques <sect1>Techniques
<sect2>Test for Time Based blind SQL injection <sect2>Test for Time Based blind SQL injection

View File

@ -108,6 +108,9 @@ Richard Safran <allapplyhere@yahoo.com>
Tomoyuki Sakurai <cherry@trombik.org> Tomoyuki Sakurai <cherry@trombik.org>
for submitting to the FreeBSD project the sqlmap 0.5 port for submitting to the FreeBSD project the sqlmap 0.5 port
Philippe A. R. Schaeffer <schaeff@compuphil.de>
for reporting a minor bug
Sven Schluter <sschlueter@netzwerk.cc> Sven Schluter <sschlueter@netzwerk.cc>
for providing with a patch for waiting a number of seconds between for providing with a patch for waiting a number of seconds between
each HTTP request each HTTP request

View File

@ -49,13 +49,49 @@ def checkSqlInjection(place, parameter, value, parenthesis):
* Double quoted string injection * Double quoted string injection
""" """
logMsg = "testing unescaped numeric injection "
logMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg)
randInt = randomInt() randInt = randomInt()
randStr = randomStr() randStr = randomStr()
if conf.prefix or conf.postfix:
prefix = ""
postfix = ""
if conf.prefix:
prefix = conf.prefix
if conf.postfix:
postfix = conf.postfix
infoMsg = "testing custom injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%d=%d %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randInt, randInt, postfix))
trueResult = Request.queryPage(payload, place)
if trueResult == kb.defaultResult:
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%d=%d %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randInt, randInt + 1, postfix))
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
infoMsg = "confirming custom injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%s %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randStr, postfix))
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "custom injectable "
logger.info(infoMsg)
return "custom"
infoMsg = "testing unescaped numeric injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt)) payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
@ -64,28 +100,28 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "confirming unescaped numeric injection " infoMsg = "confirming unescaped numeric injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
logMsg += "unescaped numeric injectable " infoMsg += "unescaped numeric injectable "
logMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
logger.info(logMsg) logger.info(infoMsg)
return "numeric" return "numeric"
logMsg = "%s parameter '%s' is not " % (place, parameter) infoMsg = "%s parameter '%s' is not " % (place, parameter)
logMsg += "unescaped numeric injectable" infoMsg += "unescaped numeric injectable"
logger.info(logMsg) logger.info(infoMsg)
logMsg = "testing single quoted string injection " infoMsg = "testing single quoted string injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr)) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
@ -95,28 +131,28 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "confirming single quoted string injection " infoMsg = "confirming single quoted string injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
logMsg += "single quoted string injectable " infoMsg += "single quoted string injectable "
logMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
logger.info(logMsg) logger.info(infoMsg)
return "stringsingle" return "stringsingle"
logMsg = "%s parameter '%s' is not " % (place, parameter) infoMsg = "%s parameter '%s' is not " % (place, parameter)
logMsg += "single quoted string injectable" infoMsg += "single quoted string injectable"
logger.info(logMsg) logger.info(infoMsg)
logMsg = "testing LIKE single quoted string injection " infoMsg = "testing LIKE single quoted string injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr)) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
@ -126,28 +162,28 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "confirming LIKE single quoted string injection " infoMsg = "confirming LIKE single quoted string injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
logMsg += "LIKE single quoted string injectable " infoMsg += "LIKE single quoted string injectable "
logMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
logger.info(logMsg) logger.info(infoMsg)
return "likesingle" return "likesingle"
logMsg = "%s parameter '%s' is not " % (place, parameter) infoMsg = "%s parameter '%s' is not " % (place, parameter)
logMsg += "LIKE single quoted string injectable" infoMsg += "LIKE single quoted string injectable"
logger.info(logMsg) logger.info(infoMsg)
logMsg = "testing double quoted string injection " infoMsg = "testing double quoted string injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
@ -157,28 +193,28 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "confirming double quoted string injection " infoMsg = "confirming double quoted string injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s\"%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
logMsg += "double quoted string injectable " infoMsg += "double quoted string injectable "
logMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
logger.info(logMsg) logger.info(infoMsg)
return "stringdouble" return "stringdouble"
logMsg = "%s parameter '%s' is not " % (place, parameter) infoMsg = "%s parameter '%s' is not " % (place, parameter)
logMsg += "double quoted string injectable" infoMsg += "double quoted string injectable"
logger.info(logMsg) logger.info(infoMsg)
logMsg = "testing LIKE double quoted string injection " infoMsg = "testing LIKE double quoted string injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
@ -188,24 +224,24 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "confirming LIKE double quoted string injection " infoMsg = "confirming LIKE double quoted string injection "
logMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s\"%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s\"%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != kb.defaultResult:
logMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
logMsg += "LIKE double quoted string injectable " infoMsg += "LIKE double quoted string injectable "
logMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
logger.info(logMsg) logger.info(infoMsg)
return "likedouble" return "likedouble"
logMsg = "%s parameter '%s' is not " % (place, parameter) infoMsg = "%s parameter '%s' is not " % (place, parameter)
logMsg += "LIKE double quoted string injectable" infoMsg += "LIKE double quoted string injectable"
logger.info(logMsg) logger.info(infoMsg)
return None return None
@ -217,8 +253,8 @@ def checkDynParam(place, parameter, value):
dynamicity might depend on another parameter. dynamicity might depend on another parameter.
""" """
logMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter) infoMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
randInt = randomInt() randInt = randomInt()
payload = agent.payload(place, parameter, value, str(randInt)) payload = agent.payload(place, parameter, value, str(randInt))
@ -227,8 +263,8 @@ def checkDynParam(place, parameter, value):
if kb.defaultResult == dynResult1: if kb.defaultResult == dynResult1:
return False return False
logMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter) infoMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter)
logger.info(logMsg) logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "'%s" % randomStr()) payload = agent.payload(place, parameter, value, "'%s" % randomStr())
dynResult2 = Request.queryPage(payload, place) dynResult2 = Request.queryPage(payload, place)
@ -253,8 +289,8 @@ def checkStability():
like for instance string matching (--string). like for instance string matching (--string).
""" """
logMsg = "testing if the url is stable, wait a few seconds" infoMsg = "testing if the url is stable, wait a few seconds"
logger.info(logMsg) logger.info(infoMsg)
firstResult = Request.queryPage() firstResult = Request.queryPage()
time.sleep(0.5) time.sleep(0.5)
@ -283,9 +319,9 @@ def checkString():
if condition: if condition:
return True return True
logMsg = "testing if the provided string is within the " infoMsg = "testing if the provided string is within the "
logMsg += "target URL page content" infoMsg += "target URL page content"
logger.info(logMsg) logger.info(infoMsg)
page = Request.queryPage(content=True) page = Request.queryPage(content=True)
@ -302,8 +338,8 @@ def checkString():
def checkConnection(): def checkConnection():
logMsg = "testing connection to the target url" infoMsg = "testing connection to the target url"
logger.info(logMsg) logger.info(infoMsg)
try: try:
kb.defaultResult = Request.queryPage() kb.defaultResult = Request.queryPage()

View File

@ -214,6 +214,7 @@ def start():
if injType: if injType:
injData.append((place, parameter, injType)) injData.append((place, parameter, injType))
kb.parenthesis = parenthesis
break break
else: else:

View File

@ -91,6 +91,9 @@ class Agent:
query = "" query = ""
if conf.prefix:
query = conf.prefix
else:
if kb.injType == "numeric": if kb.injType == "numeric":
pass pass
elif kb.injType in ( "stringsingle", "likesingle" ): elif kb.injType in ( "stringsingle", "likesingle" ):
@ -118,8 +121,11 @@ class Agent:
randStr = randomStr() randStr = randomStr()
if comment: if comment:
string += "%s" % comment string += comment
if conf.postfix:
string += " %s" % conf.postfix
else:
if kb.parenthesis != None: if kb.parenthesis != None:
string += " AND %s" % ("(" * kb.parenthesis) string += " AND %s" % ("(" * kb.parenthesis)
else: else:

View File

@ -94,6 +94,9 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
if not re.search ("^[\n]*(GET|POST).*?\sHTTP\/", request, re.I): if not re.search ("^[\n]*(GET|POST).*?\sHTTP\/", request, re.I):
continue continue
if re.search("^[\n]*(GET|POST).*?\.(gif|jpg|png)\sHTTP\/", request, re.I):
continue
getPostReq = False getPostReq = False
url = None url = None
host = None host = None
@ -235,9 +238,9 @@ def __setGoogleDorking():
raise sqlmapGenericException, errMsg raise sqlmapGenericException, errMsg
def __setRemoteDBMS(): def __setDBMS():
""" """
Checks and set the back-end DBMS option. Force the back-end DBMS option.
""" """
if not conf.dbms: if not conf.dbms:
@ -384,10 +387,22 @@ def __setHTTPMethod():
logger.debug(debugMsg) logger.debug(debugMsg)
def __setHTTPStandardHeaders(): def __setHTTPExtraHeaders():
conf.httpHeaders.append(("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")) if conf.headers:
debugMsg = "setting extra HTTP headers"
logger.debug(debugMsg)
conf.headers = conf.headers.split("\n")
for headerValue in conf.headers:
header, value = headerValue.split(": ")
if header and value:
conf.httpHeaders.append((header, value))
else:
conf.httpHeaders.append(("Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"))
conf.httpHeaders.append(("Accept-Language", "en-us,en;q=0.5")) conf.httpHeaders.append(("Accept-Language", "en-us,en;q=0.5"))
conf.httpHeaders.append(("Accept-Encoding", "gzip,deflate"))
conf.httpHeaders.append(("Accept-Charset", "ISO-8859-15,utf-8;q=0.7,*;q=0.7")) conf.httpHeaders.append(("Accept-Charset", "ISO-8859-15,utf-8;q=0.7,*;q=0.7"))
@ -646,6 +661,9 @@ def __saveCmdline():
elif datatype == "string": elif datatype == "string":
value = "" value = ""
if isinstance(value, str):
value = value.replace("\n", "\n ")
confFP.write("%s = %s\n" % (option, value)) confFP.write("%s = %s\n" % (option, value))
confFP.write("\n") confFP.write("\n")
@ -712,12 +730,12 @@ def init(inputOptions=advancedDict()):
__setHTTPCookies() __setHTTPCookies()
__setHTTPReferer() __setHTTPReferer()
__setHTTPUserAgent() __setHTTPUserAgent()
__setHTTPStandardHeaders() __setHTTPExtraHeaders()
__setHTTPMethod() __setHTTPMethod()
__setHTTPAuthentication() __setHTTPAuthentication()
__setHTTPProxy() __setHTTPProxy()
__setThreads() __setThreads()
__setRemoteDBMS() __setDBMS()
__setGoogleDorking() __setGoogleDorking()
__setMultipleTargets() __setMultipleTargets()
__urllib2Opener() __urllib2Opener()

View File

@ -39,6 +39,7 @@ optDict = {
"referer": "string", "referer": "string",
"agent": "string", "agent": "string",
"userAgentsFile": "string", "userAgentsFile": "string",
"headers": "string",
"aType": "string", "aType": "string",
"aCred": "string", "aCred": "string",
"proxy": "string", "proxy": "string",
@ -50,6 +51,8 @@ optDict = {
"Injection": { "Injection": {
"testParameter": "string", "testParameter": "string",
"dbms": "string", "dbms": "string",
"prefix": "string",
"postfix": "string",
"string": "string", "string": "string",
"regexp": "string", "regexp": "string",
"eString": "string", "eString": "string",

View File

@ -30,7 +30,7 @@ import sys
# sqlmap version and site # sqlmap version and site
VERSION = "0.6.3-rc4" VERSION = "0.6.3-rc5"
VERSION_STRING = "sqlmap/%s" % VERSION VERSION_STRING = "sqlmap/%s" % VERSION
SITE = "http://sqlmap.sourceforge.net" SITE = "http://sqlmap.sourceforge.net"

View File

@ -57,6 +57,7 @@ def cmdLineParser():
target.add_option("-c", dest="configFile", target.add_option("-c", dest="configFile",
help="Load options from a configuration INI file") help="Load options from a configuration INI file")
# Request options # Request options
request = OptionGroup(parser, "Request", "These options can be used " request = OptionGroup(parser, "Request", "These options can be used "
"to specify how to connect to the target url.") "to specify how to connect to the target url.")
@ -80,6 +81,9 @@ def cmdLineParser():
help="Load a random HTTP User-Agent " help="Load a random HTTP User-Agent "
"header from file") "header from file")
request.add_option("--headers", dest="headers",
help="Extra HTTP headers '\\n' separated")
request.add_option("--auth-type", dest="aType", request.add_option("--auth-type", dest="aType",
help="HTTP Authentication type, value: " help="HTTP Authentication type, value: "
"Basic or Digest") "Basic or Digest")
@ -112,6 +116,12 @@ def cmdLineParser():
injection.add_option("--dbms", dest="dbms", injection.add_option("--dbms", dest="dbms",
help="Force back-end DBMS to this value") help="Force back-end DBMS to this value")
injection.add_option("--prefix", dest="prefix",
help="Injection payload prefix string")
injection.add_option("--postfix", dest="postfix",
help="Injection payload postfix string")
injection.add_option("--string", dest="string", injection.add_option("--string", dest="string",
help="String to match in page when the " help="String to match in page when the "
"query is valid") "query is valid")
@ -128,6 +138,7 @@ def cmdLineParser():
help="Regexp matches to be excluded before " help="Regexp matches to be excluded before "
"calculating page hash") "calculating page hash")
# Techniques options # Techniques options
techniques = OptionGroup(parser, "Techniques", "These options can " techniques = OptionGroup(parser, "Techniques", "These options can "
"be used to test for specific SQL injection " "be used to test for specific SQL injection "
@ -149,6 +160,7 @@ def cmdLineParser():
"to retrieve the queries output. No " "to retrieve the queries output. No "
"need to go blind") "need to go blind")
# Fingerprint options # Fingerprint options
fingerprint = OptionGroup(parser, "Fingerprint") fingerprint = OptionGroup(parser, "Fingerprint")
@ -156,6 +168,7 @@ def cmdLineParser():
action="store_true", action="store_true",
help="Perform an extensive DBMS version fingerprint") help="Perform an extensive DBMS version fingerprint")
# Enumeration options # Enumeration options
enumeration = OptionGroup(parser, "Enumeration", "These options can " enumeration = OptionGroup(parser, "Enumeration", "These options can "
"be used to enumerate the back-end database " "be used to enumerate the back-end database "
@ -232,6 +245,7 @@ def cmdLineParser():
action="store_true", action="store_true",
help="Prompt for an interactive SQL shell") help="Prompt for an interactive SQL shell")
# File system options # File system options
filesystem = OptionGroup(parser, "File system access", "These options " filesystem = OptionGroup(parser, "File system access", "These options "
"can be used to access the back-end database " "can be used to access the back-end database "
@ -245,6 +259,7 @@ def cmdLineParser():
filesystem.add_option("--write-file", dest="wFile", filesystem.add_option("--write-file", dest="wFile",
help="Write to a specific OS file (not yet available)") help="Write to a specific OS file (not yet available)")
# Takeover options # Takeover options
takeover = OptionGroup(parser, "Operating system access", "This " takeover = OptionGroup(parser, "Operating system access", "This "
"option can be used to access the back-end " "option can be used to access the back-end "
@ -258,6 +273,7 @@ def cmdLineParser():
"writable directory within the web " "writable directory within the web "
"server document root for the moment)") "server document root for the moment)")
# Miscellaneous options # Miscellaneous options
miscellaneous = OptionGroup(parser, "Miscellaneous") miscellaneous = OptionGroup(parser, "Miscellaneous")
@ -282,6 +298,7 @@ def cmdLineParser():
miscellaneous.add_option("--batch", dest="batch", action="store_true", miscellaneous.add_option("--batch", dest="batch", action="store_true",
help="Never ask for user input, use the default behaviour") help="Never ask for user input, use the default behaviour")
parser.add_option_group(target) parser.add_option_group(target)
parser.add_option_group(request) parser.add_option_group(request)
parser.add_option_group(injection) parser.add_option_group(injection)

View File

@ -28,13 +28,12 @@ import md5
import re import re
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
def comparison(page, headers=None, content=False): def comparison(page, headers=None, content=False):
regExpResults = None regExpResults = None
# String to be excluded before calculating page hash
if conf.eString and conf.eString in page: if conf.eString and conf.eString in page:
index = page.index(conf.eString) index = page.index(conf.eString)
length = len(conf.eString) length = len(conf.eString)
@ -42,10 +41,11 @@ def comparison(page, headers=None, content=False):
pageWithoutString += page[index+length:] pageWithoutString += page[index+length:]
page = pageWithoutString page = pageWithoutString
# Regular expression matches to be excluded before calculating page hash
if conf.eRegexp: if conf.eRegexp:
regExpResults = re.findall(conf.eRegexp, page, re.I | re.M) regExpResults = re.findall(conf.eRegexp, page, re.I | re.M)
if conf.eRegexp and regExpResults: if regExpResults:
for regExpResult in regExpResults: for regExpResult in regExpResults:
index = page.index(regExpResult) index = page.index(regExpResult)
length = len(regExpResult) length = len(regExpResult)
@ -53,17 +53,20 @@ def comparison(page, headers=None, content=False):
pageWithoutRegExp += page[index+length:] pageWithoutRegExp += page[index+length:]
page = pageWithoutRegExp page = pageWithoutRegExp
# String to match in page when the query is valid
if conf.string: if conf.string:
if conf.string in page: if conf.string in page:
return True return True
else: else:
return False return False
elif conf.regexp: # Regular expression to match in page when the query is valid
if conf.regexp:
if re.search(conf.regexp, page, re.I | re.M): if re.search(conf.regexp, page, re.I | re.M):
return True return True
else: else:
return False return False
# By default it returns the page content MD5 hash
else: else:
return md5.new(page).hexdigest() return md5.new(page).hexdigest()

View File

@ -27,6 +27,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
@ -40,14 +41,14 @@ def checkForParenthesis():
is within the parenthesis. is within the parenthesis.
""" """
if kb.parenthesis != None:
return kb.parenthesis
logMsg = "testing for parenthesis on injectable parameter" logMsg = "testing for parenthesis on injectable parameter"
logger.info(logMsg) logger.info(logMsg)
count = 0 count = 0
if conf.prefix or conf.postfix:
return
for parenthesis in range(1, 4): for parenthesis in range(1, 4):
query = agent.prefixQuery("%s " % (")" * parenthesis)) query = agent.prefixQuery("%s " % (")" * parenthesis))
query += "AND %s" % ("(" * parenthesis) query += "AND %s" % ("(" * parenthesis)

View File

@ -3,8 +3,8 @@
# Target URL. # Target URL.
# Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 # Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2
# PHP and MySQL (local) # PHP and MySQL (local)
#url = http://127.0.0.1/sqlmap/mysql/get_int.php?id=1 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_partialunion.php?id=1
# PHP and Oracle (local) # PHP and Oracle (local)
#url = http://127.0.0.1/sqlmap/oracle/get_int.php?id=1 #url = http://127.0.0.1/sqlmap/oracle/get_int.php?id=1
# PHP and PostgreSQL (local) # PHP and PostgreSQL (local)
@ -62,6 +62,12 @@ agent =
# Example: ./txt/user-agents.txt # Example: ./txt/user-agents.txt
userAgentsFile = userAgentsFile =
# Extra HTTP headers
# Note: there must be a space at the beginning of each header line
headers = Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
# HTTP Authentication type. Useful only if the target url requires # HTTP Authentication type. Useful only if the target url requires
# HTTP Basic or Digest authentication and you have such data. # HTTP Basic or Digest authentication and you have such data.
# Valid: Basic or Digest # Valid: Basic or Digest
@ -105,6 +111,12 @@ testParameter =
# Valid: mssql, mysql, mysql 4, mysql 5, oracle, pgsql # Valid: mssql, mysql, mysql 4, mysql 5, oracle, pgsql
dbms = dbms =
# Injection payload prefix string
prefix =
# Injection payload postfix string
postfix =
# String to match within the page content when the query is valid, only # String to match within the page content when the query is valid, only
# needed if the page content dynamically changes at each refresh, # needed if the page content dynamically changes at each refresh,
# consequently changing the MD5 hash of the page which is the method used # consequently changing the MD5 hash of the page which is the method used