Path: blob/master/plugins/dbms/postgresql/fingerprint.py
2992 views
#!/usr/bin/env python12"""3Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)4See the file 'LICENSE' for copying permission5"""67from lib.core.common import Backend8from lib.core.common import Format9from lib.core.common import hashDBRetrieve10from lib.core.common import hashDBWrite11from lib.core.data import conf12from lib.core.data import kb13from lib.core.data import logger14from lib.core.enums import DBMS15from lib.core.enums import FORK16from lib.core.enums import HASHDB_KEYS17from lib.core.enums import OS18from lib.core.session import setDbms19from lib.core.settings import PGSQL_ALIASES20from lib.request import inject21from plugins.generic.fingerprint import Fingerprint as GenericFingerprint2223class Fingerprint(GenericFingerprint):24def __init__(self):25GenericFingerprint.__init__(self, DBMS.PGSQL)2627def getFingerprint(self):28fork = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)2930if fork is None:31if inject.checkBooleanExpression("VERSION() LIKE '%CockroachDB%'"):32fork = FORK.COCKROACHDB33elif inject.checkBooleanExpression("VERSION() LIKE '%Redshift%'"): # Reference: https://dataedo.com/kb/query/amazon-redshift/check-server-version34fork = FORK.REDSHIFT35elif inject.checkBooleanExpression("VERSION() LIKE '%Greenplum%'"): # Reference: http://www.sqldbpros.com/wordpress/wp-content/uploads/2014/08/what-version-of-greenplum.png36fork = FORK.GREENPLUM37elif inject.checkBooleanExpression("VERSION() LIKE '%Yellowbrick%'"): # Reference: https://www.yellowbrick.com/docs/3.3/ybd_sqlref/version.html38fork = FORK.YELLOWBRICK39elif inject.checkBooleanExpression("VERSION() LIKE '%EnterpriseDB%'"): # Reference: https://www.enterprisedb.com/edb-docs/d/edb-postgres-advanced-server/user-guides/user-guide/11/EDB_Postgres_Advanced_Server_Guide.1.087.html40fork = FORK.ENTERPRISEDB41elif inject.checkBooleanExpression("VERSION() LIKE '%YB-%'"): # Reference: https://github.com/yugabyte/yugabyte-db/issues/2447#issue-49956292642fork = FORK.YUGABYTEDB43elif inject.checkBooleanExpression("VERSION() LIKE '%openGauss%'"):44fork = FORK.OPENGAUSS45elif inject.checkBooleanExpression("AURORA_VERSION() LIKE '%'"): # Reference: https://aws.amazon.com/premiumsupport/knowledge-center/aurora-version-number/46fork = FORK.AURORA47else:48fork = ""4950hashDBWrite(HASHDB_KEYS.DBMS_FORK, fork)5152value = ""53wsOsFp = Format.getOs("web server", kb.headersFp)5455if wsOsFp:56value += "%s\n" % wsOsFp5758if kb.data.banner:59dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)6061if dbmsOsFp:62value += "%s\n" % dbmsOsFp6364value += "back-end DBMS: "6566if not conf.extensiveFp:67value += DBMS.PGSQL68if fork:69value += " (%s fork)" % fork70return value7172actVer = Format.getDbms()73blank = " " * 1574value += "active fingerprint: %s" % actVer7576if kb.bannerFp:77banVer = kb.bannerFp.get("dbmsVersion")7879if banVer:80banVer = Format.getDbms([banVer])81value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)8283htmlErrorFp = Format.getErrorParsedDBMSes()8485if htmlErrorFp:86value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)8788if fork:89value += "\n%sfork fingerprint: %s" % (blank, fork)9091return value9293def checkDbms(self):94"""95References for fingerprint:9697* https://www.postgresql.org/docs/current/static/release.html98"""99100if not conf.extensiveFp and Backend.isDbmsWithin(PGSQL_ALIASES):101setDbms(DBMS.PGSQL)102103self.getBanner()104105return True106107infoMsg = "testing %s" % DBMS.PGSQL108logger.info(infoMsg)109110# NOTE: Vertica works too without the CONVERT_TO()111result = inject.checkBooleanExpression("CONVERT_TO('[RANDSTR]', QUOTE_IDENT(NULL)) IS NULL")112113if result:114infoMsg = "confirming %s" % DBMS.PGSQL115logger.info(infoMsg)116117result = inject.checkBooleanExpression("COALESCE([RANDNUM], NULL)=[RANDNUM]")118119if not result:120warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL121logger.warning(warnMsg)122123return False124125setDbms(DBMS.PGSQL)126127self.getBanner()128129if not conf.extensiveFp:130return True131132infoMsg = "actively fingerprinting %s" % DBMS.PGSQL133logger.info(infoMsg)134135if inject.checkBooleanExpression("JSON_QUERY(NULL::jsonb, '$') IS NULL"):136Backend.setVersion(">= 17.0")137elif inject.checkBooleanExpression("RANDOM_NORMAL(0.0, 1.0) IS NOT NULL"):138Backend.setVersion(">= 16.0")139elif inject.checkBooleanExpression("REGEXP_COUNT(NULL,NULL) IS NULL"):140Backend.setVersion(">= 15.0")141elif inject.checkBooleanExpression("BIT_COUNT(NULL) IS NULL"):142Backend.setVersion(">= 14.0")143elif inject.checkBooleanExpression("GEN_RANDOM_UUID() IS NOT NULL"):144Backend.setVersion(">= 13.0")145elif inject.checkBooleanExpression("SINH(0)=0"):146Backend.setVersion(">= 12.0")147elif inject.checkBooleanExpression("SHA256(NULL) IS NULL"):148Backend.setVersion(">= 11.0")149elif inject.checkBooleanExpression("XMLTABLE(NULL) IS NULL"):150Backend.setVersionList([">= 10.0", "< 11.0"])151elif inject.checkBooleanExpression("SIND(0)=0"):152Backend.setVersionList([">= 9.6.0", "< 10.0"])153elif inject.checkBooleanExpression("TO_JSONB(1) IS NOT NULL"):154Backend.setVersionList([">= 9.5.0", "< 9.6.0"])155elif inject.checkBooleanExpression("JSON_TYPEOF(NULL) IS NULL"):156Backend.setVersionList([">= 9.4.0", "< 9.5.0"])157elif inject.checkBooleanExpression("ARRAY_REPLACE(NULL,1,1) IS NULL"):158Backend.setVersionList([">= 9.3.0", "< 9.4.0"])159elif inject.checkBooleanExpression("ROW_TO_JSON(NULL) IS NULL"):160Backend.setVersionList([">= 9.2.0", "< 9.3.0"])161elif inject.checkBooleanExpression("REVERSE('sqlmap')='pamlqs'"):162Backend.setVersionList([">= 9.1.0", "< 9.2.0"])163elif inject.checkBooleanExpression("LENGTH(TO_CHAR(1,'EEEE'))>0"):164Backend.setVersionList([">= 9.0.0", "< 9.1.0"])165elif inject.checkBooleanExpression("2=(SELECT DIV(6,3))"):166Backend.setVersionList([">= 8.4.0", "< 9.0.0"])167elif inject.checkBooleanExpression("EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"):168Backend.setVersionList([">= 8.3.0", "< 8.4.0"])169elif inject.checkBooleanExpression("ISFINITE(TRANSACTION_TIMESTAMP())"):170Backend.setVersionList([">= 8.2.0", "< 8.3.0"])171elif inject.checkBooleanExpression("9=(SELECT GREATEST(5,9,1))"):172Backend.setVersionList([">= 8.1.0", "< 8.2.0"])173elif inject.checkBooleanExpression("3=(SELECT WIDTH_BUCKET(5.35,0.024,10.06,5))"):174Backend.setVersionList([">= 8.0.0", "< 8.1.0"])175elif inject.checkBooleanExpression("'d'=(SELECT SUBSTR(MD5('sqlmap'),1,1))"):176Backend.setVersionList([">= 7.4.0", "< 8.0.0"])177elif inject.checkBooleanExpression("'p'=(SELECT SUBSTR(CURRENT_SCHEMA(),1,1))"):178Backend.setVersionList([">= 7.3.0", "< 7.4.0"])179elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"):180Backend.setVersionList([">= 7.2.0", "< 7.3.0"])181elif inject.checkBooleanExpression("'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'),2,1))"):182Backend.setVersionList([">= 7.1.0", "< 7.2.0"])183elif inject.checkBooleanExpression("8=(SELECT POW(2,3))"):184Backend.setVersionList([">= 7.0.0", "< 7.1.0"])185elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"):186Backend.setVersionList([">= 6.5.0", "< 6.5.3"])187elif inject.checkBooleanExpression("VERSION()=VERSION()"):188Backend.setVersionList([">= 6.4.0", "< 6.5.0"])189elif inject.checkBooleanExpression("2=(SELECT SUBSTR(CURRENT_DATE,1,1))"):190Backend.setVersionList([">= 6.3.0", "< 6.4.0"])191elif inject.checkBooleanExpression("'s'=(SELECT SUBSTRING('sqlmap',1,1))"):192Backend.setVersionList([">= 6.2.0", "< 6.3.0"])193else:194Backend.setVersion("< 6.2.0")195196return True197else:198warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL199logger.warning(warnMsg)200201return False202203def checkDbmsOs(self, detailed=False):204if Backend.getOs():205return206207infoMsg = "fingerprinting the back-end DBMS operating system"208logger.info(infoMsg)209210self.createSupportTbl(self.fileTblName, self.tblField, "character(10000)")211inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))212213# Windows executables should always have ' Visual C++' or ' mingw'214# patterns within the banner215osWindows = (" Visual C++", "mingw")216217for osPattern in osWindows:218query = "(SELECT LENGTH(%s) FROM %s WHERE %s " % (self.tblField, self.fileTblName, self.tblField)219query += "LIKE '%" + osPattern + "%')>0"220221if inject.checkBooleanExpression(query):222Backend.setOs(OS.WINDOWS)223224break225226if Backend.getOs() is None:227Backend.setOs(OS.LINUX)228229infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()230logger.info(infoMsg)231232self.cleanup(onlyFileTbl=True)233234235