mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-02-03 05:04:11 +03:00
adding support for (custom) POST injection (marking injection point with '*' in conf.data)
This commit is contained in:
parent
efd27d7ade
commit
6ebb621228
|
@ -368,7 +368,7 @@ def start():
|
||||||
parameters = conf.parameters.keys()
|
parameters = conf.parameters.keys()
|
||||||
|
|
||||||
# Order of testing list (last to first)
|
# Order of testing list (last to first)
|
||||||
orderList = (PLACE.URI, PLACE.GET, PLACE.POST)
|
orderList = (PLACE.URI, PLACE.GET, PLACE.POST, PLACE.CUSTOM_POST)
|
||||||
|
|
||||||
for place in orderList:
|
for place in orderList:
|
||||||
if place in parameters:
|
if place in parameters:
|
||||||
|
|
|
@ -12,6 +12,7 @@ import re
|
||||||
from xml.etree import ElementTree as ET
|
from xml.etree import ElementTree as ET
|
||||||
|
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
|
from lib.core.common import extractRegexResult
|
||||||
from lib.core.common import isDBMSVersionAtLeast
|
from lib.core.common import isDBMSVersionAtLeast
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
|
@ -62,9 +63,6 @@ class Agent:
|
||||||
if where is None and isTechniqueAvailable(kb.technique):
|
if where is None and isTechniqueAvailable(kb.technique):
|
||||||
where = kb.injection.data[kb.technique].where
|
where = kb.injection.data[kb.technique].where
|
||||||
|
|
||||||
# Debug print
|
|
||||||
#print "value: %s, newValue: %s, where: %s, kb.technique: %s" % (value, newValue, where, kb.technique)
|
|
||||||
|
|
||||||
if kb.injection.place is not None:
|
if kb.injection.place is not None:
|
||||||
place = kb.injection.place
|
place = kb.injection.place
|
||||||
|
|
||||||
|
@ -81,6 +79,9 @@ class Agent:
|
||||||
for char in ('?', '=', ':'):
|
for char in ('?', '=', ':'):
|
||||||
if char in origValue:
|
if char in origValue:
|
||||||
origValue = origValue[origValue.rfind(char) + 1:]
|
origValue = origValue[origValue.rfind(char) + 1:]
|
||||||
|
elif place == PLACE.CUSTOM_POST:
|
||||||
|
origValue = origValue.split(CUSTOM_INJECTION_MARK_CHAR)[0]
|
||||||
|
origValue = extractRegexResult(r"(?s)(?P<result>(\W+\Z|\w+\Z))", origValue)
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
if where == PAYLOAD.WHERE.ORIGINAL:
|
if where == PAYLOAD.WHERE.ORIGINAL:
|
||||||
|
@ -112,7 +113,7 @@ class Agent:
|
||||||
child.text = self.addPayloadDelimiters(newValue)
|
child.text = self.addPayloadDelimiters(newValue)
|
||||||
|
|
||||||
retValue = ET.tostring(root)
|
retValue = ET.tostring(root)
|
||||||
elif place == PLACE.URI:
|
elif place in (PLACE.URI, PLACE.CUSTOM_POST):
|
||||||
retValue = paramString.replace("%s%s" % (origValue, CUSTOM_INJECTION_MARK_CHAR), self.addPayloadDelimiters(newValue))
|
retValue = 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.UA, PLACE.REFERER, PLACE.HOST):
|
||||||
retValue = paramString.replace(origValue, self.addPayloadDelimiters(newValue))
|
retValue = paramString.replace(origValue, self.addPayloadDelimiters(newValue))
|
||||||
|
|
|
@ -66,6 +66,7 @@ class PLACE:
|
||||||
UA = "User-Agent"
|
UA = "User-Agent"
|
||||||
REFERER = "Referer"
|
REFERER = "Referer"
|
||||||
HOST = "Host"
|
HOST = "Host"
|
||||||
|
CUSTOM_POST = "(custom) POST"
|
||||||
|
|
||||||
class HTTPMETHOD:
|
class HTTPMETHOD:
|
||||||
GET = "GET"
|
GET = "GET"
|
||||||
|
|
|
@ -1473,6 +1473,7 @@ def __setKnowledgeBaseAttributes(flushAll=True):
|
||||||
kb.pageTemplate = None
|
kb.pageTemplate = None
|
||||||
kb.pageTemplates = dict()
|
kb.pageTemplates = dict()
|
||||||
kb.previousMethod = None
|
kb.previousMethod = None
|
||||||
|
kb.processUserMarks = None
|
||||||
kb.orderByColumns = None
|
kb.orderByColumns = None
|
||||||
kb.originalCode = None
|
kb.originalCode = None
|
||||||
kb.originalPage = None
|
kb.originalPage = None
|
||||||
|
|
|
@ -59,16 +59,16 @@ def __setRequestParams():
|
||||||
conf.parameters[None] = "direct connection"
|
conf.parameters[None] = "direct connection"
|
||||||
return
|
return
|
||||||
|
|
||||||
__testableParameters = False
|
testableParameters = False
|
||||||
|
|
||||||
# Perform checks on GET parameters
|
# Perform checks on GET parameters
|
||||||
if conf.parameters.has_key(PLACE.GET) and conf.parameters[PLACE.GET]:
|
if conf.parameters.has_key(PLACE.GET) and conf.parameters[PLACE.GET]:
|
||||||
parameters = conf.parameters[PLACE.GET]
|
parameters = conf.parameters[PLACE.GET]
|
||||||
__paramDict = paramToDict(PLACE.GET, parameters)
|
paramDict = paramToDict(PLACE.GET, parameters)
|
||||||
|
|
||||||
if __paramDict:
|
if paramDict:
|
||||||
conf.paramDict[PLACE.GET] = __paramDict
|
conf.paramDict[PLACE.GET] = paramDict
|
||||||
__testableParameters = True
|
testableParameters = True
|
||||||
|
|
||||||
# Perform checks on POST parameters
|
# Perform checks on POST parameters
|
||||||
if conf.method == HTTPMETHOD.POST and not conf.data:
|
if conf.method == HTTPMETHOD.POST and not conf.data:
|
||||||
|
@ -83,18 +83,17 @@ def __setRequestParams():
|
||||||
else:
|
else:
|
||||||
conf.data = conf.data.replace("\n", " ")
|
conf.data = conf.data.replace("\n", " ")
|
||||||
|
|
||||||
# Check if POST data is in xml syntax
|
|
||||||
if re.match(SOAP_REGEX, conf.data, re.I | re.M):
|
if re.match(SOAP_REGEX, conf.data, re.I | re.M):
|
||||||
place = PLACE.SOAP
|
place = PLACE.SOAP
|
||||||
else:
|
else:
|
||||||
place = PLACE.POST
|
place = PLACE.POST
|
||||||
|
|
||||||
conf.parameters[place] = conf.data
|
conf.parameters[place] = conf.data
|
||||||
__paramDict = paramToDict(place, conf.data)
|
paramDict = paramToDict(place, conf.data)
|
||||||
|
|
||||||
if __paramDict:
|
if paramDict:
|
||||||
conf.paramDict[place] = __paramDict
|
conf.paramDict[place] = paramDict
|
||||||
__testableParameters = True
|
testableParameters = True
|
||||||
|
|
||||||
conf.method = HTTPMETHOD.POST
|
conf.method = HTTPMETHOD.POST
|
||||||
|
|
||||||
|
@ -109,40 +108,52 @@ def __setRequestParams():
|
||||||
message += "in the target url itself? [Y/n/q] "
|
message += "in the target url itself? [Y/n/q] "
|
||||||
test = readInput(message, default="Y")
|
test = readInput(message, default="Y")
|
||||||
|
|
||||||
if not test or test[0] in ("y", "Y"):
|
if not test or test[0] not in ("n", "N"):
|
||||||
conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR)
|
conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR)
|
||||||
elif test[0] in ("n", "N"):
|
kb.processUserMarks = True
|
||||||
pass
|
|
||||||
elif test[0] in ("q", "Q"):
|
elif test[0] in ("q", "Q"):
|
||||||
raise sqlmapUserQuitException
|
raise sqlmapUserQuitException
|
||||||
|
|
||||||
if CUSTOM_INJECTION_MARK_CHAR in conf.url:
|
for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data)):
|
||||||
conf.parameters[PLACE.URI] = conf.url
|
if CUSTOM_INJECTION_MARK_CHAR in (value or ""):
|
||||||
conf.paramDict[PLACE.URI] = {}
|
if kb.processUserMarks is None:
|
||||||
parts = conf.url.split(CUSTOM_INJECTION_MARK_CHAR)
|
message = "custom injection mark ('%s') found in " % CUSTOM_INJECTION_MARK_CHAR
|
||||||
|
message += "'%s'. Do you want to process it? [Y/n/q] " % {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data'}[place]
|
||||||
|
test = readInput(message, default="Y")
|
||||||
|
if test and test[0] in ("q", "Q"):
|
||||||
|
raise sqlmapUserQuitException
|
||||||
|
else:
|
||||||
|
kb.processUserMarks = not test or test[0] not in ("n", "N")
|
||||||
|
|
||||||
for i in xrange(len(parts)-1):
|
if not kb.processUserMarks:
|
||||||
result = str()
|
continue
|
||||||
|
|
||||||
for j in xrange(len(parts)):
|
conf.parameters[place] = value
|
||||||
result += parts[j]
|
conf.paramDict[place] = {}
|
||||||
|
parts = value.split(CUSTOM_INJECTION_MARK_CHAR)
|
||||||
|
|
||||||
if i == j:
|
for i in xrange(len(parts) - 1):
|
||||||
result += CUSTOM_INJECTION_MARK_CHAR
|
conf.paramDict[place]["#%d%s" % (i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts)))
|
||||||
|
|
||||||
conf.paramDict[PLACE.URI]["#%d%s" % (i+1, CUSTOM_INJECTION_MARK_CHAR)] = result
|
if place == PLACE.URI and PLACE.GET in conf.paramDict:
|
||||||
|
del conf.paramDict[PLACE.GET]
|
||||||
|
elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict:
|
||||||
|
del conf.paramDict[PLACE.POST]
|
||||||
|
|
||||||
conf.url = conf.url.replace(CUSTOM_INJECTION_MARK_CHAR, str())
|
testableParameters = True
|
||||||
__testableParameters = True
|
|
||||||
|
if kb.processUserMarks:
|
||||||
|
conf.url = conf.url.replace(CUSTOM_INJECTION_MARK_CHAR, "")
|
||||||
|
conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, "") if conf.data else conf.data
|
||||||
|
|
||||||
# Perform checks on Cookie parameters
|
# Perform checks on Cookie parameters
|
||||||
if conf.cookie:
|
if conf.cookie:
|
||||||
conf.parameters[PLACE.COOKIE] = conf.cookie
|
conf.parameters[PLACE.COOKIE] = conf.cookie
|
||||||
__paramDict = paramToDict(PLACE.COOKIE, conf.cookie)
|
paramDict = paramToDict(PLACE.COOKIE, conf.cookie)
|
||||||
|
|
||||||
if __paramDict:
|
if paramDict:
|
||||||
conf.paramDict[PLACE.COOKIE] = __paramDict
|
conf.paramDict[PLACE.COOKIE] = paramDict
|
||||||
__testableParameters = True
|
testableParameters = True
|
||||||
|
|
||||||
# Perform checks on header values
|
# Perform checks on header values
|
||||||
if conf.httpHeaders:
|
if conf.httpHeaders:
|
||||||
|
@ -157,7 +168,7 @@ def __setRequestParams():
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
conf.paramDict[PLACE.UA] = { PLACE.UA: headerValue }
|
conf.paramDict[PLACE.UA] = { PLACE.UA: headerValue }
|
||||||
__testableParameters = True
|
testableParameters = True
|
||||||
|
|
||||||
elif httpHeader == PLACE.REFERER:
|
elif httpHeader == PLACE.REFERER:
|
||||||
conf.parameters[PLACE.REFERER] = urldecode(headerValue)
|
conf.parameters[PLACE.REFERER] = urldecode(headerValue)
|
||||||
|
@ -166,7 +177,7 @@ def __setRequestParams():
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
conf.paramDict[PLACE.REFERER] = { PLACE.REFERER: headerValue }
|
conf.paramDict[PLACE.REFERER] = { PLACE.REFERER: headerValue }
|
||||||
__testableParameters = True
|
testableParameters = True
|
||||||
|
|
||||||
elif httpHeader == PLACE.HOST:
|
elif httpHeader == PLACE.HOST:
|
||||||
conf.parameters[PLACE.HOST] = urldecode(headerValue)
|
conf.parameters[PLACE.HOST] = urldecode(headerValue)
|
||||||
|
@ -175,14 +186,14 @@ def __setRequestParams():
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
conf.paramDict[PLACE.HOST] = { PLACE.HOST: headerValue }
|
conf.paramDict[PLACE.HOST] = { PLACE.HOST: headerValue }
|
||||||
__testableParameters = True
|
testableParameters = True
|
||||||
|
|
||||||
if not conf.parameters:
|
if not conf.parameters:
|
||||||
errMsg = "you did not provide any GET, POST and Cookie "
|
errMsg = "you did not provide any GET, POST and Cookie "
|
||||||
errMsg += "parameter, neither an User-Agent, Referer or Host header value"
|
errMsg += "parameter, neither an User-Agent, Referer or Host header value"
|
||||||
raise sqlmapGenericException, errMsg
|
raise sqlmapGenericException, errMsg
|
||||||
|
|
||||||
elif not __testableParameters:
|
elif not testableParameters:
|
||||||
errMsg = "all testable parameters you provided are not present "
|
errMsg = "all testable parameters you provided are not present "
|
||||||
errMsg += "within the GET, POST and Cookie parameters"
|
errMsg += "within the GET, POST and Cookie parameters"
|
||||||
raise sqlmapGenericException, errMsg
|
raise sqlmapGenericException, errMsg
|
||||||
|
|
|
@ -51,6 +51,7 @@ from lib.core.enums import PLACE
|
||||||
from lib.core.enums import REDIRECTION
|
from lib.core.enums import REDIRECTION
|
||||||
from lib.core.exception import sqlmapConnectionException
|
from lib.core.exception import sqlmapConnectionException
|
||||||
from lib.core.exception import sqlmapSyntaxException
|
from lib.core.exception import sqlmapSyntaxException
|
||||||
|
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
|
||||||
from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE
|
from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE
|
||||||
from lib.core.settings import HTTP_SILENT_TIMEOUT
|
from lib.core.settings import HTTP_SILENT_TIMEOUT
|
||||||
from lib.core.settings import MAX_CONNECTION_CHUNK_SIZE
|
from lib.core.settings import MAX_CONNECTION_CHUNK_SIZE
|
||||||
|
@ -557,7 +558,7 @@ class Connect:
|
||||||
value = urlEncodeCookieValues(value)
|
value = urlEncodeCookieValues(value)
|
||||||
|
|
||||||
elif place:
|
elif place:
|
||||||
if place in (PLACE.GET, PLACE.POST, PLACE.URI):
|
if place in (PLACE.GET, PLACE.POST, PLACE.URI, PLACE.CUSTOM_POST):
|
||||||
# payloads in GET and/or POST need to be urlencoded
|
# payloads in GET and/or POST need to be urlencoded
|
||||||
# throughly without safe chars (especially & and =)
|
# throughly without safe chars (especially & and =)
|
||||||
# addendum: as we support url encoding in tampering
|
# addendum: as we support url encoding in tampering
|
||||||
|
@ -582,6 +583,9 @@ class Connect:
|
||||||
if PLACE.POST in conf.parameters:
|
if PLACE.POST in conf.parameters:
|
||||||
post = conf.parameters[PLACE.POST] if place != PLACE.POST or not value else value
|
post = conf.parameters[PLACE.POST] if place != PLACE.POST or not value else value
|
||||||
|
|
||||||
|
if PLACE.CUSTOM_POST in conf.parameters:
|
||||||
|
post = conf.parameters[PLACE.CUSTOM_POST].replace(CUSTOM_INJECTION_MARK_CHAR, "") if place != PLACE.CUSTOM_POST or not value else value
|
||||||
|
|
||||||
if PLACE.SOAP in conf.parameters:
|
if PLACE.SOAP in conf.parameters:
|
||||||
post = conf.parameters[PLACE.SOAP] if place != PLACE.SOAP or not value else value
|
post = conf.parameters[PLACE.SOAP] if place != PLACE.SOAP or not value else value
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user