2019-05-08 13:47:52 +03:00
#!/usr/bin/env python
2010-03-23 01:57:57 +03:00
"""
2021-09-08 22:01:41 +03:00
Copyright ( c ) 2006 - 2021 sqlmap developers ( https : / / sqlmap . org / )
2017-10-11 15:50:46 +03:00
See the file ' LICENSE ' for copying permission
2010-03-23 01:57:57 +03:00
"""
2011-01-28 19:36:09 +03:00
from lib . core . common import Backend
from lib . core . common import Format
2020-01-22 01:19:11 +03:00
from lib . core . common import hashDBRetrieve
from lib . core . common import hashDBWrite
2010-03-23 01:57:57 +03:00
from lib . core . data import conf
from lib . core . data import kb
from lib . core . data import logger
2010-11-08 12:20:02 +03:00
from lib . core . enums import DBMS
2020-01-22 01:19:11 +03:00
from lib . core . enums import FORK
from lib . core . enums import HASHDB_KEYS
2011-04-23 20:25:09 +04:00
from lib . core . enums import OS
2010-03-23 01:57:57 +03:00
from lib . core . session import setDbms
from lib . core . settings import PGSQL_ALIASES
from lib . request import inject
from plugins . generic . fingerprint import Fingerprint as GenericFingerprint
class Fingerprint ( GenericFingerprint ) :
def __init__ ( self ) :
2011-01-14 14:55:20 +03:00
GenericFingerprint . __init__ ( self , DBMS . PGSQL )
2010-03-23 01:57:57 +03:00
def getFingerprint ( self ) :
2020-01-22 01:19:11 +03:00
fork = hashDBRetrieve ( HASHDB_KEYS . DBMS_FORK )
if fork is None :
2020-01-31 13:39:16 +03:00
if inject . checkBooleanExpression ( " VERSION() LIKE ' % CockroachDB % ' " ) :
fork = FORK . COCKROACHDB
2020-02-04 00:11:19 +03:00
elif inject . checkBooleanExpression ( " VERSION() LIKE ' % Redshift % ' " ) : # Reference: https://dataedo.com/kb/query/amazon-redshift/check-server-version
2020-01-31 13:39:16 +03:00
fork = FORK . REDSHIFT
2020-02-04 00:11:19 +03:00
elif inject . checkBooleanExpression ( " VERSION() LIKE ' %G reenplum % ' " ) : # Reference: http://www.sqldbpros.com/wordpress/wp-content/uploads/2014/08/what-version-of-greenplum.png
2020-01-31 15:01:15 +03:00
fork = FORK . GREENPLUM
2020-02-25 14:36:07 +03:00
elif inject . checkBooleanExpression ( " VERSION() LIKE ' % Yellowbrick % ' " ) : # Reference: https://www.yellowbrick.com/docs/3.3/ybd_sqlref/version.html
fork = FORK . YELLOWBRICK
2020-02-06 16:17:14 +03:00
elif inject . checkBooleanExpression ( " VERSION() LIKE ' %E nterpriseDB % ' " ) : # 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
fork = FORK . ENTERPRISEDB
2021-01-13 13:47:10 +03:00
elif inject . checkBooleanExpression ( " VERSION() LIKE ' % YB- % ' " ) : # Reference: https://github.com/yugabyte/yugabyte-db/issues/2447#issue-499562926
fork = FORK . YUGABYTEDB
2020-02-04 00:11:19 +03:00
elif inject . checkBooleanExpression ( " AURORA_VERSION() LIKE ' % ' " ) : # Reference: https://aws.amazon.com/premiumsupport/knowledge-center/aurora-version-number/
fork = FORK . AURORA
2020-01-31 13:39:16 +03:00
else :
fork = " "
2020-01-22 01:19:11 +03:00
hashDBWrite ( HASHDB_KEYS . DBMS_FORK , fork )
2011-04-30 17:20:05 +04:00
value = " "
2011-01-28 19:36:09 +03:00
wsOsFp = Format . getOs ( " web server " , kb . headersFp )
2010-03-23 01:57:57 +03:00
if wsOsFp :
value + = " %s \n " % wsOsFp
if kb . data . banner :
2011-01-28 19:36:09 +03:00
dbmsOsFp = Format . getOs ( " back-end DBMS " , kb . bannerFp )
2010-03-23 01:57:57 +03:00
if dbmsOsFp :
value + = " %s \n " % dbmsOsFp
value + = " back-end DBMS: "
if not conf . extensiveFp :
2010-12-04 01:28:09 +03:00
value + = DBMS . PGSQL
2020-01-22 01:19:11 +03:00
if fork :
value + = " ( %s fork) " % fork
2010-03-23 01:57:57 +03:00
return value
2011-04-30 17:20:05 +04:00
actVer = Format . getDbms ( )
blank = " " * 15
value + = " active fingerprint: %s " % actVer
2010-03-23 01:57:57 +03:00
if kb . bannerFp :
2018-08-25 23:57:49 +03:00
banVer = kb . bannerFp . get ( " dbmsVersion " )
2019-05-22 10:43:10 +03:00
if banVer :
banVer = Format . getDbms ( [ banVer ] )
value + = " \n %s banner parsing fingerprint: %s " % ( blank , banVer )
2010-03-23 01:57:57 +03:00
2011-01-28 19:36:09 +03:00
htmlErrorFp = Format . getErrorParsedDBMSes ( )
2010-03-23 01:57:57 +03:00
if htmlErrorFp :
value + = " \n %s html error message fingerprint: %s " % ( blank , htmlErrorFp )
2020-01-22 01:19:11 +03:00
if fork :
value + = " \n %s fork fingerprint: %s " % ( blank , fork )
2010-03-23 01:57:57 +03:00
return value
def checkDbms ( self ) :
"""
References for fingerprint :
2018-05-08 15:06:34 +03:00
* https : / / www . postgresql . org / docs / current / static / release . html
2010-03-23 01:57:57 +03:00
"""
2017-03-06 14:53:04 +03:00
if not conf . extensiveFp and Backend . isDbmsWithin ( PGSQL_ALIASES ) :
2010-12-04 01:28:09 +03:00
setDbms ( DBMS . PGSQL )
2010-03-23 01:57:57 +03:00
self . getBanner ( )
2011-01-14 15:47:07 +03:00
return True
2010-03-23 01:57:57 +03:00
2011-01-20 02:06:15 +03:00
infoMsg = " testing %s " % DBMS . PGSQL
2010-03-31 14:50:47 +04:00
logger . info ( infoMsg )
2020-01-21 13:18:34 +03:00
# NOTE: Vertica works too without the CONVERT_TO()
result = inject . checkBooleanExpression ( " CONVERT_TO( ' [RANDSTR] ' , QUOTE_IDENT(NULL)) IS NULL " )
2010-03-23 01:57:57 +03:00
if result :
2011-01-20 02:06:15 +03:00
infoMsg = " confirming %s " % DBMS . PGSQL
2010-03-23 01:57:57 +03:00
logger . info ( infoMsg )
2013-02-04 18:26:44 +04:00
result = inject . checkBooleanExpression ( " COALESCE([RANDNUM], NULL)=[RANDNUM] " )
2010-03-23 01:57:57 +03:00
if not result :
2011-01-20 02:06:15 +03:00
warnMsg = " the back-end DBMS is not %s " % DBMS . PGSQL
2010-03-23 01:57:57 +03:00
logger . warn ( warnMsg )
return False
2010-12-04 01:28:09 +03:00
setDbms ( DBMS . PGSQL )
2010-03-23 01:57:57 +03:00
self . getBanner ( )
if not conf . extensiveFp :
return True
2011-01-20 02:06:15 +03:00
infoMsg = " actively fingerprinting %s " % DBMS . PGSQL
logger . info ( infoMsg )
2021-05-19 19:20:39 +03:00
if inject . checkBooleanExpression ( " GEN_RANDOM_UUID() IS NOT NULL " ) :
Backend . setVersion ( " >= 13.0 " )
elif inject . checkBooleanExpression ( " SINH(0)=0 " ) :
2020-01-26 01:37:57 +03:00
Backend . setVersion ( " >= 12.0 " )
elif inject . checkBooleanExpression ( " SHA256(NULL) IS NULL " ) :
2019-03-12 16:10:34 +03:00
Backend . setVersion ( " >= 11.0 " )
elif inject . checkBooleanExpression ( " XMLTABLE(NULL) IS NULL " ) :
Backend . setVersionList ( [ " >= 10.0 " , " < 11.0 " ] )
2018-05-08 15:06:34 +03:00
elif inject . checkBooleanExpression ( " SIND(0)=0 " ) :
2018-07-09 13:22:51 +03:00
Backend . setVersionList ( [ " >= 9.6.0 " , " < 10.0 " ] )
2018-05-08 15:06:34 +03:00
elif inject . checkBooleanExpression ( " TO_JSONB(1) IS NOT NULL " ) :
2018-07-09 13:22:51 +03:00
Backend . setVersionList ( [ " >= 9.5.0 " , " < 9.6.0 " ] )
2016-09-19 15:23:51 +03:00
elif inject . checkBooleanExpression ( " JSON_TYPEOF(NULL) IS NULL " ) :
Backend . setVersionList ( [ " >= 9.4.0 " , " < 9.5.0 " ] )
elif inject . checkBooleanExpression ( " ARRAY_REPLACE(NULL,1,1) IS NULL " ) :
Backend . setVersionList ( [ " >= 9.3.0 " , " < 9.4.0 " ] )
elif inject . checkBooleanExpression ( " ROW_TO_JSON(NULL) IS NULL " ) :
Backend . setVersionList ( [ " >= 9.2.0 " , " < 9.3.0 " ] )
elif inject . checkBooleanExpression ( " REVERSE( ' sqlmap ' )= ' pamlqs ' " ) :
Backend . setVersionList ( [ " >= 9.1.0 " , " < 9.2.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " LENGTH(TO_CHAR(1, ' EEEE ' ))>0 " ) :
2012-03-19 15:23:23 +04:00
Backend . setVersionList ( [ " >= 9.0.0 " , " < 9.1.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " 2=(SELECT DIV(6,3)) " ) :
2011-04-12 14:35:33 +04:00
Backend . setVersionList ( [ " >= 8.4.0 " , " < 9.0.0 " ] )
2010-12-31 00:53:34 +03:00
elif inject . checkBooleanExpression ( " EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8 " ) :
2011-04-12 14:35:33 +04:00
Backend . setVersionList ( [ " >= 8.3.0 " , " < 8.4.0 " ] )
2010-12-31 00:53:34 +03:00
elif inject . checkBooleanExpression ( " ISFINITE(TRANSACTION_TIMESTAMP()) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 8.2.0 " , " < 8.3.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " 9=(SELECT GREATEST(5,9,1)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 8.1.0 " , " < 8.2.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " 3=(SELECT WIDTH_BUCKET(5.35,0.024,10.06,5)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 8.0.0 " , " < 8.1.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " ' d ' =(SELECT SUBSTR(MD5( ' sqlmap ' ),1,1)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 7.4.0 " , " < 8.0.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " ' p ' =(SELECT SUBSTR(CURRENT_SCHEMA(),1,1)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 7.3.0 " , " < 7.4.0 " ] )
2010-12-14 00:33:42 +03:00
elif inject . checkBooleanExpression ( " 8=(SELECT BIT_LENGTH(1)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 7.2.0 " , " < 7.3.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " ' a ' =(SELECT SUBSTR(QUOTE_LITERAL( ' a ' ),2,1)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 7.1.0 " , " < 7.2.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " 8=(SELECT POW(2,3)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 7.0.0 " , " < 7.1.0 " ] )
2010-12-14 00:33:42 +03:00
elif inject . checkBooleanExpression ( " ' a ' =(SELECT MAX( ' a ' )) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 6.5.0 " , " < 6.5.3 " ] )
2010-12-31 00:53:34 +03:00
elif inject . checkBooleanExpression ( " VERSION()=VERSION() " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 6.4.0 " , " < 6.5.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " 2=(SELECT SUBSTR(CURRENT_DATE,1,1)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 6.3.0 " , " < 6.4.0 " ] )
2013-06-26 15:53:42 +04:00
elif inject . checkBooleanExpression ( " ' s ' =(SELECT SUBSTRING( ' sqlmap ' ,1,1)) " ) :
2011-01-28 19:36:09 +03:00
Backend . setVersionList ( [ " >= 6.2.0 " , " < 6.3.0 " ] )
2010-03-23 01:57:57 +03:00
else :
2011-01-28 19:36:09 +03:00
Backend . setVersion ( " < 6.2.0 " )
2010-03-23 01:57:57 +03:00
return True
else :
2011-01-20 02:06:15 +03:00
warnMsg = " the back-end DBMS is not %s " % DBMS . PGSQL
2010-03-23 01:57:57 +03:00
logger . warn ( warnMsg )
return False
def checkDbmsOs ( self , detailed = False ) :
2011-04-23 20:25:09 +04:00
if Backend . getOs ( ) :
2010-03-23 01:57:57 +03:00
return
infoMsg = " fingerprinting the back-end DBMS operating system "
logger . info ( infoMsg )
2010-03-27 02:23:25 +03:00
self . createSupportTbl ( self . fileTblName , self . tblField , " character(10000) " )
2010-03-23 01:57:57 +03:00
inject . goStacked ( " INSERT INTO %s ( %s ) VALUES ( %s ) " % ( self . fileTblName , self . tblField , " VERSION() " ) )
# Windows executables should always have ' Visual C++' or ' mingw'
# patterns within the banner
2013-01-09 18:38:41 +04:00
osWindows = ( " Visual C++ " , " mingw " )
2010-03-23 01:57:57 +03:00
for osPattern in osWindows :
2010-12-14 00:33:42 +03:00
query = " (SELECT LENGTH( %s ) FROM %s WHERE %s " % ( self . tblField , self . fileTblName , self . tblField )
2010-03-23 01:57:57 +03:00
query + = " LIKE ' % " + osPattern + " % ' )>0 "
2010-12-14 00:33:42 +03:00
if inject . checkBooleanExpression ( query ) :
2011-04-23 20:25:09 +04:00
Backend . setOs ( OS . WINDOWS )
2010-03-23 01:57:57 +03:00
break
2011-04-23 20:25:09 +04:00
if Backend . getOs ( ) is None :
Backend . setOs ( OS . LINUX )
2010-03-23 01:57:57 +03:00
2011-04-23 20:25:09 +04:00
infoMsg = " the back-end DBMS operating system is %s " % Backend . getOs ( )
2010-03-23 01:57:57 +03:00
logger . info ( infoMsg )
self . cleanup ( onlyFileTbl = True )