mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 11:03:47 +03:00
Implemented FOR JSON AUTO in MsSQL
This commit is contained in:
parent
7e483ffd7a
commit
0ff3b1ce70
|
@ -198,11 +198,11 @@
|
||||||
<blind query="SELECT TOP 1 name FROM master..sysdatabases WHERE name NOT IN (SELECT TOP %d name FROM master..sysdatabases ORDER BY name) ORDER BY name" count="SELECT LTRIM(STR(COUNT(name))) FROM master..sysdatabases"/>
|
<blind query="SELECT TOP 1 name FROM master..sysdatabases WHERE name NOT IN (SELECT TOP %d name FROM master..sysdatabases ORDER BY name) ORDER BY name" count="SELECT LTRIM(STR(COUNT(name))) FROM master..sysdatabases"/>
|
||||||
</dbs>
|
</dbs>
|
||||||
<tables>
|
<tables>
|
||||||
<inband query="SELECT %s..sysusers.name+'.'+%s..sysobjects.name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v')" query2="SELECT table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s'" query3="SELECT name FROM %s..sysobjects WHERE xtype='U'"/>
|
<inband query="SELECT %s..sysusers.name+'.'+%s..sysobjects.name AS table_name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v')" query2="SELECT table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s'" query3="SELECT name FROM %s..sysobjects WHERE xtype='U'"/>
|
||||||
<blind query="SELECT TOP 1 %s..sysusers.name+'.'+%s..sysobjects.name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v') AND %s..sysusers.name+'.'+%s..sysobjects.name NOT IN (SELECT TOP %d %s..sysusers.name+'.'+%s..sysobjects.name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v') ORDER BY %s..sysusers.name+'.'+%s..sysobjects.name) ORDER BY %s..sysusers.name+'.'+%s..sysobjects.name" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..sysobjects WHERE %s..sysobjects.xtype IN ('u','v')" query2="SELECT TOP 1 table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s' AND table_schema+'.'+table_name NOT IN (SELECT TOP %d table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s' ORDER BY table_schema+'.'+table_name) ORDER BY table_schema+'.'+table_name" count2="SELECT LTRIM(STR(COUNT(table_name))) FROM information_schema.tables WHERE table_catalog='%s'" query3="SELECT TOP 1 name FROM %s..sysobjects WHERE xtype='U' AND name NOT IN (SELECT TOP %d name FROM %s..sysobjects WHERE xtype='U' ORDER BY name) ORDER BY name" count3="SELECT COUNT(name) FROM %s..sysobjects WHERE xtype='U'"/>
|
<blind query="SELECT TOP 1 %s..sysusers.name+'.'+%s..sysobjects.name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v') AND %s..sysusers.name+'.'+%s..sysobjects.name NOT IN (SELECT TOP %d %s..sysusers.name+'.'+%s..sysobjects.name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v') ORDER BY %s..sysusers.name+'.'+%s..sysobjects.name) ORDER BY %s..sysusers.name+'.'+%s..sysobjects.name" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..sysobjects WHERE %s..sysobjects.xtype IN ('u','v')" query2="SELECT TOP 1 table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s' AND table_schema+'.'+table_name NOT IN (SELECT TOP %d table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s' ORDER BY table_schema+'.'+table_name) ORDER BY table_schema+'.'+table_name" count2="SELECT LTRIM(STR(COUNT(table_name))) FROM information_schema.tables WHERE table_catalog='%s'" query3="SELECT TOP 1 name FROM %s..sysobjects WHERE xtype='U' AND name NOT IN (SELECT TOP %d name FROM %s..sysobjects WHERE xtype='U' ORDER BY name) ORDER BY name" count3="SELECT COUNT(name) FROM %s..sysobjects WHERE xtype='U'"/>
|
||||||
</tables>
|
</tables>
|
||||||
<columns>
|
<columns>
|
||||||
<inband query="SELECT %s..syscolumns.name,TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" query2="SELECT COL_NAME(OBJECT_ID('%s.%s'),%d)" condition="[DB]..syscolumns.name"/>
|
<inband query="SELECT %s..syscolumns.name,TYPE_NAME(%s..syscolumns.xtype) AS type_name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" query2="SELECT COL_NAME(OBJECT_ID('%s.%s'),%d)" condition="[DB]..syscolumns.name"/>
|
||||||
<blind query="SELECT TOP 1 %s..syscolumns.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s' AND %s..syscolumns.name NOT IN (SELECT TOP %d %s..syscolumns.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s' ORDER BY %s..syscolumns.name) ORDER BY %s..syscolumns.name" query2="SELECT TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.name='%s' AND %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" query3="SELECT COL_NAME(OBJECT_ID('%s.%s'),%d)" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..syscolumns WHERE id=(SELECT id FROM %s..sysobjects WHERE name='%s')" condition="[DB]..syscolumns.name"/>
|
<blind query="SELECT TOP 1 %s..syscolumns.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s' AND %s..syscolumns.name NOT IN (SELECT TOP %d %s..syscolumns.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s' ORDER BY %s..syscolumns.name) ORDER BY %s..syscolumns.name" query2="SELECT TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.name='%s' AND %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" query3="SELECT COL_NAME(OBJECT_ID('%s.%s'),%d)" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..syscolumns WHERE id=(SELECT id FROM %s..sysobjects WHERE name='%s')" condition="[DB]..syscolumns.name"/>
|
||||||
</columns>
|
</columns>
|
||||||
<dump_table>
|
<dump_table>
|
||||||
|
|
|
@ -2113,7 +2113,6 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||||
kb.responseTimeMode = None
|
kb.responseTimeMode = None
|
||||||
kb.responseTimePayload = None
|
kb.responseTimePayload = None
|
||||||
kb.resumeValues = True
|
kb.resumeValues = True
|
||||||
kb.rowXmlMode = False
|
|
||||||
kb.safeCharEncode = False
|
kb.safeCharEncode = False
|
||||||
kb.safeReq = AttribDict()
|
kb.safeReq = AttribDict()
|
||||||
kb.secondReq = None
|
kb.secondReq = 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.25"
|
VERSION = "1.4.10.26"
|
||||||
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)
|
||||||
|
|
|
@ -75,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 any((kb.rowXmlMode, kb.jsonAggMode)):
|
if not 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]
|
||||||
|
@ -100,49 +100,26 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
||||||
|
|
||||||
incrementCounter(PAYLOAD.TECHNIQUE.UNION)
|
incrementCounter(PAYLOAD.TECHNIQUE.UNION)
|
||||||
|
|
||||||
if kb.rowXmlMode:
|
if kb.jsonAggMode:
|
||||||
output = extractRegexResult(r"(?P<result>(<row.+?/>)+)", page or "")
|
if Backend.isDbms(DBMS.MSSQL):
|
||||||
|
output = extractRegexResult(r"%s(?P<result>.*)%s" % (kb.chars.start, kb.chars.stop), page or "")
|
||||||
if output:
|
if output:
|
||||||
try:
|
try:
|
||||||
root = xml.etree.ElementTree.fromstring(safeStringFormat("<root>%s</root>", getBytes(output)))
|
|
||||||
retVal = ""
|
retVal = ""
|
||||||
for column in kb.dumpColumns:
|
fields = re.findall(r'"([^"]+)":', extractRegexResult(r"{(?P<result>[^}]+)}", output))
|
||||||
base64 = True
|
for row in json.loads(output):
|
||||||
for child in root:
|
retVal += "%s%s%s" % (kb.chars.start, kb.chars.delimiter.join(getUnicode(row[field] or NULL) for field in fields), kb.chars.stop)
|
||||||
value = child.attrib.get(column, "").strip()
|
|
||||||
if value and not re.match(r"\A[a-zA-Z0-9+/]+={0,2}\Z", value):
|
|
||||||
base64 = False
|
|
||||||
break
|
|
||||||
|
|
||||||
try:
|
|
||||||
decodeBase64(value)
|
|
||||||
except (binascii.Error, TypeError):
|
|
||||||
base64 = False
|
|
||||||
break
|
|
||||||
|
|
||||||
if base64:
|
|
||||||
for child in root:
|
|
||||||
child.attrib[column] = decodeBase64(child.attrib.get(column, ""), binary=False) or NULL
|
|
||||||
|
|
||||||
for child in root:
|
|
||||||
row = []
|
|
||||||
for column in kb.dumpColumns:
|
|
||||||
row.append(child.attrib.get(column, NULL))
|
|
||||||
retVal += "%s%s%s" % (kb.chars.start, kb.chars.delimiter.join(row), kb.chars.stop)
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
retVal = getUnicode(retVal)
|
retVal = getUnicode(retVal)
|
||||||
elif kb.jsonAggMode:
|
elif Backend.isDbms(DBMS.PGSQL):
|
||||||
if Backend.isDbms(DBMS.PGSQL):
|
|
||||||
output = extractRegexResult(r"(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop), page or "")
|
output = extractRegexResult(r"(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop), page or "")
|
||||||
if output:
|
if output:
|
||||||
retVal = output
|
retVal = output
|
||||||
else:
|
else:
|
||||||
output = extractRegexResult(r"(?P<result>%s.*?%s)" % (kb.chars.start, kb.chars.stop), page or "")
|
output = extractRegexResult(r"%s(?P<result>.*?)%s" % (kb.chars.start, kb.chars.stop), page or "")
|
||||||
if output:
|
if output:
|
||||||
output = output[len(kb.chars.start):-len(kb.chars.stop)]
|
|
||||||
try:
|
try:
|
||||||
retVal = ""
|
retVal = ""
|
||||||
for row in json.loads(output):
|
for row in json.loads(output):
|
||||||
|
@ -177,7 +154,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 any((kb.rowXmlMode, kb.jsonAggMode)):
|
elif not kb.jsonAggMode:
|
||||||
trimmed = _("%s(?P<result>.*?)<" % (kb.chars.start))
|
trimmed = _("%s(?P<result>.*?)<" % (kb.chars.start))
|
||||||
|
|
||||||
if trimmed:
|
if trimmed:
|
||||||
|
@ -261,7 +238,7 @@ def unionUse(expression, unpack=True, dump=False):
|
||||||
debugMsg += "it does not play well with UNION query SQL injection"
|
debugMsg += "it does not play well with UNION query SQL injection"
|
||||||
singleTimeDebugMessage(debugMsg)
|
singleTimeDebugMessage(debugMsg)
|
||||||
|
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ORACLE, DBMS.PGSQL) and expressionFields:
|
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ORACLE, DBMS.PGSQL, DBMS.MSSQL) and expressionFields:
|
||||||
match = re.search(r"SELECT\s*(.+?)\bFROM", expression, re.I)
|
match = re.search(r"SELECT\s*(.+?)\bFROM", expression, re.I)
|
||||||
if match and not (Backend.isDbms(DBMS.ORACLE) and FROM_DUMMY_TABLE[DBMS.ORACLE] in expression):
|
if match and not (Backend.isDbms(DBMS.ORACLE) and FROM_DUMMY_TABLE[DBMS.ORACLE] in expression):
|
||||||
kb.jsonAggMode = True
|
kb.jsonAggMode = True
|
||||||
|
@ -271,15 +248,11 @@ def unionUse(expression, unpack=True, dump=False):
|
||||||
query = expression.replace(expressionFields, "'%s'||JSON_ARRAYAGG(%s)||'%s'" % (kb.chars.start, ("||'%s'||" % kb.chars.delimiter).join(expressionFieldsList), kb.chars.stop), 1)
|
query = expression.replace(expressionFields, "'%s'||JSON_ARRAYAGG(%s)||'%s'" % (kb.chars.start, ("||'%s'||" % kb.chars.delimiter).join(expressionFieldsList), kb.chars.stop), 1)
|
||||||
elif Backend.isDbms(DBMS.PGSQL): # Note: ARRAY_AGG does CSV alike output, thus enclosing start/end inside each item
|
elif Backend.isDbms(DBMS.PGSQL): # Note: ARRAY_AGG does CSV alike output, thus enclosing start/end inside each item
|
||||||
query = expression.replace(expressionFields, "ARRAY_AGG('%s'||%s||'%s')::text" % (kb.chars.start, ("||'%s'||" % kb.chars.delimiter).join("COALESCE(%s::text,' ')" % field for field in expressionFieldsList), kb.chars.stop), 1)
|
query = expression.replace(expressionFields, "ARRAY_AGG('%s'||%s||'%s')::text" % (kb.chars.start, ("||'%s'||" % kb.chars.delimiter).join("COALESCE(%s::text,' ')" % field for field in expressionFieldsList), kb.chars.stop), 1)
|
||||||
|
elif Backend.isDbms(DBMS.MSSQL):
|
||||||
|
query = "'%s'+(%s FOR JSON AUTO, INCLUDE_NULL_VALUES)+'%s'" % (kb.chars.start, expression, kb.chars.stop)
|
||||||
output = _oneShotUnionUse(query, False)
|
output = _oneShotUnionUse(query, False)
|
||||||
value = parseUnionPage(output)
|
value = parseUnionPage(output)
|
||||||
kb.jsonAggMode = False
|
kb.jsonAggMode = False
|
||||||
elif Backend.isDbms(DBMS.MSSQL) and kb.dumpColumns:
|
|
||||||
kb.rowXmlMode = True
|
|
||||||
_ = "(%s FOR XML RAW, BINARY BASE64)" % expression
|
|
||||||
output = _oneShotUnionUse(_, False)
|
|
||||||
value = parseUnionPage(output)
|
|
||||||
kb.rowXmlMode = False
|
|
||||||
|
|
||||||
# We have to check if the SQL query might return multiple entries
|
# We have to check if the SQL query might return multiple entries
|
||||||
# if the technique is partial UNION query and in such case forge the
|
# if the technique is partial UNION query and in such case forge the
|
||||||
|
|
|
@ -639,18 +639,6 @@ class Databases(object):
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
values = None
|
values = None
|
||||||
if Backend.isDbms(DBMS.MSSQL) and isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
|
|
||||||
expression = query
|
|
||||||
kb.dumpColumns = []
|
|
||||||
kb.rowXmlMode = True
|
|
||||||
|
|
||||||
for column in (extractRegexResult(r"SELECT (?P<result>.+?) FROM", query) or "").split(','):
|
|
||||||
kb.dumpColumns.append(randomStr().lower())
|
|
||||||
expression = expression.replace(column, "%s AS %s" % (column, kb.dumpColumns[-1]), 1)
|
|
||||||
|
|
||||||
values = unionUse(expression)
|
|
||||||
kb.rowXmlMode = False
|
|
||||||
kb.dumpColumns = None
|
|
||||||
|
|
||||||
if values is None:
|
if values is None:
|
||||||
values = inject.getValue(query, blind=False, time=False)
|
values = inject.getValue(query, blind=False, time=False)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user