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() 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:

View File

@ -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))

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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