implementation of switch --hex for 4 major DBMSes

This commit is contained in:
Miroslav Stampar 2012-02-21 11:44:48 +00:00
parent 77723a7aee
commit bcf3255fe1
7 changed files with 108 additions and 53 deletions

View File

@ -17,6 +17,7 @@ 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
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.common import singleTimeWarnMessage
from lib.core.convert import urlencode from lib.core.convert import urlencode
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
@ -286,11 +287,22 @@ class Agent:
if field.startswith("(CASE") or field.startswith("(IIF"): if field.startswith("(CASE") or field.startswith("(IIF"):
nulledCastedField = field nulledCastedField = field
else: else:
nulledCastedField = queries[Backend.getIdentifiedDbms()].cast.query % field _ = queries[Backend.getIdentifiedDbms()]
nulledCastedField = _.cast.query % field
if Backend.isDbms(DBMS.ACCESS): if Backend.isDbms(DBMS.ACCESS):
nulledCastedField = queries[Backend.getIdentifiedDbms()].isnull.query % (nulledCastedField, nulledCastedField) nulledCastedField = _.isnull.query % (nulledCastedField, nulledCastedField)
else: else:
nulledCastedField = queries[Backend.getIdentifiedDbms()].isnull.query % nulledCastedField nulledCastedField = _.isnull.query % nulledCastedField
if conf.hexConvert:
if 'hex' in _:
nulledCastedField = _.hex.query % nulledCastedField
else:
warnMsg = "switch '--hex' is currently not supported on DBMS '%s'. " % Backend.getIdentifiedDbms()
warnMsg += "Going to switch it off"
singleTimeWarnMessage(warnMsg)
conf.hexConvert = False
return nulledCastedField return nulledCastedField

View File

@ -1234,6 +1234,7 @@ def parseUnionPage(output, unique=True):
for entry in output: for entry in output:
entry = entry.group(1) entry = entry.group(1)
entry = decodeHexValue(entry) if conf.hexConvert else entry
if unique: if unique:
key = entry.lower() key = entry.lower()
@ -3098,35 +3099,63 @@ def getCounter(technique):
return kb.counters.get(technique, 0) return kb.counters.get(technique, 0)
def applyFunctionRecursively(value, function):
"""
Applies function recursively through list-like structures
"""
if isinstance(value, (list, tuple, set, BigArray)):
retVal = [applyFunctionRecursively(_, function) for _ in value]
else:
retVal = function(value)
return retVal
def decodeHexValue(value):
"""
Returns value decoded from DBMS specific hexadecimal representation
"""
def _(value):
if isinstance(value, basestring) and len(value) % 2 == 0:
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ORACLE, DBMS.PGSQL):
value = value.decode("hex")
elif Backend.isDbms(DBMS.MSSQL):
value = value[2:].decode("hex")
if value[1] == '\x00':
value = value.decode("utf16")
return value
return applyFunctionRecursively(value, _)
def extractExpectedValue(value, expected): def extractExpectedValue(value, expected):
""" """
Extracts and returns expected value by a given type Extracts and returns expected value by a given type
""" """
if not expected: if expected:
return value value = unArrayizeValue(value)
value = unArrayizeValue(value) if isNoneValue(value):
value = None
elif expected == EXPECTED.BOOL:
if isinstance(value, int):
value = bool(value)
elif isinstance(value, basestring):
value = value.strip().lower()
if value in ("true", "false"):
value = value == "true"
elif value in ("1", "-1"):
value = True
elif value == "0":
value = False
else:
value = None
elif expected == EXPECTED.INT:
if isinstance(value, basestring):
if value.isdigit():
value = int(value)
else:
value = None
if isNoneValue(value):
value = None
elif expected == EXPECTED.BOOL:
if isinstance(value, int):
value = bool(value)
elif isinstance(value, basestring):
value = value.strip().lower()
if value in ("true", "false"):
value = value == "true"
elif value in ("1", "-1"):
value = True
elif value == "0":
value = False
else:
value = None
elif expected == EXPECTED.INT:
if isinstance(value, basestring):
if value.isdigit():
value = int(value)
else:
value = None
return value return value

View File

@ -170,6 +170,7 @@ optDict = {
"flushSession": "boolean", "flushSession": "boolean",
"forms": "boolean", "forms": "boolean",
"freshQueries": "boolean", "freshQueries": "boolean",
"hexConvert": "boolean",
"parseErrors": "boolean", "parseErrors": "boolean",
"replicate": "boolean", "replicate": "boolean",
"updateAll": "boolean", "updateAll": "boolean",

View File

@ -522,6 +522,10 @@ def cmdLineParser():
action="store_true", action="store_true",
help="Ignores query results stored in session file") help="Ignores query results stored in session file")
general.add_option("--hex", dest="hexConvert",
action="store_true",
help="Uses DBMS hex conversion function(s) for data retrieval")
general.add_option("--parse-errors", dest="parseErrors", general.add_option("--parse-errors", dest="parseErrors",
action="store_true", action="store_true",
help="Parse and display DBMS error messages from responses") help="Parse and display DBMS error messages from responses")

View File

@ -14,6 +14,7 @@ import traceback
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import Backend from lib.core.common import Backend
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import decodeHexValue
from lib.core.common import decodeIntToUnicode from lib.core.common import decodeIntToUnicode
from lib.core.common import filterControlChars from lib.core.common import filterControlChars
from lib.core.common import getCharset from lib.core.common import getCharset
@ -520,6 +521,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
logger.info(infoMsg) logger.info(infoMsg)
if finalValue is not None: if finalValue is not None:
finalValue = decodeHexValue(finalValue) if conf.hexConvert else finalValue
conf.hashDB.write(expression, finalValue) conf.hashDB.write(expression, finalValue)
else: else:
conf.hashDB.write(expression, "%s%s" % (PARTIAL_VALUE_MARKER, partialValue)) conf.hashDB.write(expression, "%s%s" % (PARTIAL_VALUE_MARKER, partialValue))

View File

@ -16,6 +16,7 @@ from lib.core.bigarray import BigArray
from lib.core.common import Backend from lib.core.common import Backend
from lib.core.common import calculateDeltaSeconds from lib.core.common import calculateDeltaSeconds
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import decodeHexValue
from lib.core.common import extractRegexResult from lib.core.common import extractRegexResult
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import incrementCounter from lib.core.common import incrementCounter
@ -123,6 +124,8 @@ def __oneShotErrorUse(expression, field):
retVal = output retVal = output
break break
retVal = decodeHexValue(retVal) if conf.hexConvert else retVal
if isinstance(retVal, basestring): if isinstance(retVal, basestring):
retVal = htmlunescape(retVal).replace("<br>", "\n") retVal = htmlunescape(retVal).replace("<br>", "\n")

View File

@ -102,7 +102,7 @@ proxy =
# Syntax: username:password # Syntax: username:password
pCred = pCred =
# Ignore system default HTTP proxy # Ignore system default HTTP proxy.
# Valid: True or False # Valid: True or False
ignoreProxy = False ignoreProxy = False
@ -121,21 +121,21 @@ timeout = 30
# Default: 3 # Default: 3
retries = 3 retries = 3
# Regular expression for filtering targets from provided Burp # Regular expression for filtering targets from provided Burp.
# or WebScarab proxy log. # or WebScarab proxy log.
# Example: (google|yahoo) # Example: (google|yahoo)
scope = scope =
# Url address to visit frequently during testing # Url address to visit frequently during testing.
# Example: http://192.168.1.121/index.html # Example: http://192.168.1.121/index.html
safUrl = safUrl =
# Test requests between two visits to a given safe url (default 0) # Test requests between two visits to a given safe url (default 0).
# Valid: integer # Valid: integer
# Default: 0 # Default: 0
saFreq = 0 saFreq = 0
# Evaluate provided Python code before the request # Evaluate provided Python code before the request.
# Example: import hashlib;id2=hashlib.md5(id).hexdigest() # Example: import hashlib;id2=hashlib.md5(id).hexdigest()
evalCode = evalCode =
@ -188,20 +188,20 @@ dbms =
# Valid: linux, windows # Valid: linux, windows
os = os =
# Injection payload prefix string # Injection payload prefix string.
prefix = prefix =
# Injection payload suffix string # Injection payload suffix string.
suffix = suffix =
# Use logic operation(s) instead of negating values # Use logic operation(s) instead of negating values.
# Valid: True or False # Valid: True or False
logicNegative = False logicNegative = False
# Skip testing for given parameter(s) # Skip testing for given parameter(s).
skip = skip =
# Use given script(s) for tampering injection data # Use given script(s) for tampering injection data.
tamper = tamper =
@ -209,14 +209,14 @@ tamper =
# content from HTTP responses when using blind SQL injection technique. # content from HTTP responses when using blind SQL injection technique.
[Detection] [Detection]
# Level of tests to perform # Level of tests to perform.
# The higher the value is, the higher the number of HTTP(s) requests are # The higher the value is, the higher the number of HTTP(s) requests are
# as well as the better chances to detect a tricky SQL injection. # as well as the better chances to detect a tricky SQL injection.
# Valid: Integer between 1 and 5 # Valid: Integer between 1 and 5
# Default: 1 # Default: 1
level = 1 level = 1
# Risk of tests to perform # Risk of tests to perform.
# Note: boolean-based blind SQL injection tests with AND are considered # Note: boolean-based blind SQL injection tests with AND are considered
# risk 1, with OR are considered risk 3. # risk 1, with OR are considered risk 3.
# Valid: Integer between 0 and 3 # Valid: Integer between 0 and 3
@ -236,17 +236,17 @@ string =
# (http://www.python.org/doc/2.5.2/lib/re-syntax.html) # (http://www.python.org/doc/2.5.2/lib/re-syntax.html)
regexp = regexp =
# HTTP response code to match when the query is valid # HTTP response code to match when the query is valid.
# Valid: Integer # Valid: Integer
# Example: 200 (assuming any False statement returns a different response # Example: 200 (assuming any False statement returns a different response
# code) # code)
# code = # code =
# Compare pages based only on the textual content # Compare pages based only on the textual content.
# Valid: True or False # Valid: True or False
textOnly = False textOnly = False
# Compare pages based only on their titles # Compare pages based only on their titles.
# Valid: True or False # Valid: True or False
titles = False titles = False
@ -497,28 +497,28 @@ tmpPath =
# system Windows registry. # system Windows registry.
[Windows] [Windows]
# Read a Windows registry key value # Read a Windows registry key value.
# Valid: True or False # Valid: True or False
regRead = False regRead = False
# Write a Windows registry key value data # Write a Windows registry key value data.
# Valid: True or False # Valid: True or False
regAdd = False regAdd = False
# Delete a Windows registry key value # Delete a Windows registry key value.
# Valid: True or False # Valid: True or False
regDel = False regDel = False
# Windows registry key # Windows registry key.
regKey = regKey =
# Windows registry key value # Windows registry key value.
regVal = regVal =
# Windows registry key value data # Windows registry key value data.
regData = regData =
# Windows registry key value type # Windows registry key value type.
regType = regType =
@ -538,11 +538,11 @@ batch = False
# Force character encoding used for data retrieval. # Force character encoding used for data retrieval.
charset = charset =
# Check to see if Tor is used properly # Check to see if Tor is used properly.
# Valid: True or False # Valid: True or False
checkTor = False checkTor = False
# Crawl the website starting from the target url # Crawl the website starting from the target url.
# Valid: integer # Valid: integer
# Default: 0 # Default: 0
crawlDepth = 0 crawlDepth = 0
@ -560,7 +560,7 @@ eta = False
# Valid: True or False # Valid: True or False
flushSession = False flushSession = False
# Parse and test forms on target url # Parse and test forms on target url.
# Valid: True or False # Valid: True or False
forms = False forms = False
@ -568,6 +568,10 @@ forms = False
# Valid: True or False # Valid: True or False
freshQueries = False freshQueries = False
# Uses DBMS hex conversion function(s) for data retrieval.
# Valid: True or False
hexConvert = False
# Parse and display DBMS error messages from responses. # Parse and display DBMS error messages from responses.
# Valid: True or False # Valid: True or False
parseErrors = False parseErrors = False
@ -580,7 +584,7 @@ replicate = False
# Valid: True or False # Valid: True or False
tor = False tor = False
# Set Tor proxy port other than default # Set Tor proxy port other than default.
# Valid: integer # Valid: integer
# torPort = # torPort =