mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 11:03:47 +03:00
Implements #4403
This commit is contained in:
parent
673a5afe07
commit
585645e806
|
@ -2058,6 +2058,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||||
kb.identifiedWafs = set()
|
kb.identifiedWafs = set()
|
||||||
kb.injection = InjectionDict()
|
kb.injection = InjectionDict()
|
||||||
kb.injections = []
|
kb.injections = []
|
||||||
|
kb.jsonAggMode = False
|
||||||
kb.laggingChecked = False
|
kb.laggingChecked = False
|
||||||
kb.lastParserStatus = None
|
kb.lastParserStatus = None
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ from lib.core.enums import OS
|
||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.4.10.19"
|
VERSION = "1.4.10.20"
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||||
|
|
|
@ -6,6 +6,7 @@ See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import binascii
|
import binascii
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import xml.etree.ElementTree
|
import xml.etree.ElementTree
|
||||||
|
@ -74,7 +75,7 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
||||||
if retVal is None:
|
if retVal is None:
|
||||||
vector = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector
|
vector = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector
|
||||||
|
|
||||||
if not kb.rowXmlMode:
|
if not any((kb.rowXmlMode, kb.jsonAggMode)):
|
||||||
injExpression = unescaper.escape(agent.concatQuery(expression, unpack))
|
injExpression = unescaper.escape(agent.concatQuery(expression, unpack))
|
||||||
kb.unionDuplicates = vector[7]
|
kb.unionDuplicates = vector[7]
|
||||||
kb.forcePartialUnion = vector[8]
|
kb.forcePartialUnion = vector[8]
|
||||||
|
@ -99,24 +100,8 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
||||||
|
|
||||||
incrementCounter(PAYLOAD.TECHNIQUE.UNION)
|
incrementCounter(PAYLOAD.TECHNIQUE.UNION)
|
||||||
|
|
||||||
if not kb.rowXmlMode:
|
if kb.rowXmlMode:
|
||||||
# Parse the returned page to get the exact UNION-based
|
output = extractRegexResult(r"(?P<result>(<row.+?/>)+)", page or "")
|
||||||
# SQL injection output
|
|
||||||
def _(regex):
|
|
||||||
return firstNotNone(
|
|
||||||
extractRegexResult(regex, removeReflectiveValues(page, payload), re.DOTALL | re.IGNORECASE),
|
|
||||||
extractRegexResult(regex, removeReflectiveValues(listToStrValue((_ for _ in headers.headers if not _.startswith(HTTP_HEADER.URI)) if headers else None), payload, True), re.DOTALL | re.IGNORECASE)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Automatically patching last char trimming cases
|
|
||||||
if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""):
|
|
||||||
warnMsg = "automatically patching output having last char trimmed"
|
|
||||||
singleTimeWarnMessage(warnMsg)
|
|
||||||
page = page.replace(kb.chars.stop[:-1], kb.chars.stop)
|
|
||||||
|
|
||||||
retVal = _("(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop))
|
|
||||||
else:
|
|
||||||
output = extractRegexResult(r"(?P<result>(<row.+?/>)+)", page)
|
|
||||||
if output:
|
if output:
|
||||||
try:
|
try:
|
||||||
root = xml.etree.ElementTree.fromstring(safeStringFormat("<root>%s</root>", getBytes(output)))
|
root = xml.etree.ElementTree.fromstring(safeStringFormat("<root>%s</root>", getBytes(output)))
|
||||||
|
@ -149,6 +134,28 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
retVal = getUnicode(retVal)
|
retVal = getUnicode(retVal)
|
||||||
|
elif kb.jsonAggMode:
|
||||||
|
output = extractRegexResult(r"(?P<result>%s.*?%s)" % (kb.chars.start, kb.chars.stop), page or "")
|
||||||
|
if output:
|
||||||
|
retVal = ""
|
||||||
|
for row in json.loads(output[len(kb.chars.start):-len(kb.chars.stop)]):
|
||||||
|
retVal += "%s%s%s" % (kb.chars.start, row, kb.chars.stop)
|
||||||
|
else:
|
||||||
|
# Parse the returned page to get the exact UNION-based
|
||||||
|
# SQL injection output
|
||||||
|
def _(regex):
|
||||||
|
return firstNotNone(
|
||||||
|
extractRegexResult(regex, removeReflectiveValues(page, payload), re.DOTALL | re.IGNORECASE),
|
||||||
|
extractRegexResult(regex, removeReflectiveValues(listToStrValue((_ for _ in headers.headers if not _.startswith(HTTP_HEADER.URI)) if headers else None), payload, True), re.DOTALL | re.IGNORECASE)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Automatically patching last char trimming cases
|
||||||
|
if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""):
|
||||||
|
warnMsg = "automatically patching output having last char trimmed"
|
||||||
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
page = page.replace(kb.chars.stop[:-1], kb.chars.stop)
|
||||||
|
|
||||||
|
retVal = _("(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop))
|
||||||
|
|
||||||
if retVal is not None:
|
if retVal is not None:
|
||||||
retVal = getUnicode(retVal, kb.pageEncoding)
|
retVal = getUnicode(retVal, kb.pageEncoding)
|
||||||
|
@ -159,7 +166,7 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
||||||
|
|
||||||
hashDBWrite("%s%s" % (conf.hexConvert or False, expression), retVal)
|
hashDBWrite("%s%s" % (conf.hexConvert or False, expression), retVal)
|
||||||
|
|
||||||
elif not kb.rowXmlMode:
|
elif not any((kb.rowXmlMode, kb.jsonAggMode)):
|
||||||
trimmed = _("%s(?P<result>.*?)<" % (kb.chars.start))
|
trimmed = _("%s(?P<result>.*?)<" % (kb.chars.start))
|
||||||
|
|
||||||
if trimmed:
|
if trimmed:
|
||||||
|
@ -236,7 +243,15 @@ def unionUse(expression, unpack=True, dump=False):
|
||||||
# Set kb.partRun in case the engine is called from the API
|
# Set kb.partRun in case the engine is called from the API
|
||||||
kb.partRun = getPartRun(alias=False) if conf.api else None
|
kb.partRun = getPartRun(alias=False) if conf.api else None
|
||||||
|
|
||||||
if Backend.isDbms(DBMS.MSSQL) and kb.dumpColumns:
|
if Backend.isDbms(DBMS.MYSQL) and expressionFields:
|
||||||
|
match = re.search(r"SELECT\s*(.+?)\bFROM", expression, re.I)
|
||||||
|
if match:
|
||||||
|
kb.jsonAggMode = True
|
||||||
|
_ = expression.replace(expressionFields, "CONCAT('%s',JSON_ARRAYAGG(CONCAT_WS('%s',%s)),'%s')" % (kb.chars.start, kb.chars.delimiter, expressionFields, kb.chars.stop), 1)
|
||||||
|
output = _oneShotUnionUse(_, False)
|
||||||
|
value = parseUnionPage(output)
|
||||||
|
kb.jsonAggMode = False
|
||||||
|
elif Backend.isDbms(DBMS.MSSQL) and kb.dumpColumns:
|
||||||
kb.rowXmlMode = True
|
kb.rowXmlMode = True
|
||||||
_ = "(%s FOR XML RAW, BINARY BASE64)" % expression
|
_ = "(%s FOR XML RAW, BINARY BASE64)" % expression
|
||||||
output = _oneShotUnionUse(_, False)
|
output = _oneShotUnionUse(_, False)
|
||||||
|
|
|
@ -159,7 +159,7 @@ class Entries(object):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
kb.dumpColumns = [unsafeSQLIdentificatorNaming(_) for _ in colList]
|
kb.dumpColumns = [unsafeSQLIdentificatorNaming(_) for _ in colList]
|
||||||
colNames = colString = ", ".join(column for column in colList)
|
colNames = colString = ','.join(column for column in colList)
|
||||||
rootQuery = queries[Backend.getIdentifiedDbms()].dump_table
|
rootQuery = queries[Backend.getIdentifiedDbms()].dump_table
|
||||||
|
|
||||||
infoMsg = "fetching entries"
|
infoMsg = "fetching entries"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user