mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-01-24 16:24:25 +03:00
Implementation for an Issue #79
This commit is contained in:
parent
3e64ab214e
commit
2cb1b054bb
|
@ -1962,7 +1962,31 @@ def extractErrorMessage(page):
|
||||||
|
|
||||||
return retVal
|
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
|
result = None
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
|
|
|
@ -197,6 +197,7 @@ SQL_STATEMENTS = {
|
||||||
|
|
||||||
POST_HINT_CONTENT_TYPES = {
|
POST_HINT_CONTENT_TYPES = {
|
||||||
POST_HINT.JSON: "application/json",
|
POST_HINT.JSON: "application/json",
|
||||||
|
POST_HINT.MULTIPART: "multipart/form-data",
|
||||||
POST_HINT.SOAP: "application/soap+xml",
|
POST_HINT.SOAP: "application/soap+xml",
|
||||||
POST_HINT.XML: "application/xml"
|
POST_HINT.XML: "application/xml"
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ class PLACE:
|
||||||
class POST_HINT:
|
class POST_HINT:
|
||||||
SOAP = "SOAP"
|
SOAP = "SOAP"
|
||||||
JSON = "JSON"
|
JSON = "JSON"
|
||||||
|
MULTIPART = "MULTIPART"
|
||||||
XML = "XML (generic)"
|
XML = "XML (generic)"
|
||||||
|
|
||||||
class HTTPMETHOD:
|
class HTTPMETHOD:
|
||||||
|
|
|
@ -471,8 +471,11 @@ LIMITED_ROWS_TEST_NUMBER = 15
|
||||||
# Regular expression for SOAP-like POST data
|
# Regular expression for SOAP-like POST data
|
||||||
SOAP_RECOGNITION_REGEX = r"(?s)\A(<\?xml[^>]+>)?\s*<([^> ]+)( [^>]+)?>.+</\2.*>\s*\Z"
|
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'
|
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 POST data content-type
|
||||||
DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded"
|
DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded"
|
||||||
|
|
|
@ -41,6 +41,7 @@ from lib.core.option import __setAuthCred
|
||||||
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
|
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
|
||||||
from lib.core.settings import HOST_ALIASES
|
from lib.core.settings import HOST_ALIASES
|
||||||
from lib.core.settings import JSON_RECOGNITION_REGEX
|
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 REFERER_ALIASES
|
||||||
from lib.core.settings import RESULTS_FILE_FORMAT
|
from lib.core.settings import RESULTS_FILE_FORMAT
|
||||||
from lib.core.settings import SOAP_RECOGNITION_REGEX
|
from lib.core.settings import SOAP_RECOGNITION_REGEX
|
||||||
|
@ -95,7 +96,6 @@ def __setRequestParams():
|
||||||
elif test[0] not in ("n", "N"):
|
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*"[^"]+)"', 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)
|
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
|
kb.postHint = POST_HINT.JSON
|
||||||
|
|
||||||
elif re.search(SOAP_RECOGNITION_REGEX, conf.data):
|
elif re.search(SOAP_RECOGNITION_REGEX, conf.data):
|
||||||
|
@ -105,10 +105,19 @@ def __setRequestParams():
|
||||||
if test and test[0] in ("q", "Q"):
|
if test and test[0] in ("q", "Q"):
|
||||||
raise sqlmapUserQuitException
|
raise sqlmapUserQuitException
|
||||||
elif test[0] not in ("n", "N"):
|
elif test[0] not in ("n", "N"):
|
||||||
conf.data = re.sub(r"(<([^>]+)( [^<]*)?>)([^<]+)(</\2)", r"\g<1>\g<4>*\g<5>", conf.data)
|
conf.data = re.sub(r"(<([^>]+)( [^<]*)?>)([^<]+)(</\2)", r"\g<1>\g<4>%s\g<5>" % CUSTOM_INJECTION_MARK_CHAR, conf.data)
|
||||||
kb.processUserMarks = True
|
|
||||||
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
|
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:
|
else:
|
||||||
place = PLACE.POST
|
place = PLACE.POST
|
||||||
|
|
||||||
|
@ -119,6 +128,8 @@ def __setRequestParams():
|
||||||
conf.paramDict[place] = paramDict
|
conf.paramDict[place] = paramDict
|
||||||
testableParameters = True
|
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])):
|
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 = "you've provided target url without any GET "
|
||||||
warnMsg += "parameters (e.g. www.site.com/article.php?id=1) "
|
warnMsg += "parameters (e.g. www.site.com/article.php?id=1) "
|
||||||
|
|
|
@ -23,6 +23,7 @@ from lib.core.common import clearConsoleLine
|
||||||
from lib.core.common import cpuThrottle
|
from lib.core.common import cpuThrottle
|
||||||
from lib.core.common import evaluateCode
|
from lib.core.common import evaluateCode
|
||||||
from lib.core.common import extractRegexResult
|
from lib.core.common import extractRegexResult
|
||||||
|
from lib.core.common import findMultipartPostBoundary
|
||||||
from lib.core.common import getCurrentThreadData
|
from lib.core.common import getCurrentThreadData
|
||||||
from lib.core.common import getHostHeader
|
from lib.core.common import getHostHeader
|
||||||
from lib.core.common import getRequestHeader
|
from lib.core.common import getRequestHeader
|
||||||
|
@ -292,6 +293,15 @@ class Connect:
|
||||||
if post and HTTPHEADER.CONTENT_TYPE not in headers:
|
if post and HTTPHEADER.CONTENT_TYPE not in headers:
|
||||||
headers[HTTPHEADER.CONTENT_TYPE] = POST_HINT_CONTENT_TYPES.get(kb.postHint, DEFAULT_CONTENT_TYPE)
|
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:
|
if auxHeaders:
|
||||||
for key, item in auxHeaders.items():
|
for key, item in auxHeaders.items():
|
||||||
headers[key] = item
|
headers[key] = item
|
||||||
|
|
Loading…
Reference in New Issue
Block a user