mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-09 22:21:30 +00:00
Added support to directly connect also to Microsoft SQL Server database.
Fixed direct connection to always use the same query as of UNION query SQL injection (= one query with multiple columns/entries output). Minor fixes to Firebird/Access/SQLite connectors to use connector's execute()/fetchall() as wrapper for third-party libraries' methods. Forced conf.timeout to 10 seconds when directly connecting to database. Slightly improved regular expression to parse -d parameter. Added import check for all connectors' third-party libraries. Code refactoring: * Moved conf.direct request to direct() function in lib/request/direct.py (code reused where needed). * Back-delegated to generic connector close() and other methods.
This commit is contained in:
@@ -45,15 +45,14 @@ class Connector(GenericConnector):
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self, reuse=True):
|
||||
if reuse and self.connector:
|
||||
return
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
self.checkFileDb()
|
||||
|
||||
try:
|
||||
#self.connector = pyodbc.connect(driver='{Microsoft Access Driver (*.mdb)}', dbq=self.db, uid='Admin')
|
||||
self.connector = pyodbc.connect('Driver={Microsoft Access Driver (*.mdb)};Dbq=%s;Uid=Admin;Pwd=;' % self.db)
|
||||
self.connector.timeout = conf.timeout
|
||||
except pyodbc.OperationalError, msg:
|
||||
raise sqlmapConnectionException, msg[1]
|
||||
|
||||
@@ -63,7 +62,7 @@ class Connector(GenericConnector):
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except pyodbc.OperationalError, msg:
|
||||
except pyodbc.ProgrammingError, msg:
|
||||
logger.log(8, msg[1])
|
||||
return None
|
||||
|
||||
@@ -80,18 +79,5 @@ class Connector(GenericConnector):
|
||||
self.connector.commit()
|
||||
|
||||
def select(self, query):
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
return self.cursor.fetchall()
|
||||
except pyodbc.ProgrammingError, msg:
|
||||
logger.log(8, msg[1])
|
||||
return None
|
||||
|
||||
def setCursor(self):
|
||||
self.cursor = self.connector.cursor()
|
||||
|
||||
def close(self):
|
||||
self.cursor.close()
|
||||
self.connector.close()
|
||||
self.closed()
|
||||
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
|
||||
@@ -140,6 +140,7 @@ class Fingerprint(GenericFingerprint):
|
||||
def checkDbms(self):
|
||||
if conf.dbms in ACCESS_ALIASES:
|
||||
setDbms("Microsoft Access")
|
||||
|
||||
if not conf.extensiveFp:
|
||||
return True
|
||||
|
||||
|
||||
@@ -37,20 +37,21 @@ class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: http://kinterbasdb.sourceforge.net/
|
||||
User guide: http://kinterbasdb.sourceforge.net/dist_docs/usage.html
|
||||
Debian package: python-kinterbasdb
|
||||
License: BSD
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self, reuse=True):
|
||||
if reuse and self.connector:
|
||||
return
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
if not self.hostname:
|
||||
self.checkFileDb()
|
||||
|
||||
try:
|
||||
self.connector = kinterbasdb.connect(database=self.db, user=self.user, password=self.password, timeout={'period': conf.timeout})
|
||||
self.connector = kinterbasdb.connect(host=self.hostname, database=self.db, user=self.user, password=self.password, timeout={'period': conf.timeout})
|
||||
except kinterbasdb.OperationalError, msg:
|
||||
raise sqlmapConnectionException, msg[1]
|
||||
|
||||
@@ -77,13 +78,5 @@ class Connector(GenericConnector):
|
||||
self.connector.commit()
|
||||
|
||||
def select(self, query):
|
||||
self.cursor.execute(query)
|
||||
return self.cursor.fetchall()
|
||||
|
||||
def setCursor(self):
|
||||
self.cursor = self.connector.cursor()
|
||||
|
||||
def close(self):
|
||||
self.cursor.close()
|
||||
self.connector.close()
|
||||
self.closed()
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
|
||||
@@ -23,10 +23,12 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
try:
|
||||
import _mssql
|
||||
import pymssql
|
||||
except ImportError, _:
|
||||
pass
|
||||
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
|
||||
@@ -45,3 +47,38 @@ class Connector(GenericConnector):
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = pymssql.connect(host="%s:%d" % (self.hostname, self.port), user=self.user, password=self.password, database=self.db, login_timeout=conf.timeout, timeout=conf.timeout)
|
||||
except pymssql.OperationalError, msg:
|
||||
raise sqlmapConnectionException, msg
|
||||
|
||||
self.setCursor()
|
||||
self.connected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except (pymssql.ProgrammingError, pymssql.OperationalError, _mssql.MssqlDatabaseException), msg:
|
||||
logger.log(8, msg)
|
||||
return None
|
||||
|
||||
def execute(self, query):
|
||||
logger.debug(query)
|
||||
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
except (pymssql.OperationalError, pymssql.ProgrammingError), msg:
|
||||
logger.log(8, msg)
|
||||
except pymssql.InternalError, msg:
|
||||
raise sqlmapConnectionException, msg
|
||||
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
value = self.fetchall()
|
||||
self.connector.commit()
|
||||
|
||||
return value
|
||||
|
||||
@@ -61,7 +61,7 @@ class Enumeration(GenericEnumeration):
|
||||
else:
|
||||
dbs = [conf.db]
|
||||
|
||||
if kb.unionPosition:
|
||||
if kb.unionPosition or conf.direct:
|
||||
for db in dbs:
|
||||
if conf.excludeSysDbs and db in self.excludeDbsList:
|
||||
infoMsg = "skipping system database '%s'" % db
|
||||
@@ -75,7 +75,7 @@ class Enumeration(GenericEnumeration):
|
||||
if value:
|
||||
kb.data.cachedTables[db] = value
|
||||
|
||||
if not kb.data.cachedTables:
|
||||
if not kb.data.cachedTables and not conf.direct:
|
||||
for db in dbs:
|
||||
if conf.excludeSysDbs and db in self.excludeDbsList:
|
||||
infoMsg = "skipping system database '%s'" % db
|
||||
|
||||
@@ -97,8 +97,13 @@ class Fingerprint(GenericFingerprint):
|
||||
infoMsg = "testing Microsoft SQL Server"
|
||||
logger.info(infoMsg)
|
||||
|
||||
payload = agent.fullPayload(" AND LEN(@@VERSION)=LEN(@@VERSION)")
|
||||
result = Request.queryPage(payload)
|
||||
# NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not work connecting
|
||||
# directly to the Microsoft SQL Server database
|
||||
if conf.direct:
|
||||
result = True
|
||||
else:
|
||||
payload = agent.fullPayload(" AND LEN(@@VERSION)=LEN(@@VERSION)")
|
||||
result = Request.queryPage(payload)
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming Microsoft SQL Server"
|
||||
|
||||
@@ -47,10 +47,7 @@ class Connector(GenericConnector):
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self, reuse=True):
|
||||
if reuse and self.connector:
|
||||
return
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
@@ -83,11 +80,3 @@ class Connector(GenericConnector):
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
|
||||
def setCursor(self):
|
||||
self.cursor = self.connector.cursor()
|
||||
|
||||
def close(self):
|
||||
self.cursor.close()
|
||||
self.connector.close()
|
||||
self.closed()
|
||||
|
||||
@@ -154,9 +154,6 @@ class Fingerprint(GenericFingerprint):
|
||||
* http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn)
|
||||
"""
|
||||
|
||||
infoMsg = "testing MySQL"
|
||||
logger.info(infoMsg)
|
||||
|
||||
if conf.dbms in MYSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit():
|
||||
setDbms("MySQL %s" % kb.dbmsVersion[0])
|
||||
|
||||
@@ -168,6 +165,9 @@ class Fingerprint(GenericFingerprint):
|
||||
if not conf.extensiveFp:
|
||||
return True
|
||||
|
||||
infoMsg = "testing MySQL"
|
||||
logger.info(infoMsg)
|
||||
|
||||
randInt = str(randomInt(1))
|
||||
payload = agent.fullPayload(" AND CONNECTION_ID()=CONNECTION_ID()")
|
||||
result = Request.queryPage(payload)
|
||||
|
||||
@@ -37,19 +37,13 @@ class Connector(GenericConnector):
|
||||
Homepage: http://cx-oracle.sourceforge.net/
|
||||
User guide: http://cx-oracle.sourceforge.net/README.txt
|
||||
API: http://cx-oracle.sourceforge.net/html/index.html
|
||||
Debian package: -
|
||||
License: http://cx-oracle.sourceforge.net/LICENSE.txt
|
||||
|
||||
Possible connectors: -
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self, reuse=True):
|
||||
if reuse and self.connector:
|
||||
return
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
self.__dsn = cx_Oracle.makedsn(self.hostname, self.port, self.db)
|
||||
|
||||
@@ -87,11 +81,3 @@ class Connector(GenericConnector):
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
|
||||
def setCursor(self):
|
||||
self.cursor = self.connector.cursor()
|
||||
|
||||
def close(self):
|
||||
self.cursor.close()
|
||||
self.connector.close()
|
||||
self.closed()
|
||||
|
||||
@@ -96,7 +96,7 @@ class Enumeration(GenericEnumeration):
|
||||
else:
|
||||
kb.data.cachedUsersRoles[user] = list(roles)
|
||||
|
||||
if not kb.data.cachedUsersRoles:
|
||||
if not kb.data.cachedUsersRoles and not conf.direct:
|
||||
conditionChar = "="
|
||||
|
||||
if conf.user:
|
||||
|
||||
@@ -78,9 +78,6 @@ class Fingerprint(GenericFingerprint):
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
logMsg = "testing Oracle"
|
||||
logger.info(logMsg)
|
||||
|
||||
if conf.dbms in ORACLE_ALIASES:
|
||||
setDbms("Oracle")
|
||||
|
||||
@@ -89,6 +86,9 @@ class Fingerprint(GenericFingerprint):
|
||||
if not conf.extensiveFp:
|
||||
return True
|
||||
|
||||
logMsg = "testing Oracle"
|
||||
logger.info(logMsg)
|
||||
|
||||
# NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting
|
||||
# directly to the Oracle database
|
||||
if conf.direct:
|
||||
|
||||
@@ -46,10 +46,7 @@ class Connector(GenericConnector):
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self, reuse=True):
|
||||
if reuse and self.connector:
|
||||
return
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
@@ -82,11 +79,3 @@ class Connector(GenericConnector):
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
|
||||
def setCursor(self):
|
||||
self.cursor = self.connector.cursor()
|
||||
|
||||
def close(self):
|
||||
self.cursor.close()
|
||||
self.connector.close()
|
||||
self.closed()
|
||||
|
||||
@@ -86,9 +86,6 @@ class Fingerprint(GenericFingerprint):
|
||||
* http://www.postgresql.org/docs/8.4/interactive/release.html (up to 8.4.2)
|
||||
"""
|
||||
|
||||
infoMsg = "testing PostgreSQL"
|
||||
logger.info(infoMsg)
|
||||
|
||||
if conf.dbms in PGSQL_ALIASES:
|
||||
setDbms("PostgreSQL")
|
||||
|
||||
@@ -97,6 +94,9 @@ class Fingerprint(GenericFingerprint):
|
||||
if not conf.extensiveFp:
|
||||
return True
|
||||
|
||||
infoMsg = "testing PostgreSQL"
|
||||
logger.info(infoMsg)
|
||||
|
||||
randInt = str(randomInt(1))
|
||||
|
||||
payload = agent.fullPayload(" AND %s::int=%s" % (randInt, randInt))
|
||||
|
||||
@@ -39,7 +39,7 @@ class Connector(GenericConnector):
|
||||
User guide: http://docs.python.org/release/2.5/lib/module-sqlite3.html
|
||||
API: http://docs.python.org/library/sqlite3.html
|
||||
Debian package: python-pysqlite2
|
||||
License: zlib/libpng
|
||||
License: MIT
|
||||
|
||||
Possible connectors: http://wiki.python.org/moin/SQLite
|
||||
"""
|
||||
@@ -47,11 +47,9 @@ class Connector(GenericConnector):
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self, reuse=True):
|
||||
if reuse and self.connector:
|
||||
return
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
self.checkFileDb()
|
||||
|
||||
try:
|
||||
self.connector = sqlite3.connect(database=self.db, timeout=conf.timeout)
|
||||
@@ -75,19 +73,11 @@ class Connector(GenericConnector):
|
||||
self.cursor.execute(query)
|
||||
except sqlite3.OperationalError, msg:
|
||||
logger.log(8, msg[0])
|
||||
except sqlite3.Error, msg:
|
||||
except sqlite3.DatabaseError, msg:
|
||||
raise sqlmapConnectionException, msg[0]
|
||||
|
||||
self.connector.commit()
|
||||
|
||||
def select(self, query):
|
||||
self.cursor.execute(query)
|
||||
return self.cursor.fetchall()
|
||||
|
||||
def setCursor(self):
|
||||
self.cursor = self.connector.cursor()
|
||||
|
||||
def close(self):
|
||||
self.cursor.close()
|
||||
self.connector.close()
|
||||
self.closed()
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
|
||||
Reference in New Issue
Block a user