mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 11:03:47 +03: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:
parent
d583cc07e7
commit
5fdebb5d5b
|
@ -65,9 +65,6 @@ def action():
|
|||
|
||||
raise sqlmapUnsupportedDBMSException, errMsg
|
||||
|
||||
if conf.direct:
|
||||
conf.dbmsConnector.connect()
|
||||
|
||||
print "%s\n" % conf.dbmsHandler.getFingerprint()
|
||||
|
||||
# Techniques options
|
||||
|
|
|
@ -79,6 +79,9 @@ def setHandler():
|
|||
conf.dbmsConnector = dbmsConn()
|
||||
|
||||
if conf.direct:
|
||||
logger.debug("forcing timeout to 10 seconds")
|
||||
conf.timeout = 10
|
||||
|
||||
conf.dbmsConnector.connect()
|
||||
|
||||
if handler.checkDbms():
|
||||
|
|
|
@ -606,49 +606,50 @@ def parseTargetDirect():
|
|||
details = None
|
||||
|
||||
for dbms in SUPPORTED_DBMS:
|
||||
details = re.search("^(?P<dbms>%s)://(?P<credentials>(?P<dbmsUser>.+?)\:(?P<dbmsPass>.+?)\@)?(?P<remote>(?P<hostname>.+?)\:(?P<port>[\d]+)\/)?(?P<dbmsDb>.+?)$" % dbms, conf.direct, re.I)
|
||||
details = re.search("^(?P<dbms>%s)://(?P<credentials>(?P<user>.+?)\:(?P<pass>.+?)\@)?(?P<remote>(?P<hostname>.+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\.\_\-\/]+?)$" % dbms, conf.direct, re.I)
|
||||
|
||||
if details:
|
||||
conf.dbms = details.group('dbms')
|
||||
|
||||
conf.dbms = details.group('dbms')
|
||||
|
||||
if details.group('credentials'):
|
||||
conf.dbmsUser = details.group('dbmsUser')
|
||||
conf.dbmsPass = details.group('dbmsPass')
|
||||
conf.dbmsUser = details.group('user')
|
||||
conf.dbmsPass = details.group('pass')
|
||||
else:
|
||||
conf.dbmsUser = str()
|
||||
conf.dbmsPass = str()
|
||||
|
||||
|
||||
if details.group('remote'):
|
||||
conf.hostname = details.group('hostname')
|
||||
conf.port = int(details.group('port'))
|
||||
else:
|
||||
conf.hostname = "localhost"
|
||||
conf.port = 0
|
||||
|
||||
conf.dbmsDb = details.group('dbmsDb')
|
||||
conf.port = 0
|
||||
|
||||
conf.dbmsDb = details.group('db')
|
||||
|
||||
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'"
|
||||
errMsg += " and/or: 'access://DATABASE_FILEPATH'"
|
||||
errMsg = "invalid target details, valid syntax is for instance "
|
||||
errMsg += "'mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME' "
|
||||
errMsg += "or 'access://DATABASE_FILEPATH'"
|
||||
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, "python cx_Oracle", "http://cx-oracle.sourceforge.net/"],
|
||||
"SQLite": [SQLITE_ALIASES, "", ""],
|
||||
"Access": [ACCESS_ALIASES, "", ""],
|
||||
"Firebird": [FIREBIRD_ALIASES, "", ""] }
|
||||
"SQLite": [SQLITE_ALIASES, "python-pysqlite2", "http://pysqlite.googlecode.com/"],
|
||||
"Access": [ACCESS_ALIASES, "python-pyodbc", "http://pyodbc.googlecode.com/"],
|
||||
"Firebird": [FIREBIRD_ALIASES, "python-kinterbasdb", "http://kinterbasdb.sourceforge.net/"] }
|
||||
|
||||
for dbmsName, data in dbmsDict.items():
|
||||
if conf.dbms in data[0]:
|
||||
try:
|
||||
if dbmsName == "Microsoft SQL Server":
|
||||
import _mssql
|
||||
import pymssql
|
||||
elif dbmsName == "MySQL":
|
||||
import MySQLdb
|
||||
|
@ -656,6 +657,12 @@ def parseTargetDirect():
|
|||
import psycopg2
|
||||
elif dbmsName == "Oracle":
|
||||
import cx_Oracle
|
||||
elif dbmsName == "SQLite":
|
||||
import sqlite3
|
||||
elif dbmsName == "Access":
|
||||
import pyodbc
|
||||
elif dbmsName == "Firebird":
|
||||
import kinterbasdb
|
||||
except ImportError, _:
|
||||
errMsg = "sqlmap requires %s third-party library " % data[1]
|
||||
errMsg += "in order to directly connect to the database "
|
||||
|
|
|
@ -42,6 +42,7 @@ from lib.core.settings import SQL_STATEMENTS
|
|||
from lib.request.basic import decodePage
|
||||
from lib.request.basic import forgeHeaders
|
||||
from lib.request.basic import parseResponse
|
||||
from lib.request.direct import direct
|
||||
from lib.request.comparison import comparison
|
||||
|
||||
|
||||
|
@ -265,39 +266,7 @@ class Connect:
|
|||
"""
|
||||
|
||||
if conf.direct:
|
||||
values = None
|
||||
select = False
|
||||
|
||||
if kb.dbms == "Oracle" and value.startswith("SELECT ") and " FROM " not in value:
|
||||
value = "%s FROM DUAL" % value
|
||||
|
||||
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
||||
for sqlStatement in sqlStatements:
|
||||
if value.lower().startswith(sqlStatement) and sqlTitle == "SQL SELECT statement":
|
||||
select = True
|
||||
break
|
||||
|
||||
if select:
|
||||
values = conf.dbmsConnector.select(value)
|
||||
else:
|
||||
values = conf.dbmsConnector.execute(value)
|
||||
|
||||
if values is None or len(values) == 0:
|
||||
return None
|
||||
elif content:
|
||||
if len(values) == 1:
|
||||
if len(values[0]) == 1:
|
||||
return str(list(values)[0][0]), None
|
||||
else:
|
||||
return list(values), None
|
||||
else:
|
||||
return values, None
|
||||
else:
|
||||
for value in values:
|
||||
if value[0] in (1, -1):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return direct(value, content)
|
||||
|
||||
get = None
|
||||
post = None
|
||||
|
|
64
lib/request/direct.py
Normal file
64
lib/request/direct.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/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 02110-1301 USA
|
||||
"""
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.settings import SQL_STATEMENTS
|
||||
|
||||
def direct(query, content=True):
|
||||
output = None
|
||||
select = False
|
||||
query = agent.payloadDirect(query)
|
||||
|
||||
if kb.dbms == "Oracle" and query.startswith("SELECT ") and " FROM " not in query:
|
||||
query = "%s FROM DUAL" % query
|
||||
|
||||
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
||||
for sqlStatement in sqlStatements:
|
||||
if query.lower().startswith(sqlStatement) and sqlTitle == "SQL SELECT statement":
|
||||
select = True
|
||||
break
|
||||
|
||||
if select:
|
||||
output = conf.dbmsConnector.select(query)
|
||||
else:
|
||||
output = conf.dbmsConnector.execute(query)
|
||||
|
||||
if output is None or len(output) == 0:
|
||||
return None
|
||||
elif content:
|
||||
if len(output) == 1:
|
||||
if len(output[0]) == 1:
|
||||
return str(list(output)[0][0])
|
||||
else:
|
||||
return list(output)
|
||||
else:
|
||||
return output
|
||||
else:
|
||||
for line in output:
|
||||
if line[0] in (1, -1):
|
||||
return True
|
||||
else:
|
||||
return False
|
|
@ -37,6 +37,7 @@ from lib.core.data import logger
|
|||
from lib.core.data import queries
|
||||
from lib.core.data import temp
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.request.direct import direct
|
||||
from lib.core.settings import SQL_STATEMENTS
|
||||
from lib.techniques.inband.union.use import unionUse
|
||||
from lib.techniques.blind.inference import bisection
|
||||
|
@ -352,33 +353,7 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
|
|||
"""
|
||||
|
||||
if conf.direct:
|
||||
expression = agent.payloadDirect(expression)
|
||||
values = None
|
||||
select = False
|
||||
|
||||
if kb.dbms == "Oracle" and expression.startswith("SELECT ") and " FROM " not in expression:
|
||||
expression = "%s FROM DUAL" % expression
|
||||
|
||||
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
||||
for sqlStatement in sqlStatements:
|
||||
if expression.lower().startswith(sqlStatement) and sqlTitle == "SQL SELECT statement":
|
||||
select = True
|
||||
break
|
||||
|
||||
if select:
|
||||
values = conf.dbmsConnector.select(expression)
|
||||
else:
|
||||
values = conf.dbmsConnector.execute(expression)
|
||||
|
||||
if values is None or len(values) == 0:
|
||||
return None
|
||||
elif len(values) == 1:
|
||||
if len(values[0]) == 1:
|
||||
return str(list(values)[0][0])
|
||||
else:
|
||||
return list(values)
|
||||
else:
|
||||
return values
|
||||
return direct(expression)
|
||||
|
||||
expression = cleanQuery(expression)
|
||||
expression = expandAsteriskForColumns(expression)
|
||||
|
@ -418,25 +393,7 @@ def goStacked(expression, silent=False):
|
|||
expression = cleanQuery(expression)
|
||||
|
||||
if conf.direct:
|
||||
expression = agent.payloadDirect(expression)
|
||||
values = None
|
||||
select = False
|
||||
|
||||
if kb.dbms == "Oracle" and expression.startswith("SELECT ") and " FROM " not in expression:
|
||||
expression = "%s FROM DUAL" % expression
|
||||
|
||||
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
||||
for sqlStatement in sqlStatements:
|
||||
if expression.lower().startswith(sqlStatement) and sqlTitle == "SQL SELECT statement":
|
||||
select = True
|
||||
break
|
||||
|
||||
if select:
|
||||
values = conf.dbmsConnector.select(expression)
|
||||
else:
|
||||
values = conf.dbmsConnector.execute(expression)
|
||||
|
||||
return None, None
|
||||
return direct(expression), None
|
||||
|
||||
debugMsg = "query: %s" % expression
|
||||
logger.debug(debugMsg)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -22,8 +22,11 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
|||
Franklin St, Fifth Floor, Boston, MA 021101301 USA
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
from lib.core.exception import sqlmapUndefinedMethod
|
||||
|
||||
class Connector:
|
||||
|
@ -48,12 +51,29 @@ class Connector:
|
|||
logger.info(infoMsg)
|
||||
|
||||
def closed(self):
|
||||
self.connector = None
|
||||
self.cursor = None
|
||||
infoMsg = "connection to %s server %s" % (conf.dbms, self.hostname)
|
||||
infoMsg += ":%d closed" % self.port
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.connector = None
|
||||
self.cursor = None
|
||||
|
||||
def setCursor(self):
|
||||
self.cursor = self.connector.cursor()
|
||||
|
||||
def getCursor(self):
|
||||
return self.cursor
|
||||
|
||||
def close(self):
|
||||
self.cursor.close()
|
||||
self.connector.close()
|
||||
self.closed()
|
||||
|
||||
def checkFileDb(self):
|
||||
if not os.path.exists(self.db):
|
||||
errMsg = "the provided database file '%s' does not exist" % self.db
|
||||
raise sqlmapFilePathException, errMsg
|
||||
|
||||
def connect(self):
|
||||
errMsg = "'connect' method must be defined "
|
||||
errMsg += "into the specific DBMS plugin"
|
||||
|
@ -73,16 +93,3 @@ class Connector:
|
|||
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
|
||||
|
|
|
@ -149,7 +149,7 @@ class Enumeration:
|
|||
if value:
|
||||
kb.data.cachedUsers = value
|
||||
|
||||
if not kb.data.cachedUsers:
|
||||
if not kb.data.cachedUsers and not conf.direct:
|
||||
infoMsg = "fetching number of database users"
|
||||
logger.info(infoMsg)
|
||||
|
||||
|
@ -232,7 +232,7 @@ class Enumeration:
|
|||
else:
|
||||
kb.data.cachedUsersPasswords[user].append(password)
|
||||
|
||||
if not kb.data.cachedUsersPasswords:
|
||||
if not kb.data.cachedUsersPasswords and not conf.direct:
|
||||
if conf.user:
|
||||
if "," in conf.user:
|
||||
users = conf.user.split(",")
|
||||
|
@ -464,7 +464,7 @@ class Enumeration:
|
|||
else:
|
||||
kb.data.cachedUsersPrivileges[user] = list(privileges)
|
||||
|
||||
if not kb.data.cachedUsersPrivileges:
|
||||
if not kb.data.cachedUsersPrivileges and not conf.direct:
|
||||
conditionChar = "="
|
||||
|
||||
if conf.user:
|
||||
|
@ -649,7 +649,7 @@ class Enumeration:
|
|||
if value:
|
||||
kb.data.cachedDbs = value
|
||||
|
||||
if not kb.data.cachedDbs:
|
||||
if not kb.data.cachedDbs and not conf.direct:
|
||||
infoMsg = "fetching number of databases"
|
||||
logger.info(infoMsg)
|
||||
|
||||
|
@ -733,7 +733,7 @@ class Enumeration:
|
|||
else:
|
||||
kb.data.cachedTables[db].append(table)
|
||||
|
||||
if not kb.data.cachedTables:
|
||||
if not kb.data.cachedTables and not conf.direct:
|
||||
if conf.db:
|
||||
if "," in conf.db:
|
||||
dbs = conf.db.split(",")
|
||||
|
@ -881,7 +881,7 @@ class Enumeration:
|
|||
table[conf.tbl] = columns
|
||||
kb.data.cachedColumns[conf.db] = table
|
||||
|
||||
if not kb.data.cachedColumns:
|
||||
if not kb.data.cachedColumns and not conf.direct:
|
||||
infoMsg = "fetching number of columns "
|
||||
infoMsg += "for table '%s'" % conf.tbl
|
||||
infoMsg += " on database '%s'" % conf.db
|
||||
|
@ -1298,8 +1298,10 @@ class Enumeration:
|
|||
colList = conf.col.split(",")
|
||||
kb.data.cachedColumns[conf.db] = {}
|
||||
kb.data.cachedColumns[conf.db][conf.tbl] = {}
|
||||
|
||||
for column in colList:
|
||||
kb.data.cachedColumns[conf.db][conf.tbl][column] = None
|
||||
|
||||
elif not kb.data.cachedColumns:
|
||||
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
|
||||
errMsg = "information_schema not available, "
|
||||
|
@ -1359,7 +1361,7 @@ class Enumeration:
|
|||
|
||||
index += 1
|
||||
|
||||
if not kb.data.dumpedTable:
|
||||
if not kb.data.dumpedTable and not conf.direct:
|
||||
infoMsg = "fetching number of "
|
||||
if conf.col:
|
||||
infoMsg += "columns '%s' " % colString
|
||||
|
|
Loading…
Reference in New Issue
Block a user