Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit aa2682e

Browse files
committed
Fixes #3873
1 parent 94ef433 commit aa2682e

2 files changed

Lines changed: 81 additions & 70 deletions

File tree

lib/core/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from thirdparty.six import unichr as _unichr
1919

2020
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
21-
VERSION = "1.3.8.6"
21+
VERSION = "1.3.8.7"
2222
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2323
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2424
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

lib/utils/brute.py

Lines changed: 80 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def _addPageTextWords():
6060

6161
return wordsList
6262

63+
@stackedmethod
6364
def tableExists(tableFile, regex=None):
6465
if kb.tableExistsChoice is None and not any(_ for _ in kb.injection.data if _ not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)) and not conf.direct:
6566
warnMsg = "it's not recommended to use '%s' and/or '%s' " % (PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.TIME], PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.STACKED])
@@ -74,15 +75,17 @@ def tableExists(tableFile, regex=None):
7475

7576
result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), randomStr())))
7677

77-
if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
78-
conf.db = conf.db.upper()
79-
8078
if result:
8179
errMsg = "can't use table existence check because of detected invalid results "
8280
errMsg += "(most likely caused by inability of the used injection "
8381
errMsg += "to distinguish erroneous results)"
8482
raise SqlmapDataException(errMsg)
8583

84+
pushValue(conf.db)
85+
86+
if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
87+
conf.db = conf.db.upper()
88+
8689
message = "which common tables (wordlist) file do you want to use?\n"
8790
message += "[1] default '%s' (press Enter)\n" % tableFile
8891
message += "[2] custom"
@@ -92,80 +95,88 @@ def tableExists(tableFile, regex=None):
9295
message = "what's the custom common tables file location?\n"
9396
tableFile = readInput(message) or tableFile
9497

95-
infoMsg = "checking table existence using items from '%s'" % tableFile
98+
infoMsg = "performing table existence using items from '%s'" % tableFile
9699
logger.info(infoMsg)
97100

98101
tables = getFileItems(tableFile, lowercase=Backend.getIdentifiedDbms() in (DBMS.ACCESS,), unique=True)
99102
tables.extend(_addPageTextWords())
100103
tables = filterListValue(tables, regex)
101104

102-
threadData = getCurrentThreadData()
103-
threadData.shared.count = 0
104-
threadData.shared.limit = len(tables)
105-
threadData.shared.files = []
106-
threadData.shared.unique = set()
105+
for conf.db in (conf.db.split(',') if conf.db else [conf.db]):
106+
if conf.db:
107+
infoMsg = "checking database '%s'" % conf.db
108+
logger.info(infoMsg)
107109

108-
def tableExistsThread():
109110
threadData = getCurrentThreadData()
110-
111-
while kb.threadContinue:
112-
kb.locks.count.acquire()
113-
if threadData.shared.count < threadData.shared.limit:
114-
table = safeSQLIdentificatorNaming(tables[threadData.shared.count], True)
115-
threadData.shared.count += 1
116-
kb.locks.count.release()
117-
else:
118-
kb.locks.count.release()
119-
break
120-
121-
if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
122-
fullTableName = "%s.%s" % (conf.db, table)
123-
else:
124-
fullTableName = table
125-
126-
result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName)))
127-
128-
kb.locks.io.acquire()
129-
130-
if result and table.lower() not in threadData.shared.unique:
131-
threadData.shared.files.append(table)
132-
threadData.shared.unique.add(table.lower())
133-
134-
if conf.verbose in (1, 2) and not conf.api:
135-
clearConsoleLine(True)
136-
infoMsg = "[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), unsafeSQLIdentificatorNaming(table))
137-
dataToStdout(infoMsg, True)
138-
139-
if conf.verbose in (1, 2):
140-
status = '%d/%d items (%d%%)' % (threadData.shared.count, threadData.shared.limit, round(100.0 * threadData.shared.count / threadData.shared.limit))
141-
dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)
142-
143-
kb.locks.io.release()
144-
145-
try:
146-
runThreads(conf.threads, tableExistsThread, threadChoice=True)
147-
except KeyboardInterrupt:
148-
warnMsg = "user aborted during table existence "
149-
warnMsg += "check. sqlmap will display partial output"
150-
logger.warn(warnMsg)
151-
152-
clearConsoleLine(True)
153-
dataToStdout("\n")
154-
155-
if not threadData.shared.files:
156-
warnMsg = "no table(s) found"
157-
logger.warn(warnMsg)
158-
else:
159-
for item in threadData.shared.files:
160-
if conf.db not in kb.data.cachedTables:
161-
kb.data.cachedTables[conf.db] = [item]
162-
else:
163-
kb.data.cachedTables[conf.db].append(item)
164-
165-
for _ in ((conf.db, item) for item in threadData.shared.files):
166-
if _ not in kb.brute.tables:
167-
kb.brute.tables.append(_)
168-
111+
threadData.shared.count = 0
112+
threadData.shared.limit = len(tables)
113+
threadData.shared.files = []
114+
threadData.shared.unique = set()
115+
116+
def tableExistsThread():
117+
threadData = getCurrentThreadData()
118+
119+
while kb.threadContinue:
120+
kb.locks.count.acquire()
121+
if threadData.shared.count < threadData.shared.limit:
122+
table = safeSQLIdentificatorNaming(tables[threadData.shared.count], True)
123+
threadData.shared.count += 1
124+
kb.locks.count.release()
125+
else:
126+
kb.locks.count.release()
127+
break
128+
129+
if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
130+
fullTableName = "%s.%s" % (conf.db, table)
131+
else:
132+
fullTableName = table
133+
134+
result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName)))
135+
136+
kb.locks.io.acquire()
137+
138+
if result and table.lower() not in threadData.shared.unique:
139+
threadData.shared.files.append(table)
140+
threadData.shared.unique.add(table.lower())
141+
142+
if conf.verbose in (1, 2) and not conf.api:
143+
clearConsoleLine(True)
144+
infoMsg = "[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), unsafeSQLIdentificatorNaming(table))
145+
dataToStdout(infoMsg, True)
146+
147+
if conf.verbose in (1, 2):
148+
status = '%d/%d items (%d%%)' % (threadData.shared.count, threadData.shared.limit, round(100.0 * threadData.shared.count / threadData.shared.limit))
149+
dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)
150+
151+
kb.locks.io.release()
152+
153+
try:
154+
runThreads(conf.threads, tableExistsThread, threadChoice=True)
155+
except KeyboardInterrupt:
156+
warnMsg = "user aborted during table existence "
157+
warnMsg += "check. sqlmap will display partial output"
158+
logger.warn(warnMsg)
159+
160+
clearConsoleLine(True)
161+
dataToStdout("\n")
162+
163+
if not threadData.shared.files:
164+
warnMsg = "no table(s) found"
165+
if conf.db:
166+
warnMsg += "for database '%s'" % conf.db
167+
logger.warn(warnMsg)
168+
else:
169+
for item in threadData.shared.files:
170+
if conf.db not in kb.data.cachedTables:
171+
kb.data.cachedTables[conf.db] = [item]
172+
else:
173+
kb.data.cachedTables[conf.db].append(item)
174+
175+
for _ in ((conf.db, item) for item in threadData.shared.files):
176+
if _ not in kb.brute.tables:
177+
kb.brute.tables.append(_)
178+
179+
conf.db = popValue()
169180
hashDBWrite(HASHDB_KEYS.KB_BRUTE_TABLES, kb.brute.tables, True)
170181

171182
return kb.data.cachedTables

0 commit comments

Comments
 (0)