code refactoring regarding charsetType inside inference/bisection

This commit is contained in:
Miroslav Stampar 2012-02-29 14:36:23 +00:00
parent f6f98f1b41
commit 8b9c5c66cc
10 changed files with 47 additions and 31 deletions

View File

@ -57,6 +57,7 @@ from lib.core.convert import htmlunescape
from lib.core.convert import unicodeencode from lib.core.convert import unicodeencode
from lib.core.convert import urldecode from lib.core.convert import urldecode
from lib.core.convert import urlencode from lib.core.convert import urlencode
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import EXPECTED from lib.core.enums import EXPECTED
from lib.core.enums import HTTPHEADER from lib.core.enums import HTTPHEADER
@ -1312,30 +1313,30 @@ def getCharset(charsetType=None):
asciiTbl.extend(xrange(0, 128)) asciiTbl.extend(xrange(0, 128))
# 0 or 1 # 0 or 1
elif charsetType == 1: elif charsetType == CHARSET_TYPE.BINARY:
asciiTbl.extend([0, 1]) asciiTbl.extend([0, 1])
asciiTbl.extend(xrange(47, 50)) asciiTbl.extend(xrange(47, 50))
# Digits # Digits
elif charsetType == 2: elif charsetType == CHARSET_TYPE.DIGITS:
asciiTbl.extend([0, 1]) asciiTbl.extend([0, 1])
asciiTbl.extend(xrange(47, 58)) asciiTbl.extend(xrange(47, 58))
# Hexadecimal # Hexadecimal
elif charsetType == 3: elif charsetType == CHARSET_TYPE.HEXADECIMAL:
asciiTbl.extend([0, 1]) asciiTbl.extend([0, 1])
asciiTbl.extend(xrange(47, 58)) asciiTbl.extend(xrange(47, 58))
asciiTbl.extend(xrange(64, 71)) asciiTbl.extend(xrange(64, 71))
asciiTbl.extend(xrange(96, 103)) asciiTbl.extend(xrange(96, 103))
# Characters # Characters
elif charsetType == 4: elif charsetType == CHARSET_TYPE.ALPHA:
asciiTbl.extend([0, 1]) asciiTbl.extend([0, 1])
asciiTbl.extend(xrange(64, 91)) asciiTbl.extend(xrange(64, 91))
asciiTbl.extend(xrange(96, 123)) asciiTbl.extend(xrange(96, 123))
# Characters and digits # Characters and digits
elif charsetType == 5: elif charsetType == CHARSET_TYPE.ALPHANUM:
asciiTbl.extend([0, 1]) asciiTbl.extend([0, 1])
asciiTbl.extend(xrange(47, 58)) asciiTbl.extend(xrange(47, 58))
asciiTbl.extend(xrange(64, 91)) asciiTbl.extend(xrange(64, 91))

View File

@ -80,6 +80,13 @@ class REFLECTIVE_COUNTER:
MISS = "MISS" MISS = "MISS"
HIT = "HIT" HIT = "HIT"
class CHARSET_TYPE:
BINARY = 1,
DIGITS = 2,
HEXADECIMAL = 3,
ALPHA = 4,
ALPHANUM = 5
class HASH: class HASH:
MYSQL = r'(?i)\A\*[0-9a-f]{40}\Z' MYSQL = r'(?i)\A\*[0-9a-f]{40}\Z'
MYSQL_OLD = r'(?i)\A(?![0-9]+\Z)[0-9a-f]{16}\Z' MYSQL_OLD = r'(?i)\A(?![0-9]+\Z)[0-9a-f]{16}\Z'

View File

@ -18,6 +18,7 @@ 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.data import queries from lib.core.data import queries
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import OS from lib.core.enums import OS
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
@ -53,7 +54,7 @@ class UDF:
logger.info("checking if UDF '%s' already exist" % udf) logger.info("checking if UDF '%s' already exist" % udf)
query = agent.forgeCaseStatement(queries[Backend.getIdentifiedDbms()].check_udf.query % (udf, udf)) query = agent.forgeCaseStatement(queries[Backend.getIdentifiedDbms()].check_udf.query % (udf, udf))
exists = inject.getValue(query, resumeValue=False, charsetType=2) exists = inject.getValue(query, resumeValue=False, charsetType=CHARSET_TYPE.DIGITS)
if exists == "1": if exists == "1":
return True return True

View File

@ -23,6 +23,7 @@ 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.data import queries from lib.core.data import queries
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.techniques.blind.inference import bisection from lib.techniques.blind.inference import bisection
@ -70,7 +71,7 @@ def queryOutputLength(expression, payload):
start = time.time() start = time.time()
lengthExprUnescaped = unescaper.unescape(lengthExpr) lengthExprUnescaped = unescaper.unescape(lengthExpr)
count, length = bisection(payload, lengthExprUnescaped, charsetType=2) count, length = bisection(payload, lengthExprUnescaped, charsetType=CHARSET_TYPE.DIGITS)
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start)) debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
logger.debug(debugMsg) logger.debug(debugMsg)

View File

@ -21,6 +21,7 @@ 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.data import queries from lib.core.data import queries
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import EXPECTED from lib.core.enums import EXPECTED
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
@ -120,7 +121,7 @@ class Enumeration(GenericEnumeration):
for query in (rootQuery.blind.count, rootQuery.blind.count2, rootQuery.blind.count3): for query in (rootQuery.blind.count, rootQuery.blind.count2, rootQuery.blind.count3):
_ = query.replace("%s", db) _ = query.replace("%s", db)
count = inject.getValue(_, inband=False, error=False, charsetType=2) count = inject.getValue(_, inband=False, error=False, charsetType=CHARSET_TYPE.DIGITS)
if not isNoneValue(count): if not isNoneValue(count):
break break
@ -221,7 +222,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.count query = rootQuery.blind.count
query = query.replace("%s", db) query = query.replace("%s", db)
query += " AND %s" % tblQuery query += " AND %s" % tblQuery
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no table" warnMsg = "no table"
@ -338,7 +339,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.count query = rootQuery.blind.count
query = query % (db, db, db, db, db, db) query = query % (db, db, db, db, db, db)
query += " AND %s" % colQuery.replace("[DB]", db) query += " AND %s" % colQuery.replace("[DB]", db)
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no tables contain column" warnMsg = "no tables contain column"

View File

@ -18,6 +18,7 @@ from lib.core.common import posixToNtSlashes
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import logger from lib.core.data import logger
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
from lib.core.exception import sqlmapUnsupportedFeatureException from lib.core.exception import sqlmapUnsupportedFeatureException
@ -96,7 +97,7 @@ class Filesystem(GenericFilesystem):
if not result: if not result:
result = [] result = []
count = inject.getValue("SELECT COUNT(*) FROM %s" % (hexTbl), resumeValue=False, charsetType=2) count = inject.getValue("SELECT COUNT(*) FROM %s" % (hexTbl), resumeValue=False, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
errMsg = "unable to retrieve the content of the " errMsg = "unable to retrieve the content of the "
@ -106,7 +107,7 @@ class Filesystem(GenericFilesystem):
indexRange = getLimitRange(count) indexRange = getLimitRange(count)
for index in indexRange: for index in indexRange:
chunk = inject.getValue("SELECT TOP 1 %s FROM %s WHERE %s NOT IN (SELECT TOP %d %s FROM %s ORDER BY id ASC) ORDER BY id ASC" % (self.tblField, hexTbl, self.tblField, index, self.tblField, hexTbl), unpack=False, resumeValue=False, unique=False, charsetType=3) chunk = inject.getValue("SELECT TOP 1 %s FROM %s WHERE %s NOT IN (SELECT TOP %d %s FROM %s ORDER BY id ASC) ORDER BY id ASC" % (self.tblField, hexTbl, self.tblField, index, self.tblField, hexTbl), unpack=False, resumeValue=False, unique=False, charsetType=CHARSET_TYPE.HEXADECIMAL)
result.append(chunk) result.append(chunk)
inject.goStacked("DROP TABLE %s" % hexTbl) inject.goStacked("DROP TABLE %s" % hexTbl)

View File

@ -14,6 +14,7 @@ from lib.core.common import unArrayizeValue
from lib.core.data import conf 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.enums import CHARSET_TYPE
from lib.core.enums import PLACE from lib.core.enums import PLACE
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
from lib.request import inject from lib.request import inject
@ -51,7 +52,7 @@ class Filesystem(GenericFilesystem):
logger.debug(debugMsg) logger.debug(debugMsg)
inject.goStacked("LOAD DATA INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' (%s)" % (tmpFile, self.fileTblName, randomStr(10), self.tblField)) inject.goStacked("LOAD DATA INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' (%s)" % (tmpFile, self.fileTblName, randomStr(10), self.tblField))
length = unArrayizeValue(inject.getValue("SELECT LENGTH(%s) FROM %s" % (self.tblField, self.fileTblName), unique=False, resumeValue=False, charsetType=2)) length = unArrayizeValue(inject.getValue("SELECT LENGTH(%s) FROM %s" % (self.tblField, self.fileTblName), unique=False, resumeValue=False, charsetType=CHARSET_TYPE.DIGITS))
if not isNumPosStrValue(length): if not isNumPosStrValue(length):
errMsg = "unable to retrieve the content of the " errMsg = "unable to retrieve the content of the "
@ -65,11 +66,11 @@ class Filesystem(GenericFilesystem):
result = [] result = []
for i in xrange(1, length, sustrLen): for i in xrange(1, length, sustrLen):
chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, sustrLen, self.fileTblName), unpack=False, unique=False, resumeValue=False, charsetType=3) chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, sustrLen, self.fileTblName), unpack=False, unique=False, resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL)
result.append(chunk) result.append(chunk)
else: else:
result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), unique=False, resumeValue=False, charsetType=3) result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), unique=False, resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL)
return result return result

View File

@ -17,6 +17,7 @@ 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.data import queries from lib.core.data import queries
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import EXPECTED from lib.core.enums import EXPECTED
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
@ -119,7 +120,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.count2 % queryUser query = rootQuery.blind.count2 % queryUser
else: else:
query = rootQuery.blind.count % queryUser query = rootQuery.blind.count % queryUser
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
if not count.isdigit() and not query2: if not count.isdigit() and not query2:

View File

@ -45,6 +45,7 @@ from lib.core.dicts import mysqlPrivs
from lib.core.dicts import pgsqlPrivs from lib.core.dicts import pgsqlPrivs
from lib.core.dicts import firebirdPrivs from lib.core.dicts import firebirdPrivs
from lib.core.dicts import db2Privs from lib.core.dicts import db2Privs
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import EXPECTED from lib.core.enums import EXPECTED
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
@ -158,7 +159,7 @@ class Enumeration:
query = queries[Backend.getIdentifiedDbms()].is_dba.query query = queries[Backend.getIdentifiedDbms()].is_dba.query
query = agent.forgeCaseStatement(query) query = agent.forgeCaseStatement(query)
kb.data.isDba = unArrayizeValue(inject.getValue(query, charsetType=1)) kb.data.isDba = unArrayizeValue(inject.getValue(query, charsetType=CHARSET_TYPE.BINARY))
return kb.data.isDba == "1" return kb.data.isDba == "1"
@ -189,7 +190,7 @@ class Enumeration:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
else: else:
query = rootQuery.blind.count query = rootQuery.blind.count
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
errMsg = "unable to retrieve the number of database users" errMsg = "unable to retrieve the number of database users"
@ -329,7 +330,7 @@ class Enumeration:
query = rootQuery.blind.count2 % user query = rootQuery.blind.count2 % user
else: else:
query = rootQuery.blind.count % user query = rootQuery.blind.count % user
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of password " warnMsg = "unable to retrieve the number of password "
@ -563,7 +564,7 @@ class Enumeration:
query = rootQuery.blind.count2 % user query = rootQuery.blind.count2 % user
else: else:
query = rootQuery.blind.count % user query = rootQuery.blind.count % user
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
if Backend.isDbms(DBMS.ORACLE) and not query2: if Backend.isDbms(DBMS.ORACLE) and not query2:
@ -740,7 +741,7 @@ class Enumeration:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
else: else:
query = rootQuery.blind.count query = rootQuery.blind.count
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
errMsg = "unable to retrieve the number of databases" errMsg = "unable to retrieve the number of databases"
@ -903,7 +904,7 @@ class Enumeration:
query = rootQuery.blind.count query = rootQuery.blind.count
else: else:
query = rootQuery.blind.count % unsafeSQLIdentificatorNaming(db) query = rootQuery.blind.count % unsafeSQLIdentificatorNaming(db)
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of " warnMsg = "unable to retrieve the number of "
@ -1194,7 +1195,7 @@ class Enumeration:
parseSqliteTableSchema(value) parseSqliteTableSchema(value)
return kb.data.cachedColumns return kb.data.cachedColumns
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
errMsg = "unable to retrieve the number of columns " errMsg = "unable to retrieve the number of columns "
@ -1313,7 +1314,7 @@ class Enumeration:
else: else:
query = "SELECT %s FROM %s.%s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(db), safeSQLIdentificatorNaming(table, True)) query = "SELECT %s FROM %s.%s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(db), safeSQLIdentificatorNaming(table, True))
count = inject.getValue(query, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if isNumPosStrValue(count): if isNumPosStrValue(count):
if safeSQLIdentificatorNaming(db) not in kb.data.cachedCounts: if safeSQLIdentificatorNaming(db) not in kb.data.cachedCounts:
@ -1662,7 +1663,7 @@ class Enumeration:
query = rootQuery.blind.count % tbl query = rootQuery.blind.count % tbl
else: else:
query = rootQuery.blind.count % (conf.db, tbl) query = rootQuery.blind.count % (conf.db, tbl)
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
lengths = {} lengths = {}
entries = {} entries = {}
@ -1934,7 +1935,7 @@ class Enumeration:
query = rootQuery.blind.count query = rootQuery.blind.count
query += dbQuery query += dbQuery
query += exclDbsQuery query += exclDbsQuery
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no database" warnMsg = "no database"
@ -2052,7 +2053,7 @@ class Enumeration:
query = rootQuery.blind.count query = rootQuery.blind.count
query += tblQuery query += tblQuery
query += whereDbsQuery query += whereDbsQuery
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no databases have table" warnMsg = "no databases have table"
@ -2096,7 +2097,7 @@ class Enumeration:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
query = query % unsafeSQLIdentificatorNaming(db) query = query % unsafeSQLIdentificatorNaming(db)
query += " AND %s" % tblQuery query += " AND %s" % tblQuery
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no table" warnMsg = "no table"
@ -2244,7 +2245,7 @@ class Enumeration:
query = rootQuery.blind.count query = rootQuery.blind.count
query += colQuery query += colQuery
query += whereDbsQuery query += whereDbsQuery
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no databases have tables containing column" warnMsg = "no databases have tables containing column"
@ -2294,7 +2295,7 @@ class Enumeration:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
query = query % db query = query % db
query += " AND %s" % colQuery query += " AND %s" % colQuery
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no tables contain column" warnMsg = "no tables contain column"

View File

@ -19,6 +19,7 @@ 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 conf
from lib.core.data import logger from lib.core.data import logger
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import sqlmapUndefinedMethod from lib.core.exception import sqlmapUndefinedMethod
@ -109,7 +110,7 @@ class Filesystem:
wFileSize = os.path.getsize(wFile) wFileSize = os.path.getsize(wFile)
logger.debug("checking if the %s file has been written" % fileType) logger.debug("checking if the %s file has been written" % fileType)
dFileSize = inject.getValue(lengthQuery, resumeValue=False, charsetType=2) dFileSize = inject.getValue(lengthQuery, resumeValue=False, charsetType=CHARSET_TYPE.DIGITS)
if dFileSize and dFileSize.isdigit(): if dFileSize and dFileSize.isdigit():
infoMsg = "the file has been successfully written and " infoMsg = "the file has been successfully written and "