mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-30 03:19:04 +00:00
Major enhancement to directly connect to the dbms without passing via a sql injection: adapted code accordingly - see #158. This feature relies on python third-party libraries to be able to connect to the database. For the moment it has been implemented for MySQL (with python-mysqldb module) and PostgreSQL (with python-psycopg2 module).
Minor layout adjustments.
This commit is contained in:
@@ -44,12 +44,25 @@ class Agent:
|
||||
temp.start = randomStr(6)
|
||||
temp.stop = randomStr(6)
|
||||
|
||||
def payloadDirect(self, query):
|
||||
if query.startswith(" AND "):
|
||||
query = query.replace(" AND ", "SELECT ")
|
||||
elif query.startswith(" UNION ALL "):
|
||||
query = query.replace(" UNION ALL ", "")
|
||||
elif query.startswith("; "):
|
||||
query = query.replace("; ", "")
|
||||
|
||||
return query
|
||||
|
||||
def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False, falseCond=False):
|
||||
"""
|
||||
This method replaces the affected parameter with the SQL
|
||||
injection statement to request
|
||||
"""
|
||||
|
||||
if conf.direct:
|
||||
return self.payloadDirect(newValue)
|
||||
|
||||
falseValue = ""
|
||||
negValue = ""
|
||||
retValue = ""
|
||||
@@ -83,6 +96,9 @@ class Agent:
|
||||
return retValue
|
||||
|
||||
def fullPayload(self, query):
|
||||
if conf.direct:
|
||||
return self.payloadDirect(query)
|
||||
|
||||
query = self.prefixQuery(query)
|
||||
query = self.postfixQuery(query)
|
||||
payload = self.payload(newValue=query)
|
||||
@@ -96,6 +112,9 @@ class Agent:
|
||||
identified as valid
|
||||
"""
|
||||
|
||||
if conf.direct:
|
||||
return self.payloadDirect(string)
|
||||
|
||||
query = ""
|
||||
|
||||
if conf.prefix:
|
||||
@@ -123,6 +142,9 @@ class Agent:
|
||||
SQL injection request
|
||||
"""
|
||||
|
||||
if conf.direct:
|
||||
return self.payloadDirect(string)
|
||||
|
||||
randInt = randomInt()
|
||||
randStr = randomStr()
|
||||
|
||||
|
||||
@@ -47,12 +47,21 @@ from lib.core.data import temp
|
||||
from lib.core.convert import urlencode
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
from lib.core.exception import sqlmapNoneDataException
|
||||
from lib.core.exception import sqlmapMissingDependence
|
||||
from lib.core.exception import sqlmapSyntaxException
|
||||
from lib.core.settings import DESCRIPTION
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import SITE
|
||||
from lib.core.settings import SQL_STATEMENTS
|
||||
from lib.core.settings import SUPPORTED_DBMS
|
||||
from lib.core.settings import VERSION_STRING
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import PGSQL_ALIASES
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
from lib.core.settings import SQLITE_ALIASES
|
||||
from lib.core.settings import ACCESS_ALIASES
|
||||
from lib.core.settings import FIREBIRD_ALIASES
|
||||
|
||||
def paramToDict(place, parameters=None):
|
||||
"""
|
||||
@@ -319,7 +328,7 @@ def getDirs(webApi=None):
|
||||
[directories.add(directory) for directory in defaultDirs]
|
||||
|
||||
return directories
|
||||
|
||||
|
||||
def filePathToString(filePath):
|
||||
strRepl = filePath.replace("/", "_").replace("\\", "_")
|
||||
strRepl = strRepl.replace(" ", "_").replace(":", "_")
|
||||
@@ -329,18 +338,18 @@ def filePathToString(filePath):
|
||||
def dataToStdout(data):
|
||||
sys.stdout.write(data)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def dataToSessionFile(data):
|
||||
if not conf.sessionFile:
|
||||
return
|
||||
|
||||
conf.sessionFP.write(data)
|
||||
conf.sessionFP.flush()
|
||||
|
||||
|
||||
def dataToDumpFile(dumpFile, data):
|
||||
dumpFile.write(data)
|
||||
dumpFile.flush()
|
||||
|
||||
|
||||
def dataToOutFile(data):
|
||||
if not data:
|
||||
return "No data retrieved"
|
||||
@@ -586,10 +595,62 @@ def weAreFrozen():
|
||||
|
||||
return hasattr(sys, "frozen")
|
||||
|
||||
def parseTargetDirect():
|
||||
"""
|
||||
Parse target dbms and set some attributes into the configuration singleton.
|
||||
"""
|
||||
|
||||
if not conf.direct:
|
||||
return
|
||||
|
||||
details = None
|
||||
|
||||
for dbms in SUPPORTED_DBMS:
|
||||
details = re.search("^(%s)://(.+?)\:(.+?)\@(.+?)\:([\d]+)\/(.+?)$" % dbms, conf.direct, re.I)
|
||||
|
||||
if details:
|
||||
conf.dbms = details.group(1)
|
||||
conf.dbmsUser = details.group(2)
|
||||
conf.dbmsPass = details.group(3)
|
||||
conf.hostname = details.group(4)
|
||||
conf.port = int(details.group(5))
|
||||
conf.dbmsDb = details.group(6)
|
||||
|
||||
conf.parameters[None] = "direct connection"
|
||||
|
||||
break
|
||||
|
||||
if not details:
|
||||
errMsg = "invalid target details, valid syntax is for instance: mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
# TODO: add details for others python DBMS libraries
|
||||
dbmsDict = { "Microsoft SQL Server": [MSSQL_ALIASES, "python-pymssql", "http://pymssql.sourceforge.net/"],
|
||||
"MySQL": [MYSQL_ALIASES, "python-mysqldb", "http://mysql-python.sourceforge.net/"],
|
||||
"PostgreSQL": [PGSQL_ALIASES, "python-psycopg2", "http://initd.org/psycopg/"],
|
||||
"Oracle": [ORACLE_ALIASES, "", ""],
|
||||
"SQLite": [SQLITE_ALIASES, "", ""],
|
||||
"Access": [ACCESS_ALIASES, "", ""],
|
||||
"Firebird": [FIREBIRD_ALIASES, "", ""] }
|
||||
|
||||
for dbmsName, data in dbmsDict.items():
|
||||
if conf.dbms in data[0]:
|
||||
try:
|
||||
if dbmsName == "Microsoft SQL Server":
|
||||
import pymssql
|
||||
elif dbmsName == "MySQL":
|
||||
import MySQLdb
|
||||
elif dbmsName == "PostgreSQL":
|
||||
import psycopg2
|
||||
except ImportError, _:
|
||||
errMsg = "sqlmap requires %s third-party library " % data[1]
|
||||
errMsg += "in order to directly connect to the database "
|
||||
errMsg += "%s. Download from %s" % (dbmsName, data[2])
|
||||
raise sqlmapMissingDependence, errMsg
|
||||
|
||||
def parseTargetUrl():
|
||||
"""
|
||||
Parse target url and set some attributes into the configuration
|
||||
singleton.
|
||||
Parse target url and set some attributes into the configuration singleton.
|
||||
"""
|
||||
|
||||
if not conf.url:
|
||||
|
||||
@@ -32,6 +32,8 @@ import sys
|
||||
import struct
|
||||
import urllib
|
||||
|
||||
from lib.core.data import conf
|
||||
|
||||
def base64decode(string):
|
||||
return string.decode("base64")
|
||||
|
||||
@@ -77,6 +79,9 @@ def urldecode(string):
|
||||
return result
|
||||
|
||||
def urlencode(string, safe=":/?%&=", convall=False):
|
||||
if conf.direct:
|
||||
return string
|
||||
|
||||
result = None
|
||||
|
||||
if string is None:
|
||||
|
||||
@@ -92,7 +92,7 @@ class Dump:
|
||||
if isinstance(element, str):
|
||||
self.__write("[*] %s" % element)
|
||||
elif isinstance(element, (list, tuple, set)):
|
||||
self.__write("[*] " + ", ".join(e for e in element))
|
||||
self.__write("[*] " + ", ".join(str(e) for e in element))
|
||||
|
||||
if elements:
|
||||
self.__write("")
|
||||
@@ -321,11 +321,11 @@ class Dump:
|
||||
info = tableValues[column]
|
||||
value = info["values"][i]
|
||||
|
||||
if re.search("^[\ *]*$", value):
|
||||
if re.search("^[\ *]*$", str(value)):
|
||||
value = "NULL"
|
||||
|
||||
maxlength = int(info["length"])
|
||||
blank = " " * (maxlength - len(value))
|
||||
blank = " " * (maxlength - len(str(value)))
|
||||
self.__write("| %s%s" % (value, blank), n=False)
|
||||
|
||||
if not conf.multipleTargets and field == fields:
|
||||
|
||||
@@ -37,6 +37,7 @@ from ConfigParser import ConfigParser
|
||||
from lib.core.common import getFileType
|
||||
from lib.core.common import normalizePath
|
||||
from lib.core.common import ntToPosixSlashes
|
||||
from lib.core.common import parseTargetDirect
|
||||
from lib.core.common import parseTargetUrl
|
||||
from lib.core.common import paths
|
||||
from lib.core.common import randomRange
|
||||
@@ -58,6 +59,9 @@ from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import PGSQL_ALIASES
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
from lib.core.settings import SQLITE_ALIASES
|
||||
from lib.core.settings import ACCESS_ALIASES
|
||||
from lib.core.settings import FIREBIRD_ALIASES
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import PLATFORM
|
||||
from lib.core.settings import SITE
|
||||
@@ -493,7 +497,10 @@ def __setDBMS():
|
||||
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||
"|".join([alias for alias in MYSQL_ALIASES]),
|
||||
"|".join([alias for alias in PGSQL_ALIASES]),
|
||||
"|".join([alias for alias in ORACLE_ALIASES]))
|
||||
"|".join([alias for alias in ORACLE_ALIASES]),
|
||||
"|".join([alias for alias in SQLITE_ALIASES]),
|
||||
"|".join([alias for alias in ACCESS_ALIASES]),
|
||||
"|".join([alias for alias in FIREBIRD_ALIASES]))
|
||||
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms)
|
||||
|
||||
if dbmsRegExp:
|
||||
@@ -606,7 +613,7 @@ def __setHTTPAuthentication():
|
||||
|
||||
elif aTypeLower == "digest":
|
||||
authHandler = urllib2.HTTPDigestAuthHandler(passwordMgr)
|
||||
|
||||
|
||||
elif aTypeLower == "ntlm":
|
||||
try:
|
||||
from ntlm import HTTPNtlmAuthHandler
|
||||
@@ -861,6 +868,7 @@ def __setConfAttributes():
|
||||
logger.debug(debugMsg)
|
||||
|
||||
conf.cj = None
|
||||
conf.dbmsConnector = None
|
||||
conf.dbmsHandler = None
|
||||
conf.dumpPath = None
|
||||
conf.httpHeaders = []
|
||||
@@ -1045,28 +1053,30 @@ def init(inputOptions=advancedDict()):
|
||||
__setConfAttributes()
|
||||
__setKnowledgeBaseAttributes()
|
||||
__cleanupOptions()
|
||||
|
||||
__setRequestFromFile()
|
||||
|
||||
parseTargetUrl()
|
||||
|
||||
__setHTTPTimeout()
|
||||
__setHTTPCookies()
|
||||
__setHTTPReferer()
|
||||
__setHTTPUserAgent()
|
||||
__setHTTPExtraHeaders()
|
||||
__setHTTPMethod()
|
||||
__setHTTPAuthentication()
|
||||
__setHTTPProxy()
|
||||
parseTargetUrl()
|
||||
parseTargetDirect()
|
||||
|
||||
if conf.url or conf.list or conf.requestFile or conf.googleDork:
|
||||
__setHTTPTimeout()
|
||||
__setHTTPCookies()
|
||||
__setHTTPReferer()
|
||||
__setHTTPUserAgent()
|
||||
__setHTTPExtraHeaders()
|
||||
__setHTTPMethod()
|
||||
__setHTTPAuthentication()
|
||||
__setHTTPProxy()
|
||||
__setUnionTech()
|
||||
__setGoogleDorking()
|
||||
__setMultipleTargets()
|
||||
__urllib2Opener()
|
||||
__setDBMS()
|
||||
|
||||
__setThreads()
|
||||
__setDBMS()
|
||||
__setOS()
|
||||
__setUnionTech()
|
||||
__setWriteFile()
|
||||
__setMetasploit()
|
||||
__setGoogleDorking()
|
||||
__setMultipleTargets()
|
||||
__urllib2Opener()
|
||||
|
||||
update()
|
||||
queriesParser()
|
||||
|
||||
@@ -25,6 +25,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
optDict = {
|
||||
# Family: { "parameter_name": "parameter_datatype" },
|
||||
"Target": {
|
||||
"direct": "string",
|
||||
"url": "string",
|
||||
"list": "string",
|
||||
"requestFile": "string",
|
||||
|
||||
@@ -43,6 +43,10 @@ def __setRequestParams():
|
||||
HTTP method POST.
|
||||
"""
|
||||
|
||||
if conf.direct:
|
||||
conf.parameters[None] = "direct connection"
|
||||
return
|
||||
|
||||
__testableParameters = False
|
||||
|
||||
# Perform checks on GET parameters
|
||||
|
||||
Reference in New Issue
Block a user