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

Skip to content

Commit 089c16a

Browse files
committed
Added tag <epayload> to the payloads.xml's <test> tag to define which payload to use when exploiting the test type.
Removed some useless tests. Moved <error> from queries.xml to payloads.xml as it makes more sense. Beeps at sql inj found only if --beep is provided. Minor fix in order to be able to pickle advancedDict() objects. Minor code refactoring. Removed useless folders.
1 parent c00ea7f commit 089c16a

11 files changed

Lines changed: 187 additions & 288 deletions

File tree

lib/controller/checks.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from lib.core.enums import HTTPMETHOD
3434
from lib.core.enums import NULLCONNECTION
3535
from lib.core.enums import PAYLOAD
36+
from lib.core.enums import PLACE
3637
from lib.core.exception import sqlmapConnectionException
3738
from lib.core.exception import sqlmapGenericException
3839
from lib.core.exception import sqlmapNoneDataException
@@ -331,14 +332,28 @@ def checkSqlInjection(place, parameter, value):
331332
# Feed with the boundaries details only the first time a
332333
# test has been successful
333334
if injection.place is None or injection.parameter is None:
335+
if place == PLACE.UA:
336+
injection.parameter = conf.agent
337+
else:
338+
injection.parameter = parameter
339+
334340
injection.place = place
335-
injection.parameter = parameter
336341
injection.ptype = ptype
337342
injection.prefix = prefix
338343
injection.suffix = suffix
339344

345+
if "epayload" in test:
346+
epayload = "%s%s" % (test.epayload, comment)
347+
else:
348+
epayload = None
349+
340350
# Feed with test details every time a test is successful
341-
injection.data[stype] = (title, agent.removePayloadDelimiters(reqPayload, False), where, comment)
351+
injection.data[stype] = advancedDict()
352+
injection.data[stype].title = title
353+
injection.data[stype].payload = agent.removePayloadDelimiters(reqPayload, False)
354+
injection.data[stype].where = where
355+
injection.data[stype].epayload = epayload
356+
injection.data[stype].comment = comment
342357

343358
if "details" in test:
344359
for detailKey, detailValue in test.details.items():
@@ -351,7 +366,8 @@ def checkSqlInjection(place, parameter, value):
351366
elif detailKey == "os" and injection.os is None:
352367
injection.os = detailValue
353368

354-
beep()
369+
if conf.beep:
370+
beep()
355371

356372
# There is no need to perform this test for other
357373
# <where> tags
@@ -703,7 +719,6 @@ def checkConnection(suppressOutput=False):
703719
try:
704720
page, _ = Request.queryPage(content=True)
705721
conf.seqMatcher.set_seq1(page)
706-
707722
except sqlmapConnectionException, errMsg:
708723
errMsg = getUnicode(errMsg)
709724
raise sqlmapConnectionException, errMsg

lib/controller/controller.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,9 @@ def __formatInjection(inj):
107107
data += "Parameter: %s\n" % inj.parameter
108108

109109
for stype, sdata in inj.data.items():
110-
stype = PAYLOAD.SQLINJECTION[stype] if isinstance(stype, int) else stype
111110
data += " Type: %s\n" % stype
112-
data += " Title: %s\n" % sdata[0]
113-
data += " Payload: %s\n\n" % sdata[1]
111+
data += " Title: %s\n" % sdata.title
112+
data += " Payload: %s\n\n" % sdata.payload
114113

115114
return data
116115

@@ -136,7 +135,7 @@ def __saveToSessionFile():
136135
parameter = inj.parameter
137136

138137
for stype, sdata in inj.data.items():
139-
payload = sdata[1]
138+
payload = sdata.payload
140139

141140
if stype == 1:
142141
kb.booleanTest = payload
@@ -303,7 +302,8 @@ def start():
303302
# TODO: consider the following line in __setRequestParams()
304303
__testableParameters = True
305304

306-
if not kb.injection.place or not kb.injection.parameter:
305+
if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \
306+
and (kb.injection.place is None or kb.injection.parameter is None):
307307
if not conf.string and not conf.regexp and not conf.eRegexp:
308308
# NOTE: this is not needed anymore, leaving only to display
309309
# a warning message to the user in case the page is not stable
@@ -394,7 +394,7 @@ def start():
394394
__showInjections()
395395
__selectInjection()
396396

397-
if kb.injection.place and kb.injection.parameter:
397+
if kb.injection.place is not None and kb.injection.parameter is not None:
398398
if conf.multipleTargets:
399399
message = "do you want to exploit this SQL injection? [Y/n] "
400400
exploit = readInput(message, default="Y")

lib/core/agent.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ def suffixQuery(self, string, comment=None):
158158
return string
159159

160160
def cleanupPayload(self, payload):
161+
if payload is None:
162+
return
163+
161164
randInt = randomInt()
162165
randInt1 = randomInt()
163166
randStr = randomStr()

lib/core/datatype.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def __getattr__(self, item):
3737
try:
3838
return self.__getitem__(item)
3939
except KeyError:
40-
raise sqlmapDataException, "Unable to access item '%s'" % item
40+
raise sqlmapDataException, "unable to access item '%s'" % item
4141

4242
def __setattr__(self, item, value):
4343
"""
@@ -56,6 +56,12 @@ def __setattr__(self, item, value):
5656
else:
5757
self.__setitem__(item, value)
5858

59+
def __getstate__(self):
60+
return self.__dict__
61+
62+
def __setstate__(self, dict):
63+
self.__dict__ = dict
64+
5965
def injectionDict():
6066
injection = advancedDict()
6167

lib/core/session.py

Lines changed: 9 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from lib.core.common import dataToSessionFile
1313
from lib.core.common import formatFingerprintString
1414
from lib.core.common import readInput
15+
from lib.core.convert import base64pickle
16+
from lib.core.convert import base64unpickle
1517
from lib.core.data import conf
1618
from lib.core.data import kb
1719
from lib.core.data import logger
@@ -78,30 +80,15 @@ def setInjection(inj):
7880
session file.
7981
"""
8082

81-
if inj.place == PLACE.UA:
82-
inj.parameter = conf.agent
83-
8483
condition = (
8584
( not kb.resumedQueries
8685
or ( kb.resumedQueries.has_key(conf.url) and
87-
( not kb.resumedQueries[conf.url].has_key("Injection point")
88-
or not kb.resumedQueries[conf.url].has_key("Injection parameter")
89-
) ) )
86+
not kb.resumedQueries[conf.url].has_key("Injection data")
87+
) )
9088
)
9189

9290
if condition:
93-
dataToSessionFile("[%s][%s][%s][Injection point][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.place))
94-
dataToSessionFile("[%s][%s][%s][Injection parameter][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.parameter))
95-
dataToSessionFile("[%s][%s][%s][Injection parameter type][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), PAYLOAD.PARAMETER[inj.ptype]))
96-
dataToSessionFile("[%s][%s][%s][Injection prefix][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.prefix))
97-
dataToSessionFile("[%s][%s][%s][Injection suffix][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.suffix))
98-
99-
for stype, sdata in inj.data.items():
100-
dataToSessionFile("[%s][%s][%s][Injection type][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), PAYLOAD.SQLINJECTION[stype]))
101-
dataToSessionFile("[%s][%s][%s][Injection title][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[0]))
102-
dataToSessionFile("[%s][%s][%s][Injection payload][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[1]))
103-
dataToSessionFile("[%s][%s][%s][Injection where][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[2]))
104-
dataToSessionFile("[%s][%s][%s][Injection comment][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[3]))
91+
dataToSessionFile("[%s][%s][%s][Injection data][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), base64pickle(inj)))
10592

10693
def setDbms(dbms):
10794
"""
@@ -370,96 +357,11 @@ def resumeConfKb(expression, url, value):
370357
except ValueError:
371358
pass
372359

373-
elif expression == "Injection point" and url == conf.url:
374-
injPlace = value[:-1]
375-
376-
logMsg = "resuming injection point '%s' from session file" % injPlace
377-
logger.info(logMsg)
378-
379-
if not conf.paramDict.has_key(injPlace):
380-
warnMsg = "none of the parameters you provided "
381-
warnMsg += "matches the resumable injection point. "
382-
warnMsg += "sqlmap is going to reidentify the "
383-
warnMsg += "injectable point"
384-
logger.warn(warnMsg)
385-
else:
386-
if kb.injection.place is not None and kb.injection.parameter is not None:
387-
kb.injections.append(kb.injection)
388-
kb.injection = injectionDict()
389-
390-
kb.injection.place = injPlace
391-
392-
elif expression == "Injection parameter" and url == conf.url:
393-
injParameter = unSafeFormatString(value[:-1])
394-
395-
logMsg = "resuming injection parameter '%s' from session file" % injParameter
396-
logger.info(logMsg)
397-
398-
condition = (
399-
not conf.paramDict.has_key(kb.injection.place) or
400-
not conf.paramDict[kb.injection.place].has_key(injParameter)
401-
)
402-
403-
if condition:
404-
warnMsg = "none of the parameters you provided "
405-
warnMsg += "matches the resumable injection parameter. "
406-
warnMsg += "sqlmap is going to reidentify the "
407-
warnMsg += "injectable point"
408-
logger.warn(warnMsg)
409-
else:
410-
kb.injection.parameter = injParameter
411-
412-
elif expression == "Injection parameter type" and url == conf.url:
413-
kb.injection.ptype = unSafeFormatString(value[:-1])
414-
415-
logMsg = "resuming injection parameter type '%s' from session file" % kb.injection.ptype
416-
logger.info(logMsg)
417-
418-
elif expression == "Injection prefix" and url == conf.url:
419-
kb.injection.prefix = unSafeFormatString(value[:-1])
420-
421-
logMsg = "resuming injection prefix '%s' from session file" % kb.injection.prefix
422-
logger.info(logMsg)
423-
424-
elif expression == "Injection suffix" and url == conf.url:
425-
kb.injection.suffix = unSafeFormatString(value[:-1])
426-
427-
logMsg = "resuming injection suffix '%s' from session file" % kb.injection.suffix
428-
logger.info(logMsg)
429-
430-
elif expression == "Injection type" and url == conf.url:
431-
stype = unSafeFormatString(value[:-1])
432-
kb.injection.data[stype] = []
433-
434-
logMsg = "resuming injection type '%s' from session file" % stype
435-
logger.info(logMsg)
436-
437-
elif expression == "Injection title" and url == conf.url:
438-
title = unSafeFormatString(value[:-1])
439-
kb.injection.data[kb.injection.data.keys()[0]].append(title)
440-
441-
logMsg = "resuming injection title '%s' from session file" % title
442-
logger.info(logMsg)
443-
444-
elif expression == "Injection payload" and url == conf.url:
445-
payload = unSafeFormatString(value[:-1])
446-
kb.injection.data[kb.injection.data.keys()[0]].append(payload)
447-
448-
logMsg = "resuming injection payload '%s' from session file" % payload
449-
logger.info(logMsg)
450-
451-
elif expression == "Injection where" and url == conf.url:
452-
where = unSafeFormatString(value[:-1])
453-
kb.injection.data[kb.injection.data.keys()[0]].append(where)
454-
455-
logMsg = "resuming injection where '%s' from session file" % where
456-
logger.info(logMsg)
457-
458-
elif expression == "Injection comment" and url == conf.url:
459-
comment = unSafeFormatString(value[:-1])
460-
kb.injection.data[kb.injection.data.keys()[0]].append(comment)
360+
elif expression == "Injection data" and url == conf.url:
361+
injection = base64unpickle(value[:-1])
362+
kb.injections.append(injection)
461363

462-
logMsg = "resuming injection comment '%s' from session file" % comment
364+
logMsg = "resuming injection data"
463365
logger.info(logMsg)
464366

465367
elif expression == "Boolean-based blind injection" and url == conf.url:

lib/parse/payloads.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
from lib.core.datatype import advancedDict
1515

1616
def cleanupVals(values, tag):
17+
if isinstance(values, basestring):
18+
return values
19+
1720
count = 0
1821

1922
for value in values:
@@ -48,7 +51,7 @@ def parseXmlNode(node):
4851

4952
for child in element.getchildren():
5053
if child.text and child.text.strip():
51-
values = cleanupVals(child.text.split(','), child.tag)
54+
values = cleanupVals(child.text.split(',') if child.tag != "epayload" else child.text, child.tag)
5255
test[child.tag] = values
5356
else:
5457
if len(child.getchildren()) == 0:

lib/request/inject.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ def goStacked(expression, silent=False):
401401
return direct(expression), None
402402

403403
comment = queries[kb.dbms].comment.query
404-
query = agent.prefixQuery("; %s" % expression)
405-
query = agent.suffixQuery("%s;%s" % (query, comment))
404+
query = agent.prefixQuery("; %s" % expression)
405+
query = agent.suffixQuery("%s;%s" % (query, comment))
406406

407407
debugMsg = "query: %s" % query
408408
logger.debug(debugMsg)
@@ -412,7 +412,7 @@ def goStacked(expression, silent=False):
412412

413413
return payload, page
414414

415-
def goError(expression, suppressOutput=False, returnPayload=False):
415+
def goError(expression, suppressOutput=False):
416416
"""
417417
Retrieve the output of a SQL query taking advantage of an error-based
418418
SQL injection vulnerability on the affected parameter.
@@ -436,10 +436,8 @@ def goError(expression, suppressOutput=False, returnPayload=False):
436436
result = resume(expression, None)
437437

438438
if not result:
439-
result = errorUse(expression, returnPayload)
440-
441-
if not returnPayload:
442-
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(result)))
439+
result = errorUse(expression)
440+
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(result)))
443441

444442
if suppressOutput:
445443
conf.verbose = popValue()

lib/techniques/error/use.py

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,45 +28,37 @@
2828
from lib.core.settings import ERROR_SPACE
2929
from lib.core.settings import ERROR_EMPTY_CHAR
3030

31-
def errorUse(expression, returnPayload=False):
31+
def errorUse(expression):
3232
"""
3333
Retrieve the output of a SQL query taking advantage of an error SQL
3434
injection vulnerability on the affected parameter.
3535
"""
3636

37-
output = None
38-
logic = conf.logic
39-
randInt = randomInt(1)
40-
query = agent.prefixQuery(queries[kb.misc.testedDbms].error.query)
41-
query = agent.suffixQuery(query)
42-
startLimiter = ""
43-
endLimiter = ""
37+
output = None
38+
randInt = randomInt(1)
39+
query = agent.cleanupPayload(kb.injection.data[2].epayload)
40+
query = agent.prefixQuery(query)
41+
query = agent.suffixQuery(query)
42+
check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop)
4443

4544
expressionUnescaped = expression
4645

47-
if kb.dbmsDetected:
48-
_, _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
49-
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
46+
_, _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
47+
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
5048

51-
if kb.dbms == DBMS.MYSQL:
52-
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))") # fix for that 'Subquery returns more than 1 row'
49+
if kb.dbms == DBMS.MYSQL:
50+
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))") # fix for that 'Subquery returns more than 1 row'
5351

54-
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
55-
expressionUnescaped = unescaper.unescape(expressionReplaced)
56-
startLimiter = unescaper.unescape("'%s'" % kb.misc.start)
57-
endLimiter = unescaper.unescape("'%s'" % kb.misc.stop)
58-
else:
59-
expressionUnescaped = kb.misc.handler.unescape(expression)
60-
startLimiter = kb.misc.handler.unescape("'%s'" % kb.misc.start)
61-
endLimiter = kb.misc.handler.unescape("'%s'" % kb.misc.stop)
52+
expression = expression.replace(fieldToCastStr, nulledCastedField, 1)
53+
expression = safeStringFormat(query, expression)
54+
expression = unescaper.unescape(expression)
6255

63-
forgedQuery = safeStringFormat(query, (logic, randInt, startLimiter, expressionUnescaped, endLimiter))
64-
debugMsg = "query: %s" % forgedQuery
56+
debugMsg = "query: %s" % expression
6557
logger.debug(debugMsg)
6658

67-
payload = agent.payload(newValue=forgedQuery)
68-
result = Request.queryPage(payload, content=True)
69-
match = re.search('%s(?P<result>.*?)%s' % (kb.misc.start, kb.misc.stop), result[0], re.DOTALL | re.IGNORECASE)
59+
payload = agent.payload(newValue=expression)
60+
reqBody, _ = Request.queryPage(payload, content=True)
61+
match = re.search(check, reqBody, re.DOTALL | re.IGNORECASE)
7062

7163
if match:
7264
output = match.group('result')
@@ -78,7 +70,4 @@ def errorUse(expression, returnPayload=False):
7870
infoMsg = "retrieved: %s" % replaceNewlineTabs(output, stdout=True)
7971
logger.info(infoMsg)
8072

81-
if returnPayload:
82-
return output, payload
83-
else:
84-
return output
73+
return output

0 commit comments

Comments
 (0)