mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-04-25 03:13:46 +03:00
changes regarding dynamic content recognition
This commit is contained in:
parent
c886659f82
commit
77a53228c5
|
@ -280,32 +280,53 @@ def checkDynParam(place, parameter, value):
|
||||||
|
|
||||||
return condition
|
return condition
|
||||||
|
|
||||||
def checkDynamicContent(firstPage, secondPage):
|
def checkDynamicContent(*pages):
|
||||||
|
"""
|
||||||
|
This function checks if the provided pages have dynamic content. If they
|
||||||
|
are dynamic, their content differs at specific lines.
|
||||||
|
"""
|
||||||
infoMsg = "searching for dynamic content"
|
infoMsg = "searching for dynamic content"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
linesFirst = preparePageForLineComparison(firstPage)
|
for i in xrange(len(pages)):
|
||||||
linesSecond = preparePageForLineComparison(secondPage)
|
firstPage = pages[i]
|
||||||
|
linesFirst = preparePageForLineComparison(firstPage)
|
||||||
|
pageLinesNumber = len(linesFirst)
|
||||||
|
for j in xrange(i+1, len(pages)):
|
||||||
|
secondPage = pages[j]
|
||||||
|
linesSecond = preparePageForLineComparison(secondPage)
|
||||||
|
if pageLinesNumber == len(linesSecond):
|
||||||
|
for k in xrange(0, pageLinesNumber):
|
||||||
|
if (linesFirst[k] != linesSecond[k]):
|
||||||
|
item = DynamicContentItem(k, pageLinesNumber, \
|
||||||
|
linesFirst[k-1] if k > 0 else None, \
|
||||||
|
linesFirst[k+1] if k < pageLinesNumber - 1 else None)
|
||||||
|
|
||||||
if len(linesFirst) == len(linesSecond):
|
found = None
|
||||||
lastLineNumber = None
|
for other in kb.dynamicContent:
|
||||||
pageLinesNumber = len(linesFirst)
|
found = True
|
||||||
for i in range(0, pageLinesNumber):
|
if other.pageTotal == item.pageTotal:
|
||||||
if (linesFirst[i] != linesSecond[i]):
|
if isinstance(other.lineNumber, int):
|
||||||
if lastLineNumber == i - 1:
|
if other.lineNumber == item.lineNumber - 1:
|
||||||
item = kb.dynamicContent[-1]
|
other.lineNumber = [other.lineNumber, item.lineNumber]
|
||||||
if isinstance(item.lineNumber, int):
|
other.lineContentAfter = item.lineContentAfter
|
||||||
item.lineNumber = [item.lineNumber]
|
break
|
||||||
item.lineNumber.append(i)
|
elif other.lineNumber == item.lineNumber + 1:
|
||||||
else:
|
other.lineNumber = [item.lineNumber, other.lineNumber]
|
||||||
kb.dynamicContent.append(DynamicContentItem(i, pageLinesNumber, linesFirst[i-1] if i > 0 else None, linesFirst[i+1] if i < pageLinesNumber - 1 else None))
|
other.lineContentBefore = item.lineContentBefore
|
||||||
lastLineNumber = i
|
break
|
||||||
|
elif item.lineNumber - 1 == other.lineNumber[-1]:
|
||||||
randInt = getUnicode(randomInt(1))
|
other.lineNumber.append(item.lineNumber)
|
||||||
payload = agent.fullPayload(" AND %s=%s" % (randInt, randInt))
|
other.lineContentAfter = item.lineContentAfter
|
||||||
result = Request.queryPage(payload)
|
break
|
||||||
if result:
|
elif item.lineNumber + 1 == other.lineNumber[0]:
|
||||||
pass #TODO: the same as above
|
other.lineNumber.insert(0, item.lineNumber)
|
||||||
|
other.lineContentBefore = item.lineContentBefore
|
||||||
|
break
|
||||||
|
found = False
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
kb.dynamicContent.append(item)
|
||||||
|
|
||||||
if kb.dynamicContent:
|
if kb.dynamicContent:
|
||||||
infoMsg = "found probably removable dynamic lines"
|
infoMsg = "found probably removable dynamic lines"
|
||||||
|
|
|
@ -163,7 +163,7 @@ def formatDBMSfp(versions=None):
|
||||||
|
|
||||||
while versions and None in versions:
|
while versions and None in versions:
|
||||||
versions.remove(None)
|
versions.remove(None)
|
||||||
|
|
||||||
if not versions and kb.dbmsVersion and kb.dbmsVersion[0] != "Unknown" and kb.dbmsVersion[0] != None:
|
if not versions and kb.dbmsVersion and kb.dbmsVersion[0] != "Unknown" and kb.dbmsVersion[0] != None:
|
||||||
versions = kb.dbmsVersion
|
versions = kb.dbmsVersion
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ def getDirs(webApi=None):
|
||||||
infoMsg = "retrieved web server full paths: "
|
infoMsg = "retrieved web server full paths: "
|
||||||
infoMsg += "'%s'" % ", ".join(path for path in kb.absFilePaths)
|
infoMsg += "'%s'" % ", ".join(path for path in kb.absFilePaths)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
for absFilePath in kb.absFilePaths:
|
for absFilePath in kb.absFilePaths:
|
||||||
if absFilePath:
|
if absFilePath:
|
||||||
directory = directoryPath(absFilePath)
|
directory = directoryPath(absFilePath)
|
||||||
|
@ -423,7 +423,7 @@ def strToHex(inpStr):
|
||||||
hexStr += hexChar
|
hexStr += hexChar
|
||||||
|
|
||||||
return hexStr
|
return hexStr
|
||||||
|
|
||||||
def fileToStr(fileName):
|
def fileToStr(fileName):
|
||||||
"""
|
"""
|
||||||
@param fileName: file path to read the content and return as a no
|
@param fileName: file path to read the content and return as a no
|
||||||
|
@ -481,7 +481,7 @@ def readInput(message, default=None):
|
||||||
data = default
|
data = default
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def randomRange(start=0, stop=1000):
|
def randomRange(start=0, stop=1000):
|
||||||
"""
|
"""
|
||||||
@param start: starting number.
|
@param start: starting number.
|
||||||
|
@ -767,7 +767,7 @@ def parseTargetUrl():
|
||||||
conf.parameters["GET"] = __urlSplit[3]
|
conf.parameters["GET"] = __urlSplit[3]
|
||||||
|
|
||||||
conf.url = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, conf.path)
|
conf.url = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, conf.path)
|
||||||
|
|
||||||
def expandAsteriskForColumns(expression):
|
def expandAsteriskForColumns(expression):
|
||||||
# If the user provided an asterisk rather than the column(s)
|
# If the user provided an asterisk rather than the column(s)
|
||||||
# name, sqlmap will retrieve the columns itself and reprocess
|
# name, sqlmap will retrieve the columns itself and reprocess
|
||||||
|
@ -819,7 +819,7 @@ def getRange(count, dump=False, plusOne=False):
|
||||||
indexRange = range(limitStart - 1, limitStop)
|
indexRange = range(limitStart - 1, limitStop)
|
||||||
|
|
||||||
return indexRange
|
return indexRange
|
||||||
|
|
||||||
def parseUnionPage(output, expression, partial=False, condition=None, sort=True):
|
def parseUnionPage(output, expression, partial=False, condition=None, sort=True):
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
|
@ -896,7 +896,7 @@ def getDelayQuery(andCond=False):
|
||||||
query = "(%s)>0" % query
|
query = "(%s)>0" % query
|
||||||
|
|
||||||
return query
|
return query
|
||||||
|
|
||||||
def getLocalIP():
|
def getLocalIP():
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
s.connect((conf.hostname, conf.port))
|
s.connect((conf.hostname, conf.port))
|
||||||
|
@ -918,7 +918,7 @@ def getFileType(filePath):
|
||||||
return "text"
|
return "text"
|
||||||
else:
|
else:
|
||||||
return "binary"
|
return "binary"
|
||||||
|
|
||||||
def pollProcess(process):
|
def pollProcess(process):
|
||||||
while True:
|
while True:
|
||||||
dataToStdout(".")
|
dataToStdout(".")
|
||||||
|
@ -935,7 +935,7 @@ def pollProcess(process):
|
||||||
dataToStdout(" quit unexpectedly with return code %d\n" % returncode)
|
dataToStdout(" quit unexpectedly with return code %d\n" % returncode)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
def getCharset(charsetType=None):
|
def getCharset(charsetType=None):
|
||||||
asciiTbl = []
|
asciiTbl = []
|
||||||
|
|
||||||
|
@ -973,7 +973,7 @@ def getCharset(charsetType=None):
|
||||||
asciiTbl.extend(range(96, 123))
|
asciiTbl.extend(range(96, 123))
|
||||||
|
|
||||||
return asciiTbl
|
return asciiTbl
|
||||||
|
|
||||||
def searchEnvPath(fileName):
|
def searchEnvPath(fileName):
|
||||||
envPaths = os.environ["PATH"]
|
envPaths = os.environ["PATH"]
|
||||||
result = None
|
result = None
|
||||||
|
@ -1137,7 +1137,7 @@ def isBase64EncodedString(subject):
|
||||||
False
|
False
|
||||||
"""
|
"""
|
||||||
return re.match(r"\A(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\Z", subject) is not None
|
return re.match(r"\A(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\Z", subject) is not None
|
||||||
|
|
||||||
def isHexEncodedString(subject):
|
def isHexEncodedString(subject):
|
||||||
"""
|
"""
|
||||||
Checks if the provided string is hex encoded
|
Checks if the provided string is hex encoded
|
||||||
|
@ -1249,7 +1249,7 @@ def parseXmlFile(xmlFile, handler):
|
||||||
|
|
||||||
def calculateDeltaSeconds(start, epsilon=0.05):
|
def calculateDeltaSeconds(start, epsilon=0.05):
|
||||||
"""
|
"""
|
||||||
Returns elapsed time from start till now (including expected
|
Returns elapsed time from start till now (including expected
|
||||||
error set by epsilon parameter)
|
error set by epsilon parameter)
|
||||||
"""
|
"""
|
||||||
return int(time.time() - start + epsilon)
|
return int(time.time() - start + epsilon)
|
||||||
|
@ -1470,6 +1470,7 @@ def smokeTest():
|
||||||
logger.error(infoMsg)
|
logger.error(infoMsg)
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
|
|
||||||
class UnicodeRawConfigParser(RawConfigParser):
|
class UnicodeRawConfigParser(RawConfigParser):
|
||||||
def write(self, fp):
|
def write(self, fp):
|
||||||
"""
|
"""
|
||||||
|
@ -1496,6 +1497,7 @@ class UnicodeRawConfigParser(RawConfigParser):
|
||||||
|
|
||||||
fp.write("\n")
|
fp.write("\n")
|
||||||
|
|
||||||
|
|
||||||
class DynamicContentItem:
|
class DynamicContentItem:
|
||||||
"""
|
"""
|
||||||
Represents line in content page with dynamic properties (candidate for removal prior detection phase)
|
Represents line in content page with dynamic properties (candidate for removal prior detection phase)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user