diff --git a/lib/controller/checks.py b/lib/controller/checks.py
index 5767fdba8..2e57637f7 100644
--- a/lib/controller/checks.py
+++ b/lib/controller/checks.py
@@ -99,11 +99,15 @@ def heuristicCheckSqlInjection(place, parameter, value):
postfix = conf.postfix
payload = "%s%s%s" % (prefix, randomStr(length=10, alphabet=['"', '\'', ')', '(']), postfix)
+
if place == "URI":
payload = conf.paramDict[place][parameter].replace('*', payload)
+
Request.queryPage(payload, place)
result = kb.lastErrorPage and kb.lastErrorPage[0]==kb.lastRequestUID
+
infoMsg = "(error based) heuristics show that %s parameter '%s' is " % (place, parameter)
+
if result:
infoMsg += "injectable"
logger.info(infoMsg)
@@ -147,6 +151,7 @@ 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"
logger.info(infoMsg)
@@ -170,6 +175,7 @@ def checkDynamicContent(*pages):
for other in kb.dynamicContent:
found = True
+
if other.pageTotal == item.pageTotal:
if isinstance(other.lineNumber, int):
if other.lineNumber == item.lineNumber - 1:
@@ -235,28 +241,34 @@ def checkStability():
elif not condition:
warnMsg = "url is not stable, sqlmap will base the page "
- warnMsg += "comparison on a sequence matcher. if no dynamic nor "
- warnMsg += "injectable parameters are detected, or in case of junk "
- warnMsg += "results, refer to user's "
- warnMsg += "manual paragraph 'Page comparison' and provide a "
- warnMsg += "string or regular expression to match on"
+ warnMsg += "comparison on a sequence matcher. If no dynamic nor "
+ warnMsg += "injectable parameters are detected, or in case of "
+ warnMsg += "junk results, refer to user's manual paragraph "
+ warnMsg += "'Page comparison' and provide a string or regular "
+ warnMsg += "expression to match on"
logger.warn(warnMsg)
message = "how do you want to proceed? [C(ontinue)/s(tring)/r(egex)/q(uit)] "
test = readInput(message, default="C")
+
if test and test[0] in ("q", "Q"):
raise sqlmapUserQuitException
+
elif test and test[0] in ("s", "S"):
showStaticWords(firstPage, secondPage)
+
message = "please enter value for parameter 'string': "
test = readInput(message)
+
if test:
conf.string = test
else:
raise sqlmapSilentQuitException
+
elif test and test[0] in ("r", "R"):
message = "please enter value for parameter 'regex': "
test = readInput(message)
+
if test:
conf.regex = test
else:
diff --git a/lib/core/common.py b/lib/core/common.py
index d9b0b2690..d831c0ee2 100644
--- a/lib/core/common.py
+++ b/lib/core/common.py
@@ -1107,33 +1107,42 @@ def sanitizeAsciiString(subject):
def preparePageForLineComparison(page):
retVal = page
+
if isinstance(page, basestring):
return page.replace("><", ">\n<").replace("
", "\n").splitlines()
+
return retVal
def getFilteredPageContent(page):
retVal = page
+
if isinstance(page, basestring):
retVal = re.sub(r"(?s)||<[^>]+>|\t|\n|\r", " ", page)
+
while retVal.find(" ") != -1:
retVal = retVal.replace(" ", " ")
+
return retVal
def getPageTextWordsSet(page):
retVal = None
+
if isinstance(page, basestring):
page = getFilteredPageContent(page)
retVal = set(re.findall(r"\w+", page))
+
return retVal
def showStaticWords(firstPage, secondPage):
infoMsg = "finding static words in longest matching part of dynamic page content"
logger.info(infoMsg)
+
firstPage = getFilteredPageContent(firstPage)
secondPage = getFilteredPageContent(secondPage)
match = SequenceMatcher(None, firstPage, secondPage).find_longest_match(0, len(firstPage), 0, len(secondPage))
commonText = firstPage[match[0]:match[0]+match[2]]
commonWords = getPageTextWordsSet(commonText)
+
infoMsg = "static words: "
if commonWords:
@@ -1190,6 +1199,7 @@ def posixToNtSlashes(filepath):
>>> posixToNtSlashes('C:/Windows')
'C:\\\\Windows'
"""
+
return filepath.replace('/', '\\')
def ntToPosixSlashes(filepath):
@@ -1199,6 +1209,7 @@ def ntToPosixSlashes(filepath):
>>> ntToPosixSlashes('C:\\Windows')
'C:/Windows'
"""
+
return filepath.replace('\\', '/')
def isBase64EncodedString(subject):
@@ -1209,6 +1220,7 @@ def isBase64EncodedString(subject):
>>> isBase64EncodedString('123456')
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
def isHexEncodedString(subject):
@@ -1219,6 +1231,7 @@ def isHexEncodedString(subject):
>>> isHexEncodedString('test')
False
"""
+
return re.match(r"\A[0-9a-fA-F]+\Z", subject) is not None
def getConsoleWidth(default=80):
@@ -1229,12 +1242,14 @@ def getConsoleWidth(default=80):
else:
output=subprocess.Popen('stty size', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read()
items = output.split()
+
if len(items) == 2 and items[1].isdigit():
width = int(items[1])
if width is None:
try:
import curses
+
stdscr = curses.initscr()
_, width = stdscr.getmaxyx()
curses.endwin()
@@ -1268,10 +1283,13 @@ def calculateDeltaSeconds(start, epsilon=0.05):
def getInjectionCase(name):
retVal = None
+
for case in kb.injections.root.case:
if case.name == name:
retVal = case
+
break
+
return retVal
def initCommonOutputs():
@@ -1302,9 +1320,9 @@ def getFileItems(filename):
retVal = []
checkFile(filename)
- file = codecs.open(filename, 'r', conf.dataEncoding)
+ ifile = codecs.open(filename, 'r', conf.dataEncoding)
- for line in file.readlines(): # xreadlines doesn't return unicode strings when codec.open() is used
+ for line in ifile.readlines(): # xreadlines doesn't return unicode strings when codec.open() is used
if line.find('#') != -1:
line = line[:line.find('#')]
line = line.strip()