Couple of trivial updates

This commit is contained in:
Miroslav Stampar 2019-08-30 14:43:56 +02:00
parent 9eda11d081
commit f2c2864ab4
10 changed files with 39 additions and 26 deletions

View File

@ -334,6 +334,7 @@ class Agent(object):
if origValue is not None: if origValue is not None:
origValue = getUnicode(origValue) origValue = getUnicode(origValue)
if "[ORIGVALUE]" in payload: if "[ORIGVALUE]" in payload:
payload = getUnicode(payload).replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % origValue)) payload = getUnicode(payload).replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % origValue))
if "[ORIGINAL]" in payload: if "[ORIGINAL]" in payload:
@ -352,6 +353,7 @@ class Agent(object):
inferenceQuery = inference.query inferenceQuery = inference.query
payload = payload.replace(INFERENCE_MARKER, inferenceQuery) payload = payload.replace(INFERENCE_MARKER, inferenceQuery)
elif not kb.testMode: elif not kb.testMode:
errMsg = "invalid usage of inference payload without " errMsg = "invalid usage of inference payload without "
errMsg += "knowledge of underlying DBMS" errMsg += "knowledge of underlying DBMS"
@ -394,7 +396,7 @@ class Agent(object):
if "hex" in rootQuery: if "hex" in rootQuery:
hexField = rootQuery.hex.query % field hexField = rootQuery.hex.query % field
else: else:
warnMsg = "switch '--hex' is currently not supported on DBMS %s" % Backend.getIdentifiedDbms() warnMsg = "switch '--hex' is currently not supported on DBMS '%s'" % Backend.getIdentifiedDbms()
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
return hexField return hexField
@ -1008,7 +1010,7 @@ class Agent(object):
limitedQuery = "%s WHERE %s " % (limitedQuery, self.nullAndCastField(uniqueField or field)) limitedQuery = "%s WHERE %s " % (limitedQuery, self.nullAndCastField(uniqueField or field))
limitedQuery += "NOT IN (%s" % (limitStr % num) limitedQuery += "NOT IN (%s" % (limitStr % num)
limitedQuery += "%s %s ORDER BY %s) ORDER BY %s" % (self.nullAndCastField(uniqueField or field), fromFrom, uniqueField or "1", uniqueField or "1") limitedQuery += "%s %s ORDER BY %s) ORDER BY %s" % (self.nullAndCastField(uniqueField or field), fromFrom, uniqueField or '1', uniqueField or '1')
else: else:
match = re.search(r" ORDER BY (\w+)\Z", query) match = re.search(r" ORDER BY (\w+)\Z", query)
field = match.group(1) if match else field field = match.group(1) if match else field
@ -1082,7 +1084,7 @@ class Agent(object):
Removes payload delimiters from inside the input string Removes payload delimiters from inside the input string
""" """
return value.replace(PAYLOAD_DELIMITER, '') if value else value return value.replace(PAYLOAD_DELIMITER, "") if value else value
def extractPayload(self, value): def extractPayload(self, value):
""" """

View File

@ -13,6 +13,7 @@ import math
import os import os
import random import random
import sys import sys
import time
import uuid import uuid
class WichmannHill(random.Random): class WichmannHill(random.Random):
@ -40,7 +41,6 @@ class WichmannHill(random.Random):
try: try:
a = int(binascii.hexlify(os.urandom(16)), 16) a = int(binascii.hexlify(os.urandom(16)), 16)
except NotImplementedError: except NotImplementedError:
import time
a = int(time.time() * 256) # use fractional seconds a = int(time.time() * 256) # use fractional seconds
if not isinstance(a, int): if not isinstance(a, int):
@ -132,7 +132,6 @@ class WichmannHill(random.Random):
raise ValueError('seeds must be in range(0, 256)') raise ValueError('seeds must be in range(0, 256)')
if 0 == x == y == z: if 0 == x == y == z:
# Initialize from current time # Initialize from current time
import time
t = int(time.time() * 256) t = int(time.time() * 256)
t = int((t & 0xffffff) ^ (t >> 24)) t = int((t & 0xffffff) ^ (t >> 24))
t, x = divmod(t, 256) t, x = divmod(t, 256)
@ -204,6 +203,7 @@ def round(x, d=0):
else: else:
return float(math.ceil((x * p) - 0.5)) / p return float(math.ceil((x * p) - 0.5)) / p
# Reference: https://code.activestate.com/recipes/576653-convert-a-cmp-function-to-a-key-function/
def cmp_to_key(mycmp): def cmp_to_key(mycmp):
"""Convert a cmp= function into a key= function""" """Convert a cmp= function into a key= function"""
class K(object): class K(object):

View File

@ -244,8 +244,8 @@ class HASHDB_KEYS(object):
OS = "OS" OS = "OS"
class REDIRECTION(object): class REDIRECTION(object):
YES = "Y" YES = 'Y'
NO = "N" NO = 'N'
class PAYLOAD(object): class PAYLOAD(object):
SQLINJECTION = { SQLINJECTION = {

View File

@ -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.3.8.30" VERSION = "1.3.8.31"
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)
@ -333,6 +333,9 @@ BLANK = "<blank>"
# String representation for current database # String representation for current database
CURRENT_DB = "CD" CURRENT_DB = "CD"
# String representation for current user
CURRENT_USER = "CU"
# Name of SQLite file used for storing session data # Name of SQLite file used for storing session data
SESSION_SQLITE_FILE = "session.sqlite" SESSION_SQLITE_FILE = "session.sqlite"

View File

@ -227,18 +227,15 @@ class Metasploit(object):
if not choice or choice == "2": if not choice or choice == "2":
_payloadStr = "windows/meterpreter" _payloadStr = "windows/meterpreter"
break break
elif choice == "3": elif choice == "3":
_payloadStr = "windows/shell" _payloadStr = "windows/shell"
break break
elif choice == "1": elif choice == "1":
if Backend.isDbms(DBMS.PGSQL): if Backend.isDbms(DBMS.PGSQL):
logger.warn("beware that the VNC injection might not work") logger.warn("beware that the VNC injection might not work")
break break
elif Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")): elif Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")):

View File

@ -76,7 +76,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
threadData.resumed = retVal is not None and not partialValue threadData.resumed = retVal is not None and not partialValue
if any(Backend.isDbms(dbms) for dbms in (DBMS.MYSQL, DBMS.MSSQL, DBMS.ORACLE)) and kb.errorChunkLength is None and not chunkTest and not kb.testMode: if any(Backend.isDbms(dbms) for dbms in (DBMS.MYSQL, DBMS.MSSQL, DBMS.SYBASE, DBMS.ORACLE)) and kb.errorChunkLength is None and not chunkTest and not kb.testMode:
debugMsg = "searching for error chunk length..." debugMsg = "searching for error chunk length..."
logger.debug(debugMsg) logger.debug(debugMsg)
@ -117,7 +117,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
if field: if field:
nulledCastedField = agent.nullAndCastField(field) nulledCastedField = agent.nullAndCastField(field)
if any(Backend.isDbms(dbms) for dbms in (DBMS.MYSQL, DBMS.MSSQL, DBMS.ORACLE)) and not any(_ in field for _ in ("COUNT", "CASE")) and kb.errorChunkLength and not chunkTest: if any(Backend.isDbms(dbms) for dbms in (DBMS.MYSQL, DBMS.MSSQL, DBMS.SYBASE, DBMS.ORACLE)) and not any(_ in field for _ in ("COUNT", "CASE")) and kb.errorChunkLength and not chunkTest:
extendedField = re.search(r"[^ ,]*%s[^ ,]*" % re.escape(field), expression).group(0) extendedField = re.search(r"[^ ,]*%s[^ ,]*" % re.escape(field), expression).group(0)
if extendedField != field: # e.g. MIN(surname) if extendedField != field: # e.g. MIN(surname)
nulledCastedField = extendedField.replace(field, nulledCastedField) nulledCastedField = extendedField.replace(field, nulledCastedField)
@ -177,7 +177,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
else: else:
output = output.rstrip() output = output.rstrip()
if any(Backend.isDbms(dbms) for dbms in (DBMS.MYSQL, DBMS.MSSQL, DBMS.ORACLE)): if any(Backend.isDbms(dbms) for dbms in (DBMS.MYSQL, DBMS.MSSQL, DBMS.SYBASE, DBMS.ORACLE)):
if offset == 1: if offset == 1:
retVal = output retVal = output
else: else:
@ -367,7 +367,7 @@ def errorUse(expression, dump=False):
message = "due to huge table size do you want to remove " message = "due to huge table size do you want to remove "
message += "ORDER BY clause gaining speed over consistency? [y/N] " message += "ORDER BY clause gaining speed over consistency? [y/N] "
if readInput(message, default="N", boolean=True): if readInput(message, default='N', boolean=True):
expression = expression[:expression.index(" ORDER BY ")] expression = expression[:expression.index(" ORDER BY ")]
numThreads = min(conf.threads, (stopLimit - startLimit)) numThreads = min(conf.threads, (stopLimit - startLimit))

View File

@ -163,7 +163,7 @@ def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=
if retVal: if retVal:
infoMsg = "target URL appears to be UNION injectable with %d columns" % retVal infoMsg = "target URL appears to be UNION injectable with %d columns" % retVal
singleTimeLogMessage(infoMsg, logging.INFO, re.sub(r"\d+", "N", infoMsg)) singleTimeLogMessage(infoMsg, logging.INFO, re.sub(r"\d+", 'N', infoMsg))
return retVal return retVal
@ -290,7 +290,7 @@ def _unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix)
if not conf.uChar and count > 1 and kb.uChar == NULL: if not conf.uChar and count > 1 and kb.uChar == NULL:
message = "injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] " message = "injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] "
if not readInput(message, default="Y", boolean=True): if not readInput(message, default='Y', boolean=True):
warnMsg += "usage of option '--union-char' " warnMsg += "usage of option '--union-char' "
warnMsg += "(e.g. '--union-char=1') " warnMsg += "(e.g. '--union-char=1') "
else: else:

View File

@ -21,6 +21,7 @@ from lib.core.enums import DBMS
from lib.core.enums import EXPECTED from lib.core.enums import EXPECTED
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapNoneDataException
from lib.core.settings import CURRENT_USER
from lib.request import inject from lib.request import inject
from plugins.generic.enumeration import Enumeration as GenericEnumeration from plugins.generic.enumeration import Enumeration as GenericEnumeration
@ -30,7 +31,7 @@ class Enumeration(GenericEnumeration):
rootQuery = queries[DBMS.ORACLE].roles rootQuery = queries[DBMS.ORACLE].roles
if conf.user == "CU": if conf.user == CURRENT_USER:
infoMsg += " for current user" infoMsg += " for current user"
conf.user = self.getCurrentUser() conf.user = self.getCurrentUser()
@ -55,7 +56,7 @@ class Enumeration(GenericEnumeration):
values = inject.getValue(query, blind=False, time=False) values = inject.getValue(query, blind=False, time=False)
if not values and not query2: if not values and not query2:
infoMsg = "trying with table USER_ROLE_PRIVS" infoMsg = "trying with table 'USER_ROLE_PRIVS'"
logger.info(infoMsg) logger.info(infoMsg)
return self.getRoles(query2=True) return self.getRoles(query2=True)
@ -116,7 +117,7 @@ class Enumeration(GenericEnumeration):
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
if count != 0 and not query2: if count != 0 and not query2:
infoMsg = "trying with table USER_SYS_PRIVS" infoMsg = "trying with table 'USER_SYS_PRIVS'"
logger.info(infoMsg) logger.info(infoMsg)
return self.getPrivileges(query2=True) return self.getPrivileges(query2=True)

View File

@ -39,6 +39,7 @@ from lib.core.enums import EXPECTED
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapNoneDataException
from lib.core.exception import SqlmapUserQuitException from lib.core.exception import SqlmapUserQuitException
from lib.core.settings import CURRENT_USER
from lib.core.threads import getCurrentThreadData from lib.core.threads import getCurrentThreadData
from lib.request import inject from lib.request import inject
from lib.utils.hash import attackCachedUsersPasswords from lib.utils.hash import attackCachedUsersPasswords
@ -153,7 +154,7 @@ class Users(object):
rootQuery = queries[Backend.getIdentifiedDbms()].passwords rootQuery = queries[Backend.getIdentifiedDbms()].passwords
if conf.user == "CU": if conf.user == CURRENT_USER:
infoMsg += " for current user" infoMsg += " for current user"
conf.user = self.getCurrentUser() conf.user = self.getCurrentUser()
@ -362,7 +363,7 @@ class Users(object):
rootQuery = queries[Backend.getIdentifiedDbms()].privileges rootQuery = queries[Backend.getIdentifiedDbms()].privileges
if conf.user == "CU": if conf.user == CURRENT_USER:
infoMsg += " for current user" infoMsg += " for current user"
conf.user = self.getCurrentUser() conf.user = self.getCurrentUser()
@ -410,7 +411,7 @@ class Users(object):
values = inject.getValue(query, blind=False, time=False) values = inject.getValue(query, blind=False, time=False)
if not values and Backend.isDbms(DBMS.ORACLE) and not query2: if not values and Backend.isDbms(DBMS.ORACLE) and not query2:
infoMsg = "trying with table USER_SYS_PRIVS" infoMsg = "trying with table 'USER_SYS_PRIVS'"
logger.info(infoMsg) logger.info(infoMsg)
return self.getPrivileges(query2=True) return self.getPrivileges(query2=True)
@ -446,7 +447,7 @@ class Users(object):
# In MySQL < 5.0 we get Y if the privilege is # In MySQL < 5.0 we get Y if the privilege is
# True, N otherwise # True, N otherwise
elif Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: elif Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema:
if privilege.upper() == "Y": if privilege.upper() == 'Y':
privileges.add(MYSQL_PRIVS[count]) privileges.add(MYSQL_PRIVS[count])
# In Firebird we get one letter for each privilege # In Firebird we get one letter for each privilege
@ -465,7 +466,7 @@ class Users(object):
i = 1 i = 1
for priv in privs: for priv in privs:
if priv.upper() in ("Y", "G"): if priv.upper() in ('Y', 'G'):
for position, db2Priv in DB2_PRIVS.items(): for position, db2Priv in DB2_PRIVS.items():
if position == i: if position == i:
privilege += ", " + db2Priv privilege += ", " + db2Priv
@ -525,7 +526,7 @@ class Users(object):
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
if not retrievedUsers and Backend.isDbms(DBMS.ORACLE) and not query2: if not retrievedUsers and Backend.isDbms(DBMS.ORACLE) and not query2:
infoMsg = "trying with table USER_SYS_PRIVS" infoMsg = "trying with table 'USER_SYS_PRIVS'"
logger.info(infoMsg) logger.info(infoMsg)
return self.getPrivileges(query2=True) return self.getPrivileges(query2=True)

View File

@ -0,0 +1,9 @@
#!/usr/bin/env python
#
# Copyright (c) 2019 Miroslav Stampar (@stamparm), MIT
# See the file 'LICENSE' for copying permission
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
pass