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

Skip to content

Commit 34d9a91

Browse files
committed
bulk of fixes
1 parent 861cdb1 commit 34d9a91

8 files changed

Lines changed: 142 additions & 148 deletions

File tree

lib/core/common.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2767,3 +2767,18 @@ def __init__(self):
27672767
else:
27682768
errMsg = "mnemonic '%s' requires value of type '%s'" % (name, found.type)
27692769
raise sqlmapSyntaxException, errMsg
2770+
2771+
def safeCSValue(value):
2772+
"""
2773+
Returns value safe for CSV dumping.
2774+
Reference: http://stackoverflow.com/questions/769621/dealing-with-commas-in-a-csv-file
2775+
"""
2776+
2777+
retVal = value
2778+
2779+
if isinstance(retVal, basestring):
2780+
if not (retVal[0] == retVal[-1] == '"'):
2781+
if any(map(lambda x: x in retVal, ['"', ',', '\n'])):
2782+
retVal = '"%s"' % retVal.replace('"', '""')
2783+
2784+
return retVal

lib/core/dump.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from lib.core.common import normalizeUnicode
1919
from lib.core.common import openFile
2020
from lib.core.common import restoreDumpMarkedChars
21+
from lib.core.common import safeCSValue
2122
from lib.core.data import conf
2223
from lib.core.data import kb
2324
from lib.core.data import logger
@@ -392,9 +393,9 @@ def dbTableValues(self, tableValues):
392393

393394
if not conf.replicate:
394395
if not conf.multipleTargets and field == fields:
395-
dataToDumpFile(dumpFP, "%s" % column)
396+
dataToDumpFile(dumpFP, "%s" % safeCSValue(column))
396397
elif not conf.multipleTargets:
397-
dataToDumpFile(dumpFP, "%s," % column)
398+
dataToDumpFile(dumpFP, "%s," % safeCSValue(column))
398399

399400
field += 1
400401

@@ -432,9 +433,9 @@ def dbTableValues(self, tableValues):
432433

433434
if not conf.replicate:
434435
if not conf.multipleTargets and field == fields:
435-
dataToDumpFile(dumpFP, "\"%s\"" % value)
436+
dataToDumpFile(dumpFP, "%s" % safeCSValue(value))
436437
elif not conf.multipleTargets:
437-
dataToDumpFile(dumpFP, "\"%s\"," % value)
438+
dataToDumpFile(dumpFP, "%s," % safeCSValue(value))
438439

439440
field += 1
440441

lib/core/threads.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@
1111
import threading
1212
import time
1313

14+
from thread import error as threadError
15+
1416
from lib.core.data import kb
1517
from lib.core.data import logger
1618
from lib.core.datatype import advancedDict
1719
from lib.core.enums import PAYLOAD
20+
from lib.core.exception import sqlmapConnectionException
1821
from lib.core.exception import sqlmapThreadException
22+
from lib.core.exception import sqlmapValueException
1923
from lib.core.settings import MAX_NUMBER_OF_THREADS
2024
from lib.core.settings import PYVERSION
2125

@@ -68,7 +72,7 @@ def exceptionHandledFunction(threadFunction):
6872
print
6973
logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg))
7074

71-
def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardException=True, threadChoice=False):
75+
def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardException=True, threadChoice=False, startThreadMsg=True):
7276
threads = []
7377

7478
kb.multiThreadMode = True
@@ -92,8 +96,9 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
9296
logger.warn(warnMsg)
9397

9498
if numThreads > 1:
95-
infoMsg = "starting %d threads" % numThreads
96-
logger.info(infoMsg)
99+
if startThreadMsg:
100+
infoMsg = "starting %d threads" % numThreads
101+
logger.info(infoMsg)
97102
else:
98103
threadFunction()
99104
return
@@ -108,7 +113,13 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
108113
else:
109114
thread.setDaemon(True)
110115

111-
thread.start()
116+
try:
117+
thread.start()
118+
except threadError, errMsg:
119+
errMsg = "error occured while starting new thread ('%s')" % errMsg
120+
logger.critical(errMsg)
121+
break
122+
112123
threads.append(thread)
113124

114125
# And wait for them to all finish
@@ -122,11 +133,9 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
122133
time.sleep(1)
123134

124135
except KeyboardInterrupt:
136+
print
125137
kb.threadContinue = False
126138
kb.threadException = True
127-
128-
print '\r',
129-
130139
logger.info("waiting for threads to finish (Ctrl+C was pressed)")
131140

132141
try:
@@ -139,6 +148,20 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
139148
if forwardException:
140149
raise
141150

151+
except (sqlmapConnectionException, sqlmapValueException), errMsg:
152+
print
153+
kb.threadException = True
154+
logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg))
155+
156+
except:
157+
from lib.core.common import unhandledExceptionMessage
158+
159+
print
160+
kb.threadException = True
161+
errMsg = unhandledExceptionMessage()
162+
logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg))
163+
traceback.print_exc()
164+
142165
finally:
143166
kb.multiThreadMode = False
144167
kb.bruteMode = False

lib/techniques/blind/inference.py

Lines changed: 34 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
from lib.core.settings import INFERENCE_EQUALS_CHAR
4545
from lib.core.settings import INFERENCE_NOT_EQUALS_CHAR
4646
from lib.core.settings import PYVERSION
47+
from lib.core.threads import getCurrentThreadData
48+
from lib.core.threads import runThreads
4749
from lib.core.unescaper import unescaper
4850
from lib.request.connect import Connect as Request
4951

@@ -301,26 +303,31 @@ def etaProgressUpdate(charTime, index):
301303

302304
# Go multi-threading (--threads > 1)
303305
if conf.threads > 1 and isinstance(length, int) and length > 1:
304-
value = [ None ] * length
305-
index = [ firstChar ] # As list for python nested function scoping
306-
idxlock = threading.Lock()
307-
iolock = threading.Lock()
308-
valuelock = threading.Lock()
309-
kb.threadContinue = True
310-
311-
def downloadThread():
312-
try:
306+
value = []
307+
threadData = getCurrentThreadData()
308+
309+
threadData.shared.value = [ None ] * length
310+
threadData.shared.index = [ firstChar ] # As list for python nested function scoping
311+
312+
lockNames = ('iolock', 'idxlock', 'valuelock')
313+
for lock in lockNames:
314+
kb.locks[lock] = threading.Lock()
315+
316+
try:
317+
def blindThread():
318+
threadData = getCurrentThreadData()
319+
313320
while kb.threadContinue:
314-
idxlock.acquire()
321+
kb.locks.idxlock.acquire()
315322

316-
if index[0] >= length:
317-
idxlock.release()
323+
if threadData.shared.index[0] >= length:
324+
kb.locks.idxlock.release()
318325

319326
return
320327

321-
index[0] += 1
322-
curidx = index[0]
323-
idxlock.release()
328+
threadData.shared.index[0] += 1
329+
curidx = threadData.shared.index[0]
330+
kb.locks.idxlock.release()
324331

325332
if kb.threadContinue:
326333
charStart = time.time()
@@ -330,14 +337,14 @@ def downloadThread():
330337
else:
331338
break
332339

333-
valuelock.acquire()
334-
value[curidx-1] = val
335-
currentValue = list(value)
336-
valuelock.release()
340+
kb.locks.valuelock.acquire()
341+
threadData.shared.value[curidx-1] = val
342+
currentValue = list(threadData.shared.value)
343+
kb.locks.valuelock.release()
337344

338345
if kb.threadContinue:
339346
if showEta:
340-
etaProgressUpdate(time.time() - charStart, index[0])
347+
etaProgressUpdate(time.time() - charStart, threadData.shared.index[0])
341348
elif conf.verbose >= 1:
342349
startCharIndex = 0
343350
endCharIndex = 0
@@ -370,14 +377,14 @@ def downloadThread():
370377
status = ' %d/%d (%d%s)' % (count, length, round(100.0*count/length), '%')
371378
output += status if count != length else " "*len(status)
372379

373-
iolock.acquire()
380+
kb.locks.iolock.acquire()
374381
dataToStdout("\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), filterControlChars(output)))
375-
iolock.release()
382+
kb.locks.iolock.release()
376383

377384
if not kb.threadContinue:
378385
if int(threading.currentThread().getName()) == numThreads - 1:
379386
partialValue = unicode()
380-
for v in value:
387+
for v in threadData.shared.value:
381388
if v is None:
382389
break
383390
elif isinstance(v, basestring):
@@ -386,57 +393,14 @@ def downloadThread():
386393
if len(partialValue) > 0:
387394
dataToSessionFile(replaceNewlineTabs(partialValue))
388395

389-
except (sqlmapConnectionException, sqlmapValueException), errMsg:
390-
print
391-
kb.threadException = True
392-
logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg))
393-
394-
except KeyboardInterrupt:
395-
kb.threadException = True
396-
397-
print
398-
logger.debug("waiting for threads to finish")
399-
400-
try:
401-
while (threading.activeCount() > 1):
402-
pass
403-
404-
except KeyboardInterrupt:
405-
raise sqlmapThreadException, "user aborted"
406-
407-
except:
408-
print
409-
kb.threadException = True
410-
errMsg = unhandledExceptionMessage()
411-
logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg))
412-
traceback.print_exc()
413-
414-
# Start the threads
415-
for numThread in range(numThreads):
416-
thread = threading.Thread(target=downloadThread, name=str(numThread))
417-
418-
if PYVERSION >= "2.6":
419-
thread.daemon = True
420-
else:
421-
thread.setDaemon(True)
422-
423-
thread.start()
424-
threads.append(thread)
425-
426-
# And wait for them to all finish
427-
try:
428-
alive = True
429-
while alive:
430-
alive = False
431-
for thread in threads:
432-
if thread.isAlive():
433-
alive = True
434-
time.sleep(1)
396+
runThreads(numThreads, blindThread, startThreadMsg=False)
435397

436398
except KeyboardInterrupt:
437-
kb.threadContinue = False
438399
raise
439400

401+
finally:
402+
value = threadData.shared.value
403+
440404
infoMsg = None
441405

442406
# If we have got one single character not correctly fetched it

lib/techniques/error/use.py

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -318,22 +318,22 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
318318

319319
stopLimit = 1
320320

321-
try:
322-
threadData = getCurrentThreadData()
323-
threadData.shared.limits = range(startLimit, stopLimit)
324-
numThreads = min(conf.threads, len(threadData.shared.limits))
325-
threadData.shared.outputs = []
321+
threadData = getCurrentThreadData()
322+
threadData.shared.limits = range(startLimit, stopLimit)
323+
numThreads = min(conf.threads, len(threadData.shared.limits))
324+
threadData.shared.outputs = []
326325

327-
if stopLimit > TURN_OFF_RESUME_INFO_LIMIT:
328-
kb.suppressResumeInfo = True
329-
debugMsg = "suppressing possible resume console info because of "
330-
debugMsg += "large number of rows. It might take too long"
331-
logger.debug(debugMsg)
326+
if stopLimit > TURN_OFF_RESUME_INFO_LIMIT:
327+
kb.suppressResumeInfo = True
328+
debugMsg = "suppressing possible resume console info because of "
329+
debugMsg += "large number of rows. It might take too long"
330+
logger.debug(debugMsg)
332331

333-
lockNames = ('limits', 'outputs')
334-
for lock in lockNames:
335-
kb.locks[lock] = threading.Lock()
332+
lockNames = ('limits', 'outputs')
333+
for lock in lockNames:
334+
kb.locks[lock] = threading.Lock()
336335

336+
try:
337337
def errorThread():
338338
threadData = getCurrentThreadData()
339339

@@ -366,12 +366,6 @@ def errorThread():
366366
warnMsg += "will display partial output"
367367
logger.warn(warnMsg)
368368

369-
except sqlmapConnectionException, e:
370-
errMsg = "connection exception detected. sqlmap "
371-
errMsg += "will display partial output"
372-
errMsg += "'%s'" % e
373-
logger.critical(errMsg)
374-
375369
finally:
376370
outputs = threadData.shared.outputs
377371
kb.suppressResumeInfo = False

lib/techniques/union/use.py

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -259,22 +259,22 @@ def unionUse(expression, unpack=True, dump=False):
259259

260260
stopLimit = 1
261261

262-
try:
263-
threadData = getCurrentThreadData()
264-
threadData.shared.limits = range(startLimit, stopLimit)
265-
numThreads = min(conf.threads, len(threadData.shared.limits))
266-
threadData.shared.value = ""
262+
threadData = getCurrentThreadData()
263+
threadData.shared.limits = range(startLimit, stopLimit)
264+
numThreads = min(conf.threads, len(threadData.shared.limits))
265+
threadData.shared.value = ""
267266

268-
if stopLimit > TURN_OFF_RESUME_INFO_LIMIT:
269-
kb.suppressResumeInfo = True
270-
debugMsg = "suppressing possible resume console info because of "
271-
debugMsg += "large number of rows. It might take too long"
272-
logger.debug(debugMsg)
267+
if stopLimit > TURN_OFF_RESUME_INFO_LIMIT:
268+
kb.suppressResumeInfo = True
269+
debugMsg = "suppressing possible resume console info because of "
270+
debugMsg += "large number of rows. It might take too long"
271+
logger.debug(debugMsg)
273272

274-
lockNames = ('limits', 'value')
275-
for lock in lockNames:
276-
kb.locks[lock] = threading.Lock()
273+
lockNames = ('limits', 'value')
274+
for lock in lockNames:
275+
kb.locks[lock] = threading.Lock()
277276

277+
try:
278278
def unionThread():
279279
threadData = getCurrentThreadData()
280280

@@ -334,12 +334,6 @@ def unionThread():
334334
warnMsg += "will display partial output"
335335
logger.warn(warnMsg)
336336

337-
except sqlmapConnectionException, e:
338-
errMsg = "connection exception detected. sqlmap "
339-
errMsg += "will display partial output"
340-
errMsg += "'%s'" % e
341-
logger.critical(errMsg)
342-
343337
finally:
344338
value = threadData.shared.value
345339
kb.suppressResumeInfo = False

0 commit comments

Comments
 (0)