Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a585239

Browse files
committed
Implements ARRAY_AGG for PostgreSQL
1 parent 73d0c67 commit a585239

2 files changed

Lines changed: 31 additions & 24 deletions

File tree

lib/core/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from thirdparty.six import unichr as _unichr
1919

2020
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
21-
VERSION = "1.4.10.23"
21+
VERSION = "1.4.10.24"
2222
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2323
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2424
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

lib/techniques/union/use.py

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,22 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
135135
else:
136136
retVal = getUnicode(retVal)
137137
elif kb.jsonAggMode:
138-
output = extractRegexResult(r"(?P<result>%s.*?%s)" % (kb.chars.start, kb.chars.stop), page or "")
139-
if output:
140-
try:
141-
retVal = ""
142-
for row in json.loads(output[len(kb.chars.start):-len(kb.chars.stop)]):
143-
retVal += "%s%s%s" % (kb.chars.start, row, kb.chars.stop)
144-
except:
145-
pass
146-
else:
147-
retVal = getUnicode(retVal)
138+
if Backend.isDbms(DBMS.PGSQL):
139+
output = extractRegexResult(r"(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop), page or "")
140+
if output:
141+
retVal = output
142+
else:
143+
output = extractRegexResult(r"(?P<result>%s.*?%s)" % (kb.chars.start, kb.chars.stop), page or "")
144+
if output:
145+
output = output[len(kb.chars.start):-len(kb.chars.stop)]
146+
try:
147+
retVal = ""
148+
for row in json.loads(output):
149+
retVal += "%s%s%s" % (kb.chars.start, row, kb.chars.stop)
150+
except:
151+
pass
152+
else:
153+
retVal = getUnicode(retVal)
148154
else:
149155
# Parse the returned page to get the exact UNION-based
150156
# SQL injection output
@@ -248,16 +254,24 @@ def unionUse(expression, unpack=True, dump=False):
248254
# Set kb.partRun in case the engine is called from the API
249255
kb.partRun = getPartRun(alias=False) if conf.api else None
250256

251-
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ORACLE) and expressionFields:
257+
if expressionFieldsList and len(expressionFieldsList) > 1 and "ORDER BY" in expression.upper():
258+
# Removed ORDER BY clause because UNION does not play well with it
259+
expression = re.sub(r"(?i)\s*ORDER BY\s+[\w,]+", "", expression)
260+
debugMsg = "stripping ORDER BY clause from statement because "
261+
debugMsg += "it does not play well with UNION query SQL injection"
262+
singleTimeDebugMessage(debugMsg)
263+
264+
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ORACLE, DBMS.PGSQL) and expressionFields:
252265
match = re.search(r"SELECT\s*(.+?)\bFROM", expression, re.I)
253266
if match and not (Backend.isDbms(DBMS.ORACLE) and FROM_DUMMY_TABLE[DBMS.ORACLE] in expression):
254267
kb.jsonAggMode = True
255268
if Backend.isDbms(DBMS.MYSQL):
256-
_ = expression.replace(expressionFields, "CONCAT('%s',JSON_ARRAYAGG(CONCAT_WS('%s',%s)),'%s')" % (kb.chars.start, kb.chars.delimiter, expressionFields, kb.chars.stop), 1)
257-
else:
258-
_ = expression.replace(expressionFields, "'%s'||JSON_ARRAYAGG(%s)||'%s'" % (kb.chars.start, ("||'%s'||" % kb.chars.delimiter).join(expressionFieldsList), kb.chars.stop), 1)
259-
_ = re.sub(r"(?i)\s*ORDER BY ROWNUM", "", _)
260-
output = _oneShotUnionUse(_, False)
269+
query = expression.replace(expressionFields, "CONCAT('%s',JSON_ARRAYAGG(CONCAT_WS('%s',%s)),'%s')" % (kb.chars.start, kb.chars.delimiter, expressionFields, kb.chars.stop), 1)
270+
elif Backend.isDbms(DBMS.ORACLE):
271+
query = expression.replace(expressionFields, "'%s'||JSON_ARRAYAGG(%s)||'%s'" % (kb.chars.start, ("||'%s'||" % kb.chars.delimiter).join(expressionFieldsList), kb.chars.stop), 1)
272+
elif Backend.isDbms(DBMS.PGSQL):
273+
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)
274+
output = _oneShotUnionUse(query, False)
261275
value = parseUnionPage(output)
262276
kb.jsonAggMode = False
263277
elif Backend.isDbms(DBMS.MSSQL) and kb.dumpColumns:
@@ -267,13 +281,6 @@ def unionUse(expression, unpack=True, dump=False):
267281
value = parseUnionPage(output)
268282
kb.rowXmlMode = False
269283

270-
if expressionFieldsList and len(expressionFieldsList) > 1 and "ORDER BY" in expression.upper():
271-
# Removed ORDER BY clause because UNION does not play well with it
272-
expression = re.sub(r"(?i)\s*ORDER BY\s+[\w,]+", "", expression)
273-
debugMsg = "stripping ORDER BY clause from statement because "
274-
debugMsg += "it does not play well with UNION query SQL injection"
275-
singleTimeDebugMessage(debugMsg)
276-
277284
# We have to check if the SQL query might return multiple entries
278285
# if the technique is partial UNION query and in such case forge the
279286
# SQL limiting the query output one entry at a time

0 commit comments

Comments
 (0)