Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/plugins/dbms/postgresql/fingerprint.py
2992 views
1
#!/usr/bin/env python
2
3
"""
4
Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)
5
See the file 'LICENSE' for copying permission
6
"""
7
8
from lib.core.common import Backend
9
from lib.core.common import Format
10
from lib.core.common import hashDBRetrieve
11
from lib.core.common import hashDBWrite
12
from lib.core.data import conf
13
from lib.core.data import kb
14
from lib.core.data import logger
15
from lib.core.enums import DBMS
16
from lib.core.enums import FORK
17
from lib.core.enums import HASHDB_KEYS
18
from lib.core.enums import OS
19
from lib.core.session import setDbms
20
from lib.core.settings import PGSQL_ALIASES
21
from lib.request import inject
22
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
23
24
class Fingerprint(GenericFingerprint):
25
def __init__(self):
26
GenericFingerprint.__init__(self, DBMS.PGSQL)
27
28
def getFingerprint(self):
29
fork = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)
30
31
if fork is None:
32
if inject.checkBooleanExpression("VERSION() LIKE '%CockroachDB%'"):
33
fork = FORK.COCKROACHDB
34
elif inject.checkBooleanExpression("VERSION() LIKE '%Redshift%'"): # Reference: https://dataedo.com/kb/query/amazon-redshift/check-server-version
35
fork = FORK.REDSHIFT
36
elif inject.checkBooleanExpression("VERSION() LIKE '%Greenplum%'"): # Reference: http://www.sqldbpros.com/wordpress/wp-content/uploads/2014/08/what-version-of-greenplum.png
37
fork = FORK.GREENPLUM
38
elif inject.checkBooleanExpression("VERSION() LIKE '%Yellowbrick%'"): # Reference: https://www.yellowbrick.com/docs/3.3/ybd_sqlref/version.html
39
fork = FORK.YELLOWBRICK
40
elif 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.html
41
fork = FORK.ENTERPRISEDB
42
elif inject.checkBooleanExpression("VERSION() LIKE '%YB-%'"): # Reference: https://github.com/yugabyte/yugabyte-db/issues/2447#issue-499562926
43
fork = FORK.YUGABYTEDB
44
elif inject.checkBooleanExpression("VERSION() LIKE '%openGauss%'"):
45
fork = FORK.OPENGAUSS
46
elif inject.checkBooleanExpression("AURORA_VERSION() LIKE '%'"): # Reference: https://aws.amazon.com/premiumsupport/knowledge-center/aurora-version-number/
47
fork = FORK.AURORA
48
else:
49
fork = ""
50
51
hashDBWrite(HASHDB_KEYS.DBMS_FORK, fork)
52
53
value = ""
54
wsOsFp = Format.getOs("web server", kb.headersFp)
55
56
if wsOsFp:
57
value += "%s\n" % wsOsFp
58
59
if kb.data.banner:
60
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
61
62
if dbmsOsFp:
63
value += "%s\n" % dbmsOsFp
64
65
value += "back-end DBMS: "
66
67
if not conf.extensiveFp:
68
value += DBMS.PGSQL
69
if fork:
70
value += " (%s fork)" % fork
71
return value
72
73
actVer = Format.getDbms()
74
blank = " " * 15
75
value += "active fingerprint: %s" % actVer
76
77
if kb.bannerFp:
78
banVer = kb.bannerFp.get("dbmsVersion")
79
80
if banVer:
81
banVer = Format.getDbms([banVer])
82
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
83
84
htmlErrorFp = Format.getErrorParsedDBMSes()
85
86
if htmlErrorFp:
87
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
88
89
if fork:
90
value += "\n%sfork fingerprint: %s" % (blank, fork)
91
92
return value
93
94
def checkDbms(self):
95
"""
96
References for fingerprint:
97
98
* https://www.postgresql.org/docs/current/static/release.html
99
"""
100
101
if not conf.extensiveFp and Backend.isDbmsWithin(PGSQL_ALIASES):
102
setDbms(DBMS.PGSQL)
103
104
self.getBanner()
105
106
return True
107
108
infoMsg = "testing %s" % DBMS.PGSQL
109
logger.info(infoMsg)
110
111
# NOTE: Vertica works too without the CONVERT_TO()
112
result = inject.checkBooleanExpression("CONVERT_TO('[RANDSTR]', QUOTE_IDENT(NULL)) IS NULL")
113
114
if result:
115
infoMsg = "confirming %s" % DBMS.PGSQL
116
logger.info(infoMsg)
117
118
result = inject.checkBooleanExpression("COALESCE([RANDNUM], NULL)=[RANDNUM]")
119
120
if not result:
121
warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL
122
logger.warning(warnMsg)
123
124
return False
125
126
setDbms(DBMS.PGSQL)
127
128
self.getBanner()
129
130
if not conf.extensiveFp:
131
return True
132
133
infoMsg = "actively fingerprinting %s" % DBMS.PGSQL
134
logger.info(infoMsg)
135
136
if inject.checkBooleanExpression("JSON_QUERY(NULL::jsonb, '$') IS NULL"):
137
Backend.setVersion(">= 17.0")
138
elif inject.checkBooleanExpression("RANDOM_NORMAL(0.0, 1.0) IS NOT NULL"):
139
Backend.setVersion(">= 16.0")
140
elif inject.checkBooleanExpression("REGEXP_COUNT(NULL,NULL) IS NULL"):
141
Backend.setVersion(">= 15.0")
142
elif inject.checkBooleanExpression("BIT_COUNT(NULL) IS NULL"):
143
Backend.setVersion(">= 14.0")
144
elif inject.checkBooleanExpression("GEN_RANDOM_UUID() IS NOT NULL"):
145
Backend.setVersion(">= 13.0")
146
elif inject.checkBooleanExpression("SINH(0)=0"):
147
Backend.setVersion(">= 12.0")
148
elif inject.checkBooleanExpression("SHA256(NULL) IS NULL"):
149
Backend.setVersion(">= 11.0")
150
elif inject.checkBooleanExpression("XMLTABLE(NULL) IS NULL"):
151
Backend.setVersionList([">= 10.0", "< 11.0"])
152
elif inject.checkBooleanExpression("SIND(0)=0"):
153
Backend.setVersionList([">= 9.6.0", "< 10.0"])
154
elif inject.checkBooleanExpression("TO_JSONB(1) IS NOT NULL"):
155
Backend.setVersionList([">= 9.5.0", "< 9.6.0"])
156
elif inject.checkBooleanExpression("JSON_TYPEOF(NULL) IS NULL"):
157
Backend.setVersionList([">= 9.4.0", "< 9.5.0"])
158
elif inject.checkBooleanExpression("ARRAY_REPLACE(NULL,1,1) IS NULL"):
159
Backend.setVersionList([">= 9.3.0", "< 9.4.0"])
160
elif inject.checkBooleanExpression("ROW_TO_JSON(NULL) IS NULL"):
161
Backend.setVersionList([">= 9.2.0", "< 9.3.0"])
162
elif inject.checkBooleanExpression("REVERSE('sqlmap')='pamlqs'"):
163
Backend.setVersionList([">= 9.1.0", "< 9.2.0"])
164
elif inject.checkBooleanExpression("LENGTH(TO_CHAR(1,'EEEE'))>0"):
165
Backend.setVersionList([">= 9.0.0", "< 9.1.0"])
166
elif inject.checkBooleanExpression("2=(SELECT DIV(6,3))"):
167
Backend.setVersionList([">= 8.4.0", "< 9.0.0"])
168
elif inject.checkBooleanExpression("EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"):
169
Backend.setVersionList([">= 8.3.0", "< 8.4.0"])
170
elif inject.checkBooleanExpression("ISFINITE(TRANSACTION_TIMESTAMP())"):
171
Backend.setVersionList([">= 8.2.0", "< 8.3.0"])
172
elif inject.checkBooleanExpression("9=(SELECT GREATEST(5,9,1))"):
173
Backend.setVersionList([">= 8.1.0", "< 8.2.0"])
174
elif inject.checkBooleanExpression("3=(SELECT WIDTH_BUCKET(5.35,0.024,10.06,5))"):
175
Backend.setVersionList([">= 8.0.0", "< 8.1.0"])
176
elif inject.checkBooleanExpression("'d'=(SELECT SUBSTR(MD5('sqlmap'),1,1))"):
177
Backend.setVersionList([">= 7.4.0", "< 8.0.0"])
178
elif inject.checkBooleanExpression("'p'=(SELECT SUBSTR(CURRENT_SCHEMA(),1,1))"):
179
Backend.setVersionList([">= 7.3.0", "< 7.4.0"])
180
elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"):
181
Backend.setVersionList([">= 7.2.0", "< 7.3.0"])
182
elif inject.checkBooleanExpression("'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'),2,1))"):
183
Backend.setVersionList([">= 7.1.0", "< 7.2.0"])
184
elif inject.checkBooleanExpression("8=(SELECT POW(2,3))"):
185
Backend.setVersionList([">= 7.0.0", "< 7.1.0"])
186
elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"):
187
Backend.setVersionList([">= 6.5.0", "< 6.5.3"])
188
elif inject.checkBooleanExpression("VERSION()=VERSION()"):
189
Backend.setVersionList([">= 6.4.0", "< 6.5.0"])
190
elif inject.checkBooleanExpression("2=(SELECT SUBSTR(CURRENT_DATE,1,1))"):
191
Backend.setVersionList([">= 6.3.0", "< 6.4.0"])
192
elif inject.checkBooleanExpression("'s'=(SELECT SUBSTRING('sqlmap',1,1))"):
193
Backend.setVersionList([">= 6.2.0", "< 6.3.0"])
194
else:
195
Backend.setVersion("< 6.2.0")
196
197
return True
198
else:
199
warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL
200
logger.warning(warnMsg)
201
202
return False
203
204
def checkDbmsOs(self, detailed=False):
205
if Backend.getOs():
206
return
207
208
infoMsg = "fingerprinting the back-end DBMS operating system"
209
logger.info(infoMsg)
210
211
self.createSupportTbl(self.fileTblName, self.tblField, "character(10000)")
212
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
213
214
# Windows executables should always have ' Visual C++' or ' mingw'
215
# patterns within the banner
216
osWindows = (" Visual C++", "mingw")
217
218
for osPattern in osWindows:
219
query = "(SELECT LENGTH(%s) FROM %s WHERE %s " % (self.tblField, self.fileTblName, self.tblField)
220
query += "LIKE '%" + osPattern + "%')>0"
221
222
if inject.checkBooleanExpression(query):
223
Backend.setOs(OS.WINDOWS)
224
225
break
226
227
if Backend.getOs() is None:
228
Backend.setOs(OS.LINUX)
229
230
infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()
231
logger.info(infoMsg)
232
233
self.cleanup(onlyFileTbl=True)
234
235