diff --git a/lib/controller/controller.py b/lib/controller/controller.py index ad9e44b3a..1a39d91eb 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -129,6 +129,9 @@ def _formatInjection(inj): title = sdata.title vector = sdata.vector comment = sdata.comment + payload = agent.adjustLateValues(sdata.payload) + if inj.place == PLACE.CUSTOM_HEADER: + payload = payload.split(',', 1)[1] if stype == PAYLOAD.TECHNIQUE.UNION: count = re.sub(r"(?i)(\(.+\))|(\blimit[^A-Za-z]+)", "", sdata.payload).count(',') + 1 title = re.sub(r"\d+ to \d+", str(count), title) @@ -139,7 +142,7 @@ def _formatInjection(inj): vector = "%s%s" % (vector, comment) data += " Type: %s\n" % PAYLOAD.SQLINJECTION[stype] data += " Title: %s\n" % title - data += " Payload: %s\n" % agent.adjustLateValues(sdata.payload) + data += " Payload: %s\n" % payload data += " Vector: %s\n\n" % vector if conf.verbose > 1 else "\n" return data @@ -369,7 +372,7 @@ def start(): parameters = conf.parameters.keys() # Order of testing list (first to last) - orderList = (PLACE.CUSTOM_POST, PLACE.URI, PLACE.POST, PLACE.GET) + orderList = (PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER, PLACE.URI, PLACE.POST, PLACE.GET) for place in orderList[::-1]: if place in parameters: @@ -377,7 +380,6 @@ def start(): parameters.insert(0, place) proceed = True - for place in parameters: # Test User-Agent and Referer headers only if # --level >= 3 @@ -444,15 +446,15 @@ def start(): logger.info(infoMsg) elif PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech: - check = checkDynParam(place, parameter, value) + check = checkDynParam(place, parameter, value) - if not check: - warnMsg = "%s parameter '%s' does not appear dynamic" % (place, parameter) - logger.warn(warnMsg) + if not check: + warnMsg = "%s parameter '%s' does not appear dynamic" % (place, parameter) + logger.warn(warnMsg) - else: - infoMsg = "%s parameter '%s' is dynamic" % (place, parameter) - logger.info(infoMsg) + else: + infoMsg = "%s parameter '%s' is dynamic" % (place, parameter) + logger.info(infoMsg) kb.testedParams.add(paramKey) diff --git a/lib/core/agent.py b/lib/core/agent.py index 15597aa5d..137abeb5b 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -90,6 +90,10 @@ class Agent(object): paramString = origValue origValue = origValue.split(CUSTOM_INJECTION_MARK_CHAR)[0] origValue = extractRegexResult(r"(?s)(?P(\W+\Z|\w+\Z))", origValue) + elif place == PLACE.CUSTOM_HEADER: + paramString = origValue + origValue = origValue.split(CUSTOM_INJECTION_MARK_CHAR)[0] + origValue = origValue[origValue.index(',') + 1:] if value is None: if where == PAYLOAD.WHERE.ORIGINAL: @@ -115,7 +119,7 @@ class Agent(object): newValue = self.cleanupPayload(newValue, origValue) - if place in (PLACE.URI, PLACE.CUSTOM_POST): + if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER): _ = "%s%s" % (origValue, CUSTOM_INJECTION_MARK_CHAR) if kb.postHint == POST_HINT.JSON and not isNumber(newValue) and not '"%s"' % _ in paramString: newValue = '"%s"' % newValue diff --git a/lib/core/enums.py b/lib/core/enums.py index a5b649013..50a8ce1cf 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -64,6 +64,7 @@ class PLACE: REFERER = "Referer" HOST = "Host" CUSTOM_POST = "(custom) POST" + CUSTOM_HEADER = "(custom) HEADER" class POST_HINT: SOAP = "SOAP" diff --git a/lib/core/target.py b/lib/core/target.py index 9ccec202f..d3941dfcb 100644 --- a/lib/core/target.py +++ b/lib/core/target.py @@ -147,10 +147,10 @@ def _setRequestParams(): elif test[0] in ("q", "Q"): raise SqlmapUserQuitException - for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data)): + for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, re.sub(r"\bq=[^;']+", "", str(conf.httpHeaders)))): if CUSTOM_INJECTION_MARK_CHAR in (value or ""): if kb.processUserMarks is None: - _ = {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data'} + _ = {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data', PLACE.CUSTOM_HEADER: '--headers/--user-agent/--referer'} message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR message += "'%s'. Do you want to process it? [Y/n/q] " % _[place] test = readInput(message, default="Y") @@ -170,21 +170,28 @@ def _setRequestParams(): conf.url = conf.url.split('?')[0] conf.paramDict[PLACE.GET] = paramDict testableParameters = True - continue + else: + conf.parameters[place] = value + conf.paramDict[place] = OrderedDict() - conf.parameters[place] = value - conf.paramDict[place] = OrderedDict() - parts = value.split(CUSTOM_INJECTION_MARK_CHAR) + if place == PLACE.CUSTOM_HEADER: + for index in xrange(len(conf.httpHeaders)): + header, value = conf.httpHeaders[index] + if CUSTOM_INJECTION_MARK_CHAR in re.sub(r"\bq=[^;']+", "", value): + conf.paramDict[place][header] = "%s,%s" % (header, value) + conf.httpHeaders[index] = (header, value.replace(CUSTOM_INJECTION_MARK_CHAR, "")) + else: + parts = value.split(CUSTOM_INJECTION_MARK_CHAR) - for i in xrange(len(parts) - 1): - conf.paramDict[place]["%s#%d%s" % (("%s " % kb.postHint) if kb.postHint else "", i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts))) + for i in xrange(len(parts) - 1): + conf.paramDict[place]["%s#%d%s" % (("%s " % kb.postHint) if kb.postHint else "", i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts))) - if place == PLACE.URI and PLACE.GET in conf.paramDict: - del conf.paramDict[PLACE.GET] - elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict: - del conf.paramDict[PLACE.POST] + if place == PLACE.URI and PLACE.GET in conf.paramDict: + del conf.paramDict[PLACE.GET] + elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict: + del conf.paramDict[PLACE.POST] - testableParameters = True + testableParameters = True if kb.processUserMarks: conf.url = conf.url.replace(CUSTOM_INJECTION_MARK_CHAR, "") diff --git a/lib/request/connect.py b/lib/request/connect.py index e4bcd7b34..488586f7b 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -617,7 +617,6 @@ class Connect(object): else: payload = json.dumps(payload)[1:-1] value = agent.replacePayload(value, payload) - else: if not skipUrlEncode and place in (PLACE.GET, PLACE.COOKIE, PLACE.URI): # GET, URI and Cookie need to be throughly URL encoded (POST is encoded down below) @@ -686,6 +685,11 @@ class Connect(object): else: uri = conf.url + if place == PLACE.CUSTOM_HEADER: + if not auxHeaders: + auxHeaders = {} + auxHeaders[value.split(',')[0]] = value.split(',', 1)[1] + if conf.rParam: def _randomizeParameter(paramString, randomParameter): retVal = paramString