adding support for (custom) POST injection (marking injection point with '*' in conf.data)

This commit is contained in:
Miroslav Stampar 2012-04-17 14:23:00 +00:00
parent efd27d7ade
commit 6ebb621228
6 changed files with 58 additions and 40 deletions

View File

@ -368,7 +368,7 @@ def start():
parameters = conf.parameters.keys()
# 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:
if place in parameters:

View File

@ -12,6 +12,7 @@ import re
from xml.etree import ElementTree as ET
from lib.core.common import Backend
from lib.core.common import extractRegexResult
from lib.core.common import isDBMSVersionAtLeast
from lib.core.common import isTechniqueAvailable
from lib.core.common import randomInt
@ -62,9 +63,6 @@ class Agent:
if where is None and isTechniqueAvailable(kb.technique):
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:
place = kb.injection.place
@ -81,6 +79,9 @@ class Agent:
for char in ('?', '=', ':'):
if char in origValue:
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 where == PAYLOAD.WHERE.ORIGINAL:
@ -112,7 +113,7 @@ class Agent:
child.text = self.addPayloadDelimiters(newValue)
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))
elif place in (PLACE.UA, PLACE.REFERER, PLACE.HOST):
retValue = paramString.replace(origValue, self.addPayloadDelimiters(newValue))

View File

@ -66,6 +66,7 @@ class PLACE:
UA = "User-Agent"
REFERER = "Referer"
HOST = "Host"
CUSTOM_POST = "(custom) POST"
class HTTPMETHOD:
GET = "GET"

View File

@ -1473,6 +1473,7 @@ def __setKnowledgeBaseAttributes(flushAll=True):
kb.pageTemplate = None
kb.pageTemplates = dict()
kb.previousMethod = None
kb.processUserMarks = None
kb.orderByColumns = None
kb.originalCode = None
kb.originalPage = None

View File

@ -59,16 +59,16 @@ def __setRequestParams():
conf.parameters[None] = "direct connection"
return
__testableParameters = False
testableParameters = False
# Perform checks on GET parameters
if conf.parameters.has_key(PLACE.GET) and conf.parameters[PLACE.GET]:
parameters = conf.parameters[PLACE.GET]
__paramDict = paramToDict(PLACE.GET, parameters)
paramDict = paramToDict(PLACE.GET, parameters)
if __paramDict:
conf.paramDict[PLACE.GET] = __paramDict
__testableParameters = True
if paramDict:
conf.paramDict[PLACE.GET] = paramDict
testableParameters = True
# Perform checks on POST parameters
if conf.method == HTTPMETHOD.POST and not conf.data:
@ -83,18 +83,17 @@ def __setRequestParams():
else:
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):
place = PLACE.SOAP
else:
place = PLACE.POST
conf.parameters[place] = conf.data
__paramDict = paramToDict(place, conf.data)
paramDict = paramToDict(place, conf.data)
if __paramDict:
conf.paramDict[place] = __paramDict
__testableParameters = True
if paramDict:
conf.paramDict[place] = paramDict
testableParameters = True
conf.method = HTTPMETHOD.POST
@ -109,40 +108,52 @@ def __setRequestParams():
message += "in the target url itself? [Y/n/q] "
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)
elif test[0] in ("n", "N"):
pass
kb.processUserMarks = True
elif test[0] in ("q", "Q"):
raise sqlmapUserQuitException
if CUSTOM_INJECTION_MARK_CHAR in conf.url:
conf.parameters[PLACE.URI] = conf.url
conf.paramDict[PLACE.URI] = {}
parts = conf.url.split(CUSTOM_INJECTION_MARK_CHAR)
for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data)):
if CUSTOM_INJECTION_MARK_CHAR in (value or ""):
if kb.processUserMarks is None:
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):
result = str()
if not kb.processUserMarks:
continue
for j in xrange(len(parts)):
result += parts[j]
conf.parameters[place] = value
conf.paramDict[place] = {}
parts = value.split(CUSTOM_INJECTION_MARK_CHAR)
if i == j:
result += CUSTOM_INJECTION_MARK_CHAR
for i in xrange(len(parts) - 1):
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
if conf.cookie:
conf.parameters[PLACE.COOKIE] = conf.cookie
__paramDict = paramToDict(PLACE.COOKIE, conf.cookie)
paramDict = paramToDict(PLACE.COOKIE, conf.cookie)
if __paramDict:
conf.paramDict[PLACE.COOKIE] = __paramDict
__testableParameters = True
if paramDict:
conf.paramDict[PLACE.COOKIE] = paramDict
testableParameters = True
# Perform checks on header values
if conf.httpHeaders:
@ -157,7 +168,7 @@ def __setRequestParams():
if condition:
conf.paramDict[PLACE.UA] = { PLACE.UA: headerValue }
__testableParameters = True
testableParameters = True
elif httpHeader == PLACE.REFERER:
conf.parameters[PLACE.REFERER] = urldecode(headerValue)
@ -166,7 +177,7 @@ def __setRequestParams():
if condition:
conf.paramDict[PLACE.REFERER] = { PLACE.REFERER: headerValue }
__testableParameters = True
testableParameters = True
elif httpHeader == PLACE.HOST:
conf.parameters[PLACE.HOST] = urldecode(headerValue)
@ -175,14 +186,14 @@ def __setRequestParams():
if condition:
conf.paramDict[PLACE.HOST] = { PLACE.HOST: headerValue }
__testableParameters = True
testableParameters = True
if not conf.parameters:
errMsg = "you did not provide any GET, POST and Cookie "
errMsg += "parameter, neither an User-Agent, Referer or Host header value"
raise sqlmapGenericException, errMsg
elif not __testableParameters:
elif not testableParameters:
errMsg = "all testable parameters you provided are not present "
errMsg += "within the GET, POST and Cookie parameters"
raise sqlmapGenericException, errMsg

View File

@ -51,6 +51,7 @@ from lib.core.enums import PLACE
from lib.core.enums import REDIRECTION
from lib.core.exception import sqlmapConnectionException
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_SILENT_TIMEOUT
from lib.core.settings import MAX_CONNECTION_CHUNK_SIZE
@ -557,7 +558,7 @@ class Connect:
value = urlEncodeCookieValues(value)
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
# throughly without safe chars (especially & and =)
# addendum: as we support url encoding in tampering
@ -582,6 +583,9 @@ class Connect:
if PLACE.POST in conf.parameters:
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:
post = conf.parameters[PLACE.SOAP] if place != PLACE.SOAP or not value else value