mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 19:13:48 +03:00
Merge branch 'master' of github.com:sqlmapproject/sqlmap
This commit is contained in:
commit
92c2b3bd4c
|
@ -359,7 +359,7 @@ def checkSqlInjection(place, parameter, value):
|
|||
|
||||
injectable = True
|
||||
|
||||
if not injectable and not conf.string and kb.pageStable:
|
||||
if not injectable and not any((conf.string, conf.notString, conf.regexp)) and kb.pageStable:
|
||||
trueSet = set(extractTextTagContent(truePage))
|
||||
falseSet = set(extractTextTagContent(falsePage))
|
||||
candidates = filter(None, (_.strip() if _.strip() in (kb.pageTemplate or "") and _.strip() not in falsePage else None for _ in (trueSet - falseSet)))
|
||||
|
@ -460,7 +460,7 @@ def checkSqlInjection(place, parameter, value):
|
|||
# Feed with the boundaries details only the first time a
|
||||
# test has been successful
|
||||
if injection.place is None or injection.parameter is None:
|
||||
if place in (PLACE.UA, PLACE.REFERER, PLACE.HOST):
|
||||
if place in (PLACE.USER_AGENT, PLACE.REFERER, PLACE.HOST):
|
||||
injection.parameter = place
|
||||
else:
|
||||
injection.parameter = parameter
|
||||
|
@ -499,6 +499,7 @@ def checkSqlInjection(place, parameter, value):
|
|||
injection.conf.textOnly = conf.textOnly
|
||||
injection.conf.titles = conf.titles
|
||||
injection.conf.string = conf.string
|
||||
injection.conf.notString = conf.notString
|
||||
injection.conf.regexp = conf.regexp
|
||||
injection.conf.optimize = conf.optimize
|
||||
|
||||
|
|
|
@ -357,7 +357,7 @@ def start():
|
|||
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:
|
||||
if not any((conf.string, conf.notString, 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()
|
||||
|
@ -378,7 +378,7 @@ def start():
|
|||
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.USER_AGENT and conf.level < 3)
|
||||
skip |= (place == PLACE.REFERER and conf.level < 3)
|
||||
|
||||
# Test Host header only if
|
||||
|
@ -388,11 +388,11 @@ def start():
|
|||
# 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.USER_AGENT 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.USER_AGENT 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))
|
||||
|
||||
|
@ -527,7 +527,7 @@ def start():
|
|||
errMsg += "Please, consider usage of tampering scripts as "
|
||||
errMsg += "your target might filter the queries."
|
||||
|
||||
if not conf.string and not conf.regexp:
|
||||
if not conf.string and not conf.notString and not conf.regexp:
|
||||
errMsg += " Also, you can try to rerun by providing "
|
||||
errMsg += "either a valid value for option '--string' "
|
||||
errMsg += "(or '--regexp')"
|
||||
|
|
|
@ -118,7 +118,7 @@ class Agent:
|
|||
retVal = ET.tostring(root)
|
||||
elif place in (PLACE.URI, PLACE.CUSTOM_POST):
|
||||
retVal = paramString.replace("%s%s" % (origValue, CUSTOM_INJECTION_MARK_CHAR), self.addPayloadDelimiters(newValue))
|
||||
elif place in (PLACE.UA, PLACE.REFERER, PLACE.HOST):
|
||||
elif place in (PLACE.USER_AGENT, PLACE.REFERER, PLACE.HOST):
|
||||
retVal = paramString.replace(origValue, self.addPayloadDelimiters(newValue))
|
||||
else:
|
||||
retVal = paramString.replace("%s=%s" % (parameter, origValue),
|
||||
|
|
|
@ -255,7 +255,7 @@ class Format:
|
|||
if "technology" in info:
|
||||
infoStr += "\nweb application technology: %s" % Format.humanize(info["technology"], ", ")
|
||||
|
||||
return infoStr
|
||||
return infoStr.lstrip()
|
||||
|
||||
class Backend:
|
||||
# Set methods
|
||||
|
@ -2362,7 +2362,7 @@ def setOptimize():
|
|||
#conf.predictOutput = True
|
||||
conf.keepAlive = True
|
||||
conf.threads = 3 if conf.threads < 3 else conf.threads
|
||||
conf.nullConnection = not any([conf.data, conf.textOnly, conf.titles, conf.string, conf.regexp, conf.tor])
|
||||
conf.nullConnection = not any([conf.data, conf.textOnly, conf.titles, conf.string, conf.notString, conf.regexp, conf.tor])
|
||||
|
||||
if not conf.nullConnection:
|
||||
debugMsg = "turning off --null-connection switch used indirectly by switch -o"
|
||||
|
|
|
@ -61,7 +61,7 @@ class PLACE:
|
|||
SOAP = "SOAP"
|
||||
URI = "URI"
|
||||
COOKIE = "Cookie"
|
||||
UA = "User-Agent"
|
||||
USER_AGENT = "User-Agent"
|
||||
REFERER = "Referer"
|
||||
HOST = "Host"
|
||||
CUSTOM_POST = "(custom) POST"
|
||||
|
|
|
@ -1867,6 +1867,14 @@ def __basicOptionValidation():
|
|||
errMsg = "option '--string' is incompatible with switch '--null-connection'"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
if conf.notString and conf.nullConnection:
|
||||
errMsg = "option '--not-string' is incompatible with switch '--null-connection'"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
if conf.string and conf.notString:
|
||||
errMsg = "option '--string' is incompatible with switch '--not-string'"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
if conf.regexp and conf.nullConnection:
|
||||
errMsg = "option '--regexp' is incompatible with switch '--null-connection'"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
|
|
@ -76,6 +76,7 @@ optDict = {
|
|||
"level": "integer",
|
||||
"risk": "integer",
|
||||
"string": "string",
|
||||
"notString": "notString",
|
||||
"regexp": "string",
|
||||
"code": "integer",
|
||||
"textOnly": "boolean",
|
||||
|
@ -87,7 +88,8 @@ optDict = {
|
|||
"timeSec": "integer",
|
||||
"uCols": "string",
|
||||
"uChar": "string",
|
||||
"dnsName": "string"
|
||||
"dnsName": "string",
|
||||
"secondOrder": "string"
|
||||
},
|
||||
|
||||
"Fingerprint": {
|
||||
|
|
|
@ -26,6 +26,7 @@ from lib.core.data import logger
|
|||
from lib.core.data import paths
|
||||
from lib.core.dump import dumper
|
||||
from lib.core.enums import HASHDB_KEYS
|
||||
from lib.core.enums import HTTPHEADER
|
||||
from lib.core.enums import HTTPMETHOD
|
||||
from lib.core.enums import PLACE
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
|
@ -158,16 +159,18 @@ def __setRequestParams():
|
|||
# Url encoding of the header values should be avoided
|
||||
# Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value
|
||||
|
||||
if httpHeader == PLACE.UA:
|
||||
conf.parameters[PLACE.UA] = urldecode(headerValue)
|
||||
httpHeader = "-".join(_.capitalize() for _ in (httpHeader or "").split("-"))
|
||||
|
||||
if httpHeader == HTTPHEADER.USER_AGENT:
|
||||
conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES)))
|
||||
|
||||
if condition:
|
||||
conf.paramDict[PLACE.UA] = {PLACE.UA: headerValue}
|
||||
conf.paramDict[PLACE.USER_AGENT] = {PLACE.USER_AGENT: headerValue}
|
||||
testableParameters = True
|
||||
|
||||
elif httpHeader == PLACE.REFERER:
|
||||
elif httpHeader == HTTPHEADER.REFERER:
|
||||
conf.parameters[PLACE.REFERER] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES)))
|
||||
|
@ -176,7 +179,7 @@ def __setRequestParams():
|
|||
conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue}
|
||||
testableParameters = True
|
||||
|
||||
elif httpHeader == PLACE.HOST:
|
||||
elif httpHeader == HTTPHEADER.HOST:
|
||||
conf.parameters[PLACE.HOST] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES)))
|
||||
|
|
|
@ -245,6 +245,10 @@ def cmdLineParser():
|
|||
help="String to match when "
|
||||
"query is evaluated to True")
|
||||
|
||||
detection.add_option("--not-string", dest="notString",
|
||||
help="String to match when "
|
||||
"query is evaluated to False")
|
||||
|
||||
detection.add_option("--regexp", dest="regexp",
|
||||
help="Regexp to match when "
|
||||
"query is evaluated to True")
|
||||
|
@ -284,6 +288,10 @@ def cmdLineParser():
|
|||
techniques.add_option("--dns-domain", dest="dnsName",
|
||||
help="Domain name used for DNS exfiltration attack")
|
||||
|
||||
techniques.add_option("--second-order", dest="secondOrder",
|
||||
help="Resulting page url searched for second-order "
|
||||
"response")
|
||||
|
||||
# Fingerprint options
|
||||
fingerprint = OptionGroup(parser, "Fingerprint")
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ def comparison(page, headers, code=None, getRatioValue=False, pageLength=None):
|
|||
return _
|
||||
|
||||
def _adjust(condition, getRatioValue):
|
||||
if not any([conf.string, conf.regexp, conf.code]):
|
||||
if not any([conf.string, conf.notString, conf.regexp, conf.code]):
|
||||
# Negative logic approach is used in raw page comparison scheme as that what is "different" than original
|
||||
# PAYLOAD.WHERE.NEGATIVE response is considered as True; in switch based approach negative logic is not
|
||||
# applied as that what is by user considered as True is that what is returned by the comparison mechanism
|
||||
|
@ -54,14 +54,18 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
|
|||
seqMatcher = threadData.seqMatcher
|
||||
seqMatcher.set_seq1(kb.pageTemplate)
|
||||
|
||||
if any([conf.string, conf.regexp]):
|
||||
if any([conf.string, conf.notString, conf.regexp]):
|
||||
rawResponse = "%s%s" % (listToStrValue(headers.headers if headers else ""), page)
|
||||
|
||||
# String to match in page when the query is valid
|
||||
# String to match in page when the query is True and/or valid
|
||||
if conf.string:
|
||||
return conf.string in rawResponse
|
||||
|
||||
# Regular expression to match in page when the query is valid
|
||||
# String to match in page when the query is False and/or invalid
|
||||
if conf.notString:
|
||||
return conf.notString not in rawResponse
|
||||
|
||||
# Regular expression to match in page when the query is True and/or valid
|
||||
if conf.regexp:
|
||||
return re.search(conf.regexp, rawResponse, re.I | re.M) is not None
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ class Connect:
|
|||
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 "/"
|
||||
requestMsg += ("%s" % urlparse.urlsplit(url)[2] or "/") if not any((refreshing, crawling)) else url
|
||||
responseMsg = u"HTTP response "
|
||||
requestHeaders = u""
|
||||
responseHeaders = None
|
||||
|
@ -236,7 +236,7 @@ class Connect:
|
|||
|
||||
return page
|
||||
|
||||
elif any ([refreshing, crawling]):
|
||||
elif any ((refreshing, crawling)):
|
||||
pass
|
||||
|
||||
elif target:
|
||||
|
@ -595,8 +595,8 @@ class Connect:
|
|||
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.USER_AGENT in conf.parameters:
|
||||
ua = conf.parameters[PLACE.USER_AGENT] if place != PLACE.USER_AGENT 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
|
||||
|
@ -731,6 +731,9 @@ class Connect:
|
|||
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)
|
||||
|
||||
if conf.secondOrder:
|
||||
page, headers, code = Connect.getPage(url=conf.secondOrder, cookie=cookie, ua=ua, silent=silent, auxHeaders=auxHeaders, response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
|
||||
|
||||
threadData.lastQueryDuration = calculateDeltaSeconds(start)
|
||||
|
||||
kb.originalCode = kb.originalCode or code
|
||||
|
|
|
@ -6,6 +6,7 @@ See the file 'doc/COPYING' for copying permission
|
|||
"""
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import sqlite3
|
||||
import threading
|
||||
import time
|
||||
|
@ -54,7 +55,7 @@ class HashDB(object):
|
|||
|
||||
def retrieve(self, key, unserialize=False):
|
||||
retVal = None
|
||||
if key:
|
||||
if key and (self._write_cache or os.path.isfile(self.filepath)):
|
||||
hash_ = HashDB.hashKey(key)
|
||||
retVal = self._write_cache.get(hash_, None)
|
||||
if not retVal:
|
||||
|
|
|
@ -247,6 +247,11 @@ risk = 1
|
|||
# Refer to the user's manual for further details.
|
||||
string =
|
||||
|
||||
# String to match within the raw response when the query is evaluated to
|
||||
# False, only needed if the page content dynamically changes at each refresh.
|
||||
# Refer to the user's manual for further details.
|
||||
notString =
|
||||
|
||||
# Regular expression to match within the raw response when the query is
|
||||
# evaluated to True, only needed if the needed if the page content
|
||||
# dynamically changes at each refresh.
|
||||
|
@ -305,6 +310,10 @@ uChar =
|
|||
# Valid: string
|
||||
dnsName =
|
||||
|
||||
# Resulting page url searched for second-order response
|
||||
# Valid: string
|
||||
secondOrder =
|
||||
|
||||
|
||||
[Fingerprint]
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user