From 1d0b43b1a235be3ab7f628f960b31c4e375a8324 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Wed, 11 Jan 2012 14:28:08 +0000 Subject: [PATCH] implemented mechanism for merging cookies by request --- lib/controller/controller.py | 27 +------------------- lib/core/enums.py | 1 + lib/core/option.py | 1 + lib/request/basic.py | 48 +++++++++++++++++++++++++++--------- lib/request/connect.py | 19 +++----------- 5 files changed, 42 insertions(+), 54 deletions(-) diff --git a/lib/controller/controller.py b/lib/controller/controller.py index eaff7acbd..94deab6ea 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -49,6 +49,7 @@ from lib.core.exception import sqlmapSilentQuitException from lib.core.exception import sqlmapValueException from lib.core.exception import sqlmapUserQuitException from lib.core.session import setInjection +from lib.core.settings import DEFAULT_COOKIE_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import EMPTY_FORM_FIELDS_REGEX from lib.core.settings import IGNORE_PARAMETERS @@ -241,7 +242,6 @@ def start(): hostCount = 0 cookieStr = "" - setCookieAsInjectable = True for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls: try: @@ -345,31 +345,6 @@ def start(): if conf.nullConnection: checkNullConnection() - if not conf.dropSetCookie and conf.cj: - cookieStr = ";".join("%s=%s" % (getUnicode(cookie.name), getUnicode(cookie.value)) for _, cookie in enumerate(conf.cj)) - - if cookieStr: - if PLACE.COOKIE in conf.parameters: - message = "you provided an HTTP Cookie header value. " - message += "The target url provided its own Cookie within " - message += "the HTTP Set-Cookie header. Do you want to " - message += "continue using the HTTP Cookie values that " - message += "you provided? [Y/n] " - test = readInput(message, default="Y") - - if not test or test[0] in ("y", "Y"): - setCookieAsInjectable = False - - if setCookieAsInjectable: - conf.httpHeaders.append((HTTPHEADER.COOKIE, cookieStr)) - conf.parameters[PLACE.COOKIE] = cookieStr - __paramDict = paramToDict(PLACE.COOKIE, cookieStr) - - if __paramDict: - conf.paramDict[PLACE.COOKIE] = __paramDict - # TODO: consider the following line in __setRequestParams() - # __testableParameters = True - if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \ and (kb.injection.place is None or kb.injection.parameter is None): diff --git a/lib/core/enums.py b/lib/core/enums.py index 3fffcc189..38af43cb8 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -109,6 +109,7 @@ class HTTPHEADER: CONTENT_RANGE = "Content-Range" CONTENT_TYPE = "Content-Type" COOKIE = "Cookie" + SET_COOKIE = "Set-Cookie" HOST = "Host" PRAGMA = "Pragma" PROXY_AUTHORIZATION = "Proxy-Authorization" diff --git a/lib/core/option.py b/lib/core/option.py index 4b7e041a9..ee9bb7d8b 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1442,6 +1442,7 @@ def __setKnowledgeBaseAttributes(flushAll=True): kb.locks[_] = threading.Lock() kb.matchRatio = None + kb.mergeCookies = None kb.multiThreadMode = False kb.nullConnection = None kb.pageTemplate = None diff --git a/lib/request/basic.py b/lib/request/basic.py index 1a7b870df..6c2996004 100644 --- a/lib/request/basic.py +++ b/lib/request/basic.py @@ -21,13 +21,16 @@ from lib.core.common import extractRegexResult from lib.core.common import getUnicode from lib.core.common import isWindowsDriveLetterPath from lib.core.common import posixToNtSlashes +from lib.core.common import readInput from lib.core.common import sanitizeAsciiString from lib.core.common import singleTimeLogMessage from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger from lib.core.enums import HTTPHEADER +from lib.core.enums import PLACE from lib.core.exception import sqlmapDataException +from lib.core.settings import DEFAULT_COOKIE_DELIMITER from lib.core.settings import ML from lib.core.settings import META_CHARSET_REGEX from lib.core.settings import PARSE_HEADERS_LIMIT @@ -35,27 +38,48 @@ from lib.core.settings import UNICODE_ENCODING from lib.parse.headers import headersParser from lib.parse.html import htmlParser -def forgeHeaders(cookie, ua, referer): +def forgeHeaders(items=None): """ Prepare HTTP Cookie, HTTP User-Agent and HTTP Referer headers to use when performing the HTTP requests """ - headers = {} + headers = dict(conf.httpHeaders) + headers.update(items or {}) - for header, value in conf.httpHeaders: - if cookie and header == HTTPHEADER.COOKIE: - headers[header] = cookie - elif ua and header == HTTPHEADER.USER_AGENT: - headers[header] = ua - elif referer and header == HTTPHEADER.REFERER: - headers[header] = referer - else: - headers[header] = value + for _ in headers.keys(): + if headers[_] is None: + del headers[_] + + if conf.cj: + if HTTPHEADER.COOKIE in headers: + for cookie in conf.cj: + if ("%s=" % cookie.name) in headers[HTTPHEADER.COOKIE]: + if kb.mergeCookies is None: + message = "you provided a HTTP %s header value. " % HTTPHEADER.COOKIE + message += "The target url provided it's own cookies within " + message += "the HTTP %s header which intersect with yours. " % HTTPHEADER.SET_COOKIE + message += "Do you want to merge them in futher requests? [Y/n] " + test = readInput(message, default="Y") + kb.mergeCookies = not test or test[0] in ("y", "Y") + + if kb.mergeCookies: + _ = lambda x: re.sub("%s=[^%s]+" % (cookie.name, DEFAULT_COOKIE_DELIMITER), "%s=%s" % (cookie.name, cookie.value), x, re.I) + headers[HTTPHEADER.COOKIE] = _(headers[HTTPHEADER.COOKIE]) + + if PLACE.COOKIE in conf.parameters: + conf.parameters[PLACE.COOKIE] = _(conf.parameters[PLACE.COOKIE]) + conf.httpHeaders = [(item[0], item[1] if item[0] != HTTPHEADER.COOKIE else _(item[1])) for item in conf.httpHeaders] + + elif not kb.testMode: + headers[HTTPHEADER.COOKIE] += "%s %s=%s" % (DEFAULT_COOKIE_DELIMITER, cookie.name, cookie.value) + + if kb.testMode: + conf.cj.clear() if kb.redirectSetCookie and not conf.dropSetCookie: if HTTPHEADER.COOKIE in headers: - headers[HTTPHEADER.COOKIE] = "%s; %s" % (headers[HTTPHEADER.COOKIE], kb.redirectSetCookie) + headers[HTTPHEADER.COOKIE] += "%s %s" % (DEFAULT_COOKIE_DELIMITER, kb.redirectSetCookie) else: headers[HTTPHEADER.COOKIE] = kb.redirectSetCookie diff --git a/lib/request/connect.py b/lib/request/connect.py index 05f630752..a480b9230 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -240,7 +240,7 @@ class Connect: requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str # Prepare HTTP headers - headers = forgeHeaders(cookie, ua, referer) + headers = forgeHeaders({ HTTPHEADER.COOKIE: cookie, HTTPHEADER.USER_AGENT: ua, HTTPHEADER.REFERER: referer }) if conf.realTest: headers[HTTPHEADER.REFERER] = "%s://%s" % (conf.scheme, conf.hostname) @@ -271,23 +271,13 @@ class Connect: else: req = urllib2.Request(url, post, headers) - if not conf.dropSetCookie and conf.cj: - for _, cookie in enumerate(conf.cj): - if not cookieStr: - cookieStr = "Cookie: " - - cookie = getUnicode(cookie) - index = cookie.index(" for ") - - cookieStr += "%s; " % cookie[8:index] - if not req.has_header(HTTPHEADER.ACCEPT_ENCODING): requestHeaders += "%s: identity\n" % HTTPHEADER.ACCEPT_ENCODING requestHeaders += "\n".join("%s: %s" % (key.capitalize() if isinstance(key, basestring) else key, getUnicode(value)) for (key, value) in req.header_items()) - if not req.has_header(HTTPHEADER.COOKIE) and cookieStr: - requestHeaders += "\n%s" % cookieStr[:-2] + if not req.has_header(HTTPHEADER.COOKIE) and conf.cj: + requestHeaders += "\n%s" % ("Cookie: %s" % ";".join("%s=%s" % (getUnicode(cookie.name), getUnicode(cookie.value)) for cookie in conf.cj)) if not req.has_header(HTTPHEADER.CONNECTION): requestHeaders += "\n%s: close" % HTTPHEADER.CONNECTION @@ -728,9 +718,6 @@ class Connect: if kb.testMode: kb.testQueryCount += 1 - if conf.cj: - conf.cj.clear() - if timeBasedCompare: return wasLastRequestDelayed() elif noteResponseTime: