Implementation for an Issue #79

This commit is contained in:
Miroslav Stampar 2012-10-16 12:32:58 +02:00
parent 3e64ab214e
commit 2cb1b054bb
6 changed files with 55 additions and 5 deletions

View File

@ -1962,7 +1962,31 @@ def extractErrorMessage(page):
return retVal
def urldecode(value, encoding=None, unsafe="%&=", convall=False):
def findMultipartPostBoundary(post):
"""
Finds value for a boundary parameter in given multipart POST body
"""
retVal = None
done = set()
candidates = []
for match in re.finditer(r"(?m)^--(.+?)(--)?$", post or ""):
_ = match.group(1)
if _ in done:
continue
else:
candidates.append((post.count(_), _))
done.add(_)
if candidates:
candidates.sort(key=lambda _: _[0], reverse=True)
retVal = candidates[0][1]
return retVal
def urldecode(value, encoding=None, unsafe="%%&=%s" % CUSTOM_INJECTION_MARK_CHAR, convall=False):
result = None
if value:

View File

@ -197,6 +197,7 @@ SQL_STATEMENTS = {
POST_HINT_CONTENT_TYPES = {
POST_HINT.JSON: "application/json",
POST_HINT.MULTIPART: "multipart/form-data",
POST_HINT.SOAP: "application/soap+xml",
POST_HINT.XML: "application/xml"
}

View File

@ -68,6 +68,7 @@ class PLACE:
class POST_HINT:
SOAP = "SOAP"
JSON = "JSON"
MULTIPART = "MULTIPART"
XML = "XML (generic)"
class HTTPMETHOD:

View File

@ -471,8 +471,11 @@ LIMITED_ROWS_TEST_NUMBER = 15
# Regular expression for SOAP-like POST data
SOAP_RECOGNITION_REGEX = r"(?s)\A(<\?xml[^>]+>)?\s*<([^> ]+)( [^>]+)?>.+</\2.*>\s*\Z"
# Regular expressing used for detecting JSON-like POST data
# Regular expression used for detecting JSON-like POST data
JSON_RECOGNITION_REGEX = r'(?s)\A\s*\{.*"[^"]+"\s*:\s*("[^"]+"|\d+).*\}\s*\Z'
# Regular expression used for detecting multipart POST data
MULTIPART_RECOGNITION_REGEX = r"(?i)Content-Disposition:[^;]+;\s*name="
# Default POST data content-type
DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded"

View File

@ -41,6 +41,7 @@ from lib.core.option import __setAuthCred
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import HOST_ALIASES
from lib.core.settings import JSON_RECOGNITION_REGEX
from lib.core.settings import MULTIPART_RECOGNITION_REGEX
from lib.core.settings import REFERER_ALIASES
from lib.core.settings import RESULTS_FILE_FORMAT
from lib.core.settings import SOAP_RECOGNITION_REGEX
@ -95,7 +96,6 @@ def __setRequestParams():
elif test[0] not in ("n", "N"):
conf.data = re.sub(r'("[^"]+"\s*:\s*"[^"]+)"', r'\g<1>%s"' % CUSTOM_INJECTION_MARK_CHAR, conf.data)
conf.data = re.sub(r'("[^"]+"\s*:\s*)(-?\d[\d\.]*\b)', r'\g<0>%s' % CUSTOM_INJECTION_MARK_CHAR, conf.data)
kb.processUserMarks = True
kb.postHint = POST_HINT.JSON
elif re.search(SOAP_RECOGNITION_REGEX, conf.data):
@ -105,10 +105,19 @@ def __setRequestParams():
if test and test[0] in ("q", "Q"):
raise sqlmapUserQuitException
elif test[0] not in ("n", "N"):
conf.data = re.sub(r"(<([^>]+)( [^<]*)?>)([^<]+)(</\2)", r"\g<1>\g<4>*\g<5>", conf.data)
kb.processUserMarks = True
conf.data = re.sub(r"(<([^>]+)( [^<]*)?>)([^<]+)(</\2)", r"\g<1>\g<4>%s\g<5>" % CUSTOM_INJECTION_MARK_CHAR, conf.data)
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data):
message = "Multipart like data found in POST data. "
message += "Do you want to process it? [Y/n/q] "
test = readInput(message, default="Y")
if test and test[0] in ("q", "Q"):
raise sqlmapUserQuitException
elif test[0] not in ("n", "N"):
conf.data = re.sub(r"(?si)(Content-Disposition.+?)((\r)?\n--)", r"\g<1>%s\g<2>" % CUSTOM_INJECTION_MARK_CHAR, conf.data)
kb.postHint = POST_HINT.MULTIPART
else:
place = PLACE.POST
@ -119,6 +128,8 @@ def __setRequestParams():
conf.paramDict[place] = paramDict
testableParameters = True
kb.processUserMarks = True if kb.postHint else kb.processUserMarks
if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(map(lambda place: place in conf.parameters, [PLACE.GET, PLACE.POST])):
warnMsg = "you've provided target url without any GET "
warnMsg += "parameters (e.g. www.site.com/article.php?id=1) "

View File

@ -23,6 +23,7 @@ from lib.core.common import clearConsoleLine
from lib.core.common import cpuThrottle
from lib.core.common import evaluateCode
from lib.core.common import extractRegexResult
from lib.core.common import findMultipartPostBoundary
from lib.core.common import getCurrentThreadData
from lib.core.common import getHostHeader
from lib.core.common import getRequestHeader
@ -292,6 +293,15 @@ class Connect:
if post and HTTPHEADER.CONTENT_TYPE not in headers:
headers[HTTPHEADER.CONTENT_TYPE] = POST_HINT_CONTENT_TYPES.get(kb.postHint, DEFAULT_CONTENT_TYPE)
if headers[HTTPHEADER.CONTENT_TYPE] == POST_HINT_CONTENT_TYPES[POST_HINT.MULTIPART]:
warnMsg = "missing 'boundary parameter' in '%s' header. " % HTTPHEADER.CONTENT_TYPE
warnMsg += "Will try to reconstruct"
singleTimeWarnMessage(warnMsg)
boundary = findMultipartPostBoundary(conf.data)
if boundary:
headers[HTTPHEADER.CONTENT_TYPE] = "%s; boundary=%s" % (headers[HTTPHEADER.CONTENT_TYPE], boundary)
if auxHeaders:
for key, item in auxHeaders.items():
headers[key] = item