From 47073f4afd9a1d526288069183b1d8e3f8f6a8ae Mon Sep 17 00:00:00 2001
From: Miroslav Stampar <miroslav.stampar@gmail.com>
Date: Mon, 30 Jul 2012 21:50:46 +0200
Subject: [PATCH] Implementation of an Issue #131

---
 lib/parse/cmdline.py       |  3 +++
 lib/request/inject.py      | 33 +++++++++++++++++----------------
 lib/techniques/dns/test.py | 12 ++++++++----
 3 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py
index 82c5e7cc0..51b3c11a7 100644
--- a/lib/parse/cmdline.py
+++ b/lib/parse/cmdline.py
@@ -655,6 +655,9 @@ def cmdLineParser():
         parser.add_option("--cpu-throttle", dest="cpuThrottle", type="int",
                           help=SUPPRESS_HELP)
 
+        parser.add_option("--force-dns", dest="forceDns", action="store_true",
+                          help=SUPPRESS_HELP)
+
         parser.add_option("--smoke-test", dest="smokeTest", action="store_true",
                           help=SUPPRESS_HELP)
 
diff --git a/lib/request/inject.py b/lib/request/inject.py
index 1215d75a9..0f1e423d0 100644
--- a/lib/request/inject.py
+++ b/lib/request/inject.py
@@ -395,24 +395,25 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
             if query and not 'COUNT(*)' in query:
                 query = query.replace("DISTINCT ", "")
 
-            if inband and isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
-                kb.technique = PAYLOAD.TECHNIQUE.UNION
-                value = __goInband(forgeCaseExpression if expected == EXPECTED.BOOL else query, unpack, dump)
-                count += 1
-                found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
+            if not conf.forceDns:
+                if inband and isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
+                    kb.technique = PAYLOAD.TECHNIQUE.UNION
+                    value = __goInband(forgeCaseExpression if expected == EXPECTED.BOOL else query, unpack, dump)
+                    count += 1
+                    found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
 
-            if error and isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) and not found:
-                kb.technique = PAYLOAD.TECHNIQUE.ERROR
-                value = errorUse(forgeCaseExpression if expected == EXPECTED.BOOL else query, dump)
-                count += 1
-                found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
+                if error and isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) and not found:
+                    kb.technique = PAYLOAD.TECHNIQUE.ERROR
+                    value = errorUse(forgeCaseExpression if expected == EXPECTED.BOOL else query, dump)
+                    count += 1
+                    found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
 
-            if found and conf.dnsName:
-                _ = "".join(filter(None, (key if isTechniqueAvailable(value) else None for key, value in {"E":PAYLOAD.TECHNIQUE.ERROR, "U":PAYLOAD.TECHNIQUE.UNION}.items())))
-                warnMsg = "option '--dns-domain' will be ignored "
-                warnMsg += "as faster techniques are usable "
-                warnMsg += "(%s) " % _
-                singleTimeWarnMessage(warnMsg)
+                if found and conf.dnsName:
+                    _ = "".join(filter(None, (key if isTechniqueAvailable(value) else None for key, value in {"E":PAYLOAD.TECHNIQUE.ERROR, "U":PAYLOAD.TECHNIQUE.UNION}.items())))
+                    warnMsg = "option '--dns-domain' will be ignored "
+                    warnMsg += "as faster techniques are usable "
+                    warnMsg += "(%s) " % _
+                    singleTimeWarnMessage(warnMsg)
 
             if blind and isTechniqueAvailable(PAYLOAD.TECHNIQUE.BOOLEAN) and not found:
                 kb.technique = PAYLOAD.TECHNIQUE.BOOLEAN
diff --git a/lib/techniques/dns/test.py b/lib/techniques/dns/test.py
index a91c2dfc6..9a3f8eb1b 100644
--- a/lib/techniques/dns/test.py
+++ b/lib/techniques/dns/test.py
@@ -10,6 +10,7 @@ from lib.core.common import randomInt
 from lib.core.data import conf
 from lib.core.data import kb
 from lib.core.data import logger
+from lib.core.exception import sqlmapNotVulnerableException
 from lib.core.settings import FROM_DUMMY_TABLE
 from lib.techniques.dns.use import dnsUse
 
@@ -21,10 +22,13 @@ def dnsTest(payload):
     kb.dnsTest = dnsUse(payload, "SELECT %d%s" % (randInt, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), ""))) == str(randInt)
 
     if not kb.dnsTest:
-        errMsg = "data retrieval through DNS channel failed. Turning off DNS exfiltration support"
-        logger.error(errMsg)
-
-        conf.dnsName = None
+        errMsg = "data retrieval through DNS channel failed"
+        if not conf.forceDns:
+            conf.dnsName = None
+            errMsg += ". Turning off DNS exfiltration support"
+            logger.error(errMsg)
+        else:
+            raise sqlmapNotVulnerableException, errMsg
     else:
         infoMsg = "data retrieval through DNS channel was successful"
         logger.info(infoMsg)