Path: blob/master/plugins/dbms/access/fingerprint.py
2992 views
#!/usr/bin/env python12"""3Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)4See the file 'LICENSE' for copying permission5"""67import re89from lib.core.common import Backend10from lib.core.common import Format11from lib.core.common import getCurrentThreadData12from lib.core.common import randomStr13from lib.core.common import wasLastResponseDBMSError14from lib.core.data import conf15from lib.core.data import kb16from lib.core.data import logger17from lib.core.enums import DBMS18from lib.core.session import setDbms19from lib.core.settings import ACCESS_ALIASES20from lib.core.settings import METADB_SUFFIX21from lib.request import inject22from plugins.generic.fingerprint import Fingerprint as GenericFingerprint2324class Fingerprint(GenericFingerprint):25def __init__(self):26GenericFingerprint.__init__(self, DBMS.ACCESS)2728def _sandBoxCheck(self):29# Reference: http://milw0rm.com/papers/19830retVal = None31table = None3233if Backend.isVersionWithin(("97", "2000")):34table = "MSysAccessObjects"35elif Backend.isVersionWithin(("2002-2003", "2007")):36table = "MSysAccessStorage"3738if table is not None:39result = inject.checkBooleanExpression("EXISTS(SELECT CURDIR() FROM %s)" % table)40retVal = "not sandboxed" if result else "sandboxed"4142return retVal4344def _sysTablesCheck(self):45infoMsg = "executing system table(s) existence fingerprint"46logger.info(infoMsg)4748# Microsoft Access table reference updated on 01/201049sysTables = {50"97": ("MSysModules2", "MSysAccessObjects"),51"2000": ("!MSysModules2", "MSysAccessObjects"),52"2002-2003": ("MSysAccessStorage", "!MSysNavPaneObjectIDs"),53"2007": ("MSysAccessStorage", "MSysNavPaneObjectIDs"),54}5556# MSysAccessXML is not a reliable system table because it doesn't always exist57# ("Access through Access", p6, should be "normally doesn't exist" instead of "is normally empty")5859for version, tables in sysTables.items():60exist = True6162for table in tables:63negate = False6465if table[0] == '!':66negate = True67table = table[1:]6869result = inject.checkBooleanExpression("EXISTS(SELECT * FROM %s WHERE [RANDNUM]=[RANDNUM])" % table)70if result is None:71result = False7273if negate:74result = not result7576exist &= result7778if not exist:79break8081if exist:82return version8384return None8586def _getDatabaseDir(self):87retVal = None8889infoMsg = "searching for database directory"90logger.info(infoMsg)9192randStr = randomStr()93inject.checkBooleanExpression("EXISTS(SELECT * FROM %s.%s WHERE [RANDNUM]=[RANDNUM])" % (randStr, randStr))9495if wasLastResponseDBMSError():96threadData = getCurrentThreadData()97match = re.search(r"Could not find file\s+'([^']+?)'", threadData.lastErrorPage[1])9899if match:100retVal = match.group(1).rstrip("%s.mdb" % randStr)101102if retVal.endswith('\\'):103retVal = retVal[:-1]104105return retVal106107def getFingerprint(self):108value = ""109wsOsFp = Format.getOs("web server", kb.headersFp)110111if wsOsFp:112value += "%s\n" % wsOsFp113114if kb.data.banner:115dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)116117if dbmsOsFp:118value += "%s\n" % dbmsOsFp119120value += "back-end DBMS: "121122if not conf.extensiveFp:123value += DBMS.ACCESS124return value125126actVer = Format.getDbms() + " (%s)" % (self._sandBoxCheck())127blank = " " * 15128value += "active fingerprint: %s" % actVer129130if kb.bannerFp:131banVer = kb.bannerFp.get("dbmsVersion")132133if banVer:134if re.search(r"-log$", kb.data.banner or ""):135banVer += ", logging enabled"136137banVer = Format.getDbms([banVer])138value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)139140htmlErrorFp = Format.getErrorParsedDBMSes()141142if htmlErrorFp:143value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)144145value += "\ndatabase directory: '%s'" % self._getDatabaseDir()146147return value148149def checkDbms(self):150if not conf.extensiveFp and Backend.isDbmsWithin(ACCESS_ALIASES):151setDbms(DBMS.ACCESS)152153return True154155infoMsg = "testing %s" % DBMS.ACCESS156logger.info(infoMsg)157158result = inject.checkBooleanExpression("VAL(CVAR(1))=1")159160if result:161infoMsg = "confirming %s" % DBMS.ACCESS162logger.info(infoMsg)163164result = inject.checkBooleanExpression("IIF(ATN(2) IS NOT NULL,1,0) BETWEEN 2 AND 0")165166if not result:167warnMsg = "the back-end DBMS is not %s" % DBMS.ACCESS168logger.warning(warnMsg)169return False170171setDbms(DBMS.ACCESS)172173if not conf.extensiveFp:174return True175176infoMsg = "actively fingerprinting %s" % DBMS.ACCESS177logger.info(infoMsg)178179version = self._sysTablesCheck()180181if version is not None:182Backend.setVersion(version)183184return True185else:186warnMsg = "the back-end DBMS is not %s" % DBMS.ACCESS187logger.warning(warnMsg)188189return False190191def forceDbmsEnum(self):192conf.db = ("%s%s" % (DBMS.ACCESS, METADB_SUFFIX)).replace(' ', '_')193194195