mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-01-09 08:09:01 +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:
81
plugins/generic/connector.py
Normal file
81
plugins/generic/connector.py
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2010 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 021101301 USA
|
||||
"""
|
||||
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapUndefinedMethod
|
||||
|
||||
class Connector:
|
||||
"""
|
||||
This class defines generic dbms protocol functionalities for plugins.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.connector = None
|
||||
self.cursor = None
|
||||
|
||||
def initConnection(self):
|
||||
self.user = conf.dbmsUser
|
||||
self.password = conf.dbmsPass
|
||||
self.hostname = conf.hostname
|
||||
self.port = conf.port
|
||||
self.db = conf.dbmsDb
|
||||
|
||||
def connected(self):
|
||||
infoMsg = "connection to %s server %s" % (conf.dbms, self.hostname)
|
||||
infoMsg += ":%d established" % self.port
|
||||
logger.info(infoMsg)
|
||||
|
||||
def connect(self):
|
||||
errMsg = "'connect' method must be defined "
|
||||
errMsg += "into the specific DBMS plugin"
|
||||
raise sqlmapUndefinedMethod, errMsg
|
||||
|
||||
def fetchall(self):
|
||||
errMsg = "'fetchall' method must be defined "
|
||||
errMsg += "into the specific DBMS plugin"
|
||||
raise sqlmapUndefinedMethod, errMsg
|
||||
|
||||
def execute(self, query):
|
||||
errMsg = "'execute' method must be defined "
|
||||
errMsg += "into the specific DBMS plugin"
|
||||
raise sqlmapUndefinedMethod, errMsg
|
||||
|
||||
def select(self, query):
|
||||
errMsg = "'select' method must be defined "
|
||||
errMsg += "into the specific DBMS plugin"
|
||||
raise sqlmapUndefinedMethod, errMsg
|
||||
|
||||
def setCursor(self):
|
||||
errMsg = "'setCursor' method must be defined "
|
||||
errMsg += "into the specific DBMS plugin"
|
||||
raise sqlmapUndefinedMethod, errMsg
|
||||
|
||||
def getCursor(self):
|
||||
return self.cursor
|
||||
|
||||
def close(self):
|
||||
errMsg = "'close' method must be defined "
|
||||
errMsg += "into the specific DBMS plugin"
|
||||
raise sqlmapUndefinedMethod, errMsg
|
||||
@@ -139,7 +139,7 @@ class Enumeration:
|
||||
condition = ( kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ) )
|
||||
condition |= ( kb.dbms == "MySQL" and not kb.data.has_information_schema )
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
if condition:
|
||||
query = rootQuery["inband"]["query2"]
|
||||
else:
|
||||
@@ -196,7 +196,7 @@ class Enumeration:
|
||||
|
||||
logger.info(infoMsg)
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
if kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
||||
query = rootQuery["inband"]["query2"]
|
||||
else:
|
||||
@@ -393,7 +393,7 @@ class Enumeration:
|
||||
"E": "EXECUTE"
|
||||
}
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
|
||||
query = rootQuery["inband"]["query2"]
|
||||
condition = rootQuery["inband"]["condition2"]
|
||||
@@ -439,7 +439,7 @@ class Enumeration:
|
||||
|
||||
# In PostgreSQL we get 1 if the privilege is
|
||||
# True, 0 otherwise
|
||||
if kb.dbms == "PostgreSQL" and privilege.isdigit():
|
||||
if kb.dbms == "PostgreSQL" and str(privilege).isdigit():
|
||||
for position, pgsqlPriv in pgsqlPrivs:
|
||||
if count == position and int(privilege) == 1:
|
||||
privileges.add(pgsqlPriv)
|
||||
@@ -639,7 +639,7 @@ class Enumeration:
|
||||
|
||||
rootQuery = queries[kb.dbms].dbs
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
|
||||
query = rootQuery["inband"]["query2"]
|
||||
else:
|
||||
@@ -696,7 +696,7 @@ class Enumeration:
|
||||
|
||||
rootQuery = queries[kb.dbms].tables
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
query = rootQuery["inband"]["query"]
|
||||
condition = rootQuery["inband"]["condition"]
|
||||
|
||||
@@ -855,7 +855,7 @@ class Enumeration:
|
||||
infoMsg += "on database '%s'" % conf.db
|
||||
logger.info(infoMsg)
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
query = rootQuery["inband"]["query"] % (conf.tbl, conf.db)
|
||||
query += condQuery
|
||||
@@ -1039,7 +1039,7 @@ class Enumeration:
|
||||
colQuery = "%s%s" % (colCond, colCondParam)
|
||||
colQuery = colQuery % column
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
query = rootQuery["inband"]["query"]
|
||||
query += colQuery
|
||||
query += dbsQuery
|
||||
@@ -1095,7 +1095,7 @@ class Enumeration:
|
||||
infoMsg += " '%s' in database '%s'" % (column, db)
|
||||
logger.info(infoMsg)
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
query = rootQuery["inband"]["query2"]
|
||||
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
@@ -1321,7 +1321,7 @@ class Enumeration:
|
||||
|
||||
entriesCount = 0
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
if kb.dbms == "Oracle":
|
||||
query = rootQuery["inband"]["query"] % (colString, conf.tbl.upper())
|
||||
elif kb.dbms == "SQLite":
|
||||
@@ -1349,7 +1349,7 @@ class Enumeration:
|
||||
else:
|
||||
colEntry = entry[index]
|
||||
|
||||
colEntryLen = len(colEntry)
|
||||
colEntryLen = len(str(colEntry))
|
||||
maxLen = max(colLen, colEntryLen)
|
||||
|
||||
if maxLen > kb.data.dumpedTable[column]["length"]:
|
||||
|
||||
@@ -29,13 +29,13 @@ from lib.core.agent import agent
|
||||
from lib.core.common import dataToOutFile
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapUndefinedMethod
|
||||
from lib.request import inject
|
||||
from lib.techniques.outband.stacked import stackedTest
|
||||
|
||||
|
||||
class Filesystem:
|
||||
"""
|
||||
This class defines generic OS file system functionalities for plugins.
|
||||
@@ -278,18 +278,19 @@ class Filesystem:
|
||||
|
||||
self.checkDbmsOs()
|
||||
|
||||
if not kb.stackedTest:
|
||||
if conf.direct or kb.stackedTest:
|
||||
if kb.stackedTest:
|
||||
debugMsg = "going to read the file with stacked query SQL "
|
||||
debugMsg += "injection technique"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
fileContent = self.stackedReadFile(rFile)
|
||||
else:
|
||||
debugMsg = "going to read the file with UNION query SQL "
|
||||
debugMsg += "injection technique"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
fileContent = self.unionReadFile(rFile)
|
||||
else:
|
||||
debugMsg = "going to read the file with stacked query SQL "
|
||||
debugMsg += "injection technique"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
fileContent = self.stackedReadFile(rFile)
|
||||
|
||||
if fileContent in ( None, "" ) and kb.dbms != "PostgreSQL":
|
||||
self.cleanup(onlyFileTbl=True)
|
||||
@@ -319,16 +320,17 @@ class Filesystem:
|
||||
|
||||
self.checkDbmsOs()
|
||||
|
||||
if not kb.stackedTest:
|
||||
if conf.direct or kb.stackedTest:
|
||||
if kb.stackedTest:
|
||||
debugMsg = "going to upload the %s file with " % fileType
|
||||
debugMsg += "stacked query SQL injection technique"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
self.stackedWriteFile(wFile, dFile, fileType, confirm)
|
||||
self.cleanup(onlyFileTbl=True)
|
||||
else:
|
||||
debugMsg = "going to upload the %s file with " % fileType
|
||||
debugMsg += "UNION query SQL injection technique"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
self.unionWriteFile(wFile, dFile, fileType, confirm)
|
||||
else:
|
||||
debugMsg = "going to upload the %s file with " % fileType
|
||||
debugMsg += "stacked query SQL injection technique"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
self.stackedWriteFile(wFile, dFile, fileType, confirm)
|
||||
self.cleanup(onlyFileTbl=True)
|
||||
|
||||
@@ -98,6 +98,9 @@ class Miscellaneous:
|
||||
|
||||
query = queries[kb.dbms].substring % (queries[kb.dbms].banner, first, last)
|
||||
|
||||
if conf.direct:
|
||||
query = "SELECT %s" % query
|
||||
|
||||
kb.bannerFp["dbmsVersion"] = inject.getValue(query, unpack=False)
|
||||
kb.bannerFp["dbmsVersion"] = kb.bannerFp["dbmsVersion"].replace(",", "").replace("-", "").replace(" ", "")
|
||||
|
||||
@@ -127,7 +130,7 @@ class Miscellaneous:
|
||||
|
||||
stackedTest()
|
||||
|
||||
if not kb.stackedTest:
|
||||
if not kb.stackedTest and not conf.direct:
|
||||
return
|
||||
|
||||
if kb.os == "Windows":
|
||||
|
||||
@@ -51,7 +51,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||
def osCmd(self):
|
||||
stackedTest()
|
||||
|
||||
if kb.stackedTest:
|
||||
if kb.stackedTest or conf.direct:
|
||||
web = False
|
||||
elif not kb.stackedTest and kb.dbms == "MySQL":
|
||||
infoMsg = "going to use a web backdoor for command execution"
|
||||
@@ -74,7 +74,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||
def osShell(self):
|
||||
stackedTest()
|
||||
|
||||
if kb.stackedTest:
|
||||
if kb.stackedTest or conf.direct:
|
||||
web = False
|
||||
elif not kb.stackedTest and kb.dbms == "MySQL":
|
||||
infoMsg = "going to use a web backdoor for command prompt"
|
||||
@@ -99,7 +99,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||
|
||||
stackedTest()
|
||||
|
||||
if kb.stackedTest:
|
||||
if kb.stackedTest or conf.direct:
|
||||
web = False
|
||||
|
||||
self.initEnv(web=web)
|
||||
@@ -195,7 +195,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||
errMsg += "relay attack"
|
||||
raise sqlmapUnsupportedDBMSException(errMsg)
|
||||
|
||||
if not kb.stackedTest:
|
||||
if not kb.stackedTest and not conf.direct:
|
||||
if kb.dbms in ( "PostgreSQL", "Microsoft SQL Server" ):
|
||||
errMsg = "on this back-end DBMS it is only possible to "
|
||||
errMsg += "perform the SMB relay attack if stacked "
|
||||
@@ -239,7 +239,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||
def osBof(self):
|
||||
stackedTest()
|
||||
|
||||
if not kb.stackedTest:
|
||||
if not kb.stackedTest and not conf.direct:
|
||||
return
|
||||
|
||||
if not kb.dbms == "Microsoft SQL Server" or kb.dbmsVersion[0] not in ( "2000", "2005" ):
|
||||
@@ -267,7 +267,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||
def __regInit(self):
|
||||
stackedTest()
|
||||
|
||||
if not kb.stackedTest:
|
||||
if not kb.stackedTest and not conf.direct:
|
||||
return
|
||||
|
||||
self.checkDbmsOs()
|
||||
|
||||
Reference in New Issue
Block a user