From f8c9868cb688865375553fe3826b55d425f1fcc2 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Tue, 24 Jul 2012 15:34:50 +0200 Subject: [PATCH] Implementation for an Issue #118 --- lib/core/agent.py | 2 +- lib/core/common.py | 4 ++-- lib/core/option.py | 14 +++++++------- lib/core/optiondict.py | 6 +++--- lib/parse/cmdline.py | 16 +++++++++++++--- lib/request/inject.py | 2 +- lib/takeover/abstraction.py | 4 ++-- lib/takeover/xp_cmdshell.py | 6 +++--- lib/techniques/dns/test.py | 2 +- lib/techniques/dns/use.py | 6 +++--- sqlmap.conf | 6 +++--- 11 files changed, 39 insertions(+), 29 deletions(-) diff --git a/lib/core/agent.py b/lib/core/agent.py index bd6404456..26c4781f7 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -855,7 +855,7 @@ class Agent: return re.sub("(%s.*?%s)" % (PAYLOAD_DELIMITER, PAYLOAD_DELIMITER), ("%s%s%s" % (PAYLOAD_DELIMITER, payload, PAYLOAD_DELIMITER)).replace("\\", r"\\"), inpStr) if inpStr else inpStr def runAsDBMSUser(self, query): - if conf.dCred and "Ad Hoc Distributed Queries" not in query: + if conf.dbmsCred and "Ad Hoc Distributed Queries" not in query: query = getSQLSnippet(DBMS.MSSQL, "run_statement_as_user", USER=conf.dbmsUsername, PASSWORD=conf.dbmsPassword, STATEMENT=query.replace("'", "''")) return query diff --git a/lib/core/common.py b/lib/core/common.py index 3afc0b9bc..00404f6b2 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -3211,11 +3211,11 @@ def resetCookieJar(cookieJar): Cleans cookies from a given cookie jar """ - if not conf.loC: + if not conf.loadCookies: cookieJar.clear() else: try: - cookieJar.load(conf.loC) + cookieJar.load(conf.loadCookies) cookieJar.clear_expired_cookies() except cookielib.LoadError, msg: errMsg = "there was a problem loading " diff --git a/lib/core/option.py b/lib/core/option.py index 5c1b6e353..73104b715 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -150,7 +150,7 @@ def __urllib2Opener(): handlers = [proxyHandler, authHandler, redirectHandler, rangeHandler, httpsHandler] if not conf.dropSetCookie: - if not conf.loC: + if not conf.loadCookies: conf.cj = cookielib.CookieJar() else: conf.cj = cookielib.MozillaCookieJar() @@ -562,13 +562,13 @@ def __setDBMSAuthentication(): another user, not the session user """ - if not conf.dCred: + if not conf.dbmsCred: return debugMsg = "setting the DBMS authentication credentials" logger.debug(debugMsg) - match = re.search("^(.+?):(.*?)$", conf.dCred) + match = re.search("^(.+?):(.*?)$", conf.dbmsCred) if not match: errMsg = "DBMS authentication credentials value must be in format " @@ -1730,7 +1730,7 @@ def __setTrafficOutputFP(): conf.trafficFP = openFile(conf.trafficFile, "w+") def __setDNSServer(): - if not conf.dName: + if not conf.dnsName: return infoMsg = "setting up DNS server instance" @@ -1944,9 +1944,9 @@ def __basicOptionValidation(): errMsg += "supported charsets" raise sqlmapSyntaxException, errMsg - if conf.loC: - if not os.path.exists(conf.loC): - errMsg = "cookies file '%s' does not exist" % conf.loC + if conf.loadCookies: + if not os.path.exists(conf.loadCookies): + errMsg = "cookies file '%s' does not exist" % conf.loadCookies raise sqlmapFilePathException, errMsg def __resolveCrossReferences(): diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 6c30d46a6..aa258275b 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -24,7 +24,7 @@ optDict = { "data": "string", "pDel": "string", "cookie": "string", - "loC": "string", + "loadCookies": "string", "cookieUrlencode": "boolean", "dropSetCookie": "boolean", "agent": "string", @@ -87,7 +87,7 @@ optDict = { "timeSec": "integer", "uCols": "string", "uChar": "string", - "dName": "string" + "dnsName": "string" }, "Fingerprint": { @@ -171,7 +171,7 @@ optDict = { "checkTor": "boolean", "crawlDepth": "integer", "csvDel": "string", - "dCred": "string", + "dbmsCred": "string", "eta": "boolean", "flushSession": "boolean", "forms": "boolean", diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 9ff2f4bb4..353fee133 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -76,7 +76,7 @@ def cmdLineParser(): request.add_option("--cookie", dest="cookie", help="HTTP Cookie header") - request.add_option("--load-cookies", dest="loC", + request.add_option("--load-cookies", dest="loadCookies", help="File containing cookies in Netscape/wget format") request.add_option("--cookie-urlencode", dest="cookieUrlencode", @@ -280,7 +280,7 @@ def cmdLineParser(): techniques.add_option("--union-char", dest="uChar", help="Character to use for bruteforcing number of columns") - techniques.add_option("--dns-domain", dest="dName", + techniques.add_option("--dns-domain", dest="dnsName", help="Domain name used for DNS exfiltration attack") # Fingerprint options @@ -533,7 +533,7 @@ def cmdLineParser(): help="Delimiting character used in CSV output " "(default \"%s\")" % defaults.csvDel) - general.add_option("--dbms-cred", dest="dCred", + general.add_option("--dbms-cred", dest="dbmsCred", help="DBMS authentication credentials (user:password)") general.add_option("--eta", dest="eta", @@ -674,6 +674,16 @@ def cmdLineParser(): parser.add_option_group(general) parser.add_option_group(miscellaneous) + # Dirty hack to display longer options without breaking into two lines + def _(self, *args): + _ = parser.formatter._format_option_strings(*args) + if len(_) > 18: + _ = "%.16s.." % _ + return _ + + parser.formatter._format_option_strings = parser.formatter.format_option_strings + parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser, type(parser)) + # Dirty hack for making a short option -hh option = parser.get_option("--hh") option._short_opts = ["-hh"] diff --git a/lib/request/inject.py b/lib/request/inject.py index 418adaed6..a8fa34861 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -57,7 +57,7 @@ from lib.techniques.union.use import unionUse def __goDns(payload, expression): value = None - if conf.dName and kb.dnsTest is not False: + if conf.dnsName and kb.dnsTest is not False: if kb.dnsTest is None: dnsTest(payload) diff --git a/lib/takeover/abstraction.py b/lib/takeover/abstraction.py index 28478c24b..f29a93e3a 100644 --- a/lib/takeover/abstraction.py +++ b/lib/takeover/abstraction.py @@ -142,7 +142,7 @@ class Abstraction(Web, UDF, xp_cmdshell): self.runCmd(command) def __initRunAs(self): - if not conf.dCred: + if not conf.dbmsCred: return if not conf.direct and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED): @@ -186,7 +186,7 @@ class Abstraction(Web, UDF, xp_cmdshell): warnMsg = "functionality requested probably does not work because " warnMsg += "the curent session user is not a database administrator" - if not conf.dCred and Backend.getIdentifiedDbms() in ( DBMS.MSSQL, DBMS.PGSQL ): + if not conf.dbmsCred and Backend.getIdentifiedDbms() in ( DBMS.MSSQL, DBMS.PGSQL ): warnMsg += ". You can try to use option '--dbms-cred' " warnMsg += "to execute statements as a DBA user if you " warnMsg += "were able to extract and crack a DBA " diff --git a/lib/takeover/xp_cmdshell.py b/lib/takeover/xp_cmdshell.py index 8c1f28e9b..28c02a126 100644 --- a/lib/takeover/xp_cmdshell.py +++ b/lib/takeover/xp_cmdshell.py @@ -155,7 +155,7 @@ class xp_cmdshell: # to retrieve it afterwards # NOTE: this does not need to be done when the command is 'del' to # delete the temporary file - if conf.dCred and insertIntoTable: + if conf.dbmsCred and insertIntoTable: self.tmpFile = "%s/tmpc%s.txt" % (conf.tmpPath, randomStr(lowercase=True)) cmd = "%s > \"%s\"" % (cmd, self.tmpFile) @@ -171,7 +171,7 @@ class xp_cmdshell: # it does not work unfortunately, BULK INSERT needs to be used to # retrieve the output when OPENROWSET is used hence the redirection # to a temporary file from above - if insertIntoTable and not conf.dCred: + if insertIntoTable and not conf.dbmsCred: self.__forgedCmd += "INSERT INTO %s " % insertIntoTable self.__forgedCmd += "EXEC %s @%s" % (self.xpCmdshellStr, self.__randStr) @@ -203,7 +203,7 @@ class xp_cmdshell: # command standard output is redirected to a temporary file # The file needs to be copied to the support table, # 'sqlmapoutput' - if conf.dCred: + if conf.dbmsCred: inject.goStacked("BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')" % (self.cmdTblName, self.tmpFile, randomStr(10), randomStr(10))) self.delRemoteFile(self.tmpFile) diff --git a/lib/techniques/dns/test.py b/lib/techniques/dns/test.py index 0efb01990..a91c2dfc6 100644 --- a/lib/techniques/dns/test.py +++ b/lib/techniques/dns/test.py @@ -24,7 +24,7 @@ def dnsTest(payload): errMsg = "data retrieval through DNS channel failed. Turning off DNS exfiltration support" logger.error(errMsg) - conf.dName = None + conf.dnsName = None else: infoMsg = "data retrieval through DNS channel was successful" logger.info(infoMsg) diff --git a/lib/techniques/dns/use.py b/lib/techniques/dns/use.py index 33de07049..544d07651 100644 --- a/lib/techniques/dns/use.py +++ b/lib/techniques/dns/use.py @@ -48,7 +48,7 @@ def dnsUse(payload, expression): count = 0 offset = 1 - if conf.dName and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.ORACLE, DBMS.MYSQL, DBMS.PGSQL): + if conf.dnsName and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.ORACLE, DBMS.MYSQL, DBMS.PGSQL): output = hashDBRetrieve(expression, checkConf=True) if output and PARTIAL_VALUE_MARKER in output or kb.dnsTest is None: @@ -67,7 +67,7 @@ def dnsUse(payload, expression): nulledCastedField = agent.hexConvertField(nulledCastedField) expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1) - expressionRequest = getSQLSnippet(Backend.getIdentifiedDbms(), "dns_request", PREFIX=prefix, QUERY=expressionReplaced, SUFFIX=suffix, DOMAIN=conf.dName) + expressionRequest = getSQLSnippet(Backend.getIdentifiedDbms(), "dns_request", PREFIX=prefix, QUERY=expressionReplaced, SUFFIX=suffix, DOMAIN=conf.dnsName) expressionUnescaped = unescaper.unescape(expressionRequest) if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.PGSQL): @@ -108,7 +108,7 @@ def dnsUse(payload, expression): debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start)) logger.debug(debugMsg) - elif conf.dName: + elif conf.dnsName: warnMsg = "DNS data exfiltration method through SQL injection " warnMsg += "is currently not available for DBMS %s" % Backend.getIdentifiedDbms() singleTimeWarnMessage(warnMsg) diff --git a/sqlmap.conf b/sqlmap.conf index ea5810933..b5774a6ec 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -43,7 +43,7 @@ pDel = cookie = # File containing cookies in Netscape/wget format -loC = +loadCookies = # URL-encode generated cookie injections. # Valid: True or False @@ -303,7 +303,7 @@ uChar = # Domain name used for DNS exfiltration attack # Valid: string -dName = +dnsName = [Fingerprint] @@ -584,7 +584,7 @@ csvDel = , # vulnerable by stacked queries SQL injection or you are connecting directly # to the DBMS (-d switch). # Syntax: username:password -dCred = +dbmsCred = # Retrieve each query output length and calculate the estimated time of # arrival in real time.