From 05a8c8d3bfa81053d629050811680aec8c2ac694 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Tue, 16 Dec 2008 21:30:24 +0000 Subject: [PATCH] Added support to test for stacked queries support and improved check for time based blind sql injection. Minor bug fix in --save option --- lib/controller/action.py | 4 ++ lib/core/option.py | 3 ++ lib/core/optiondict.py | 3 +- lib/parse/cmdline.py | 6 ++- lib/request/inject.py | 20 ++++------ lib/techniques/blind/timebased.py | 50 ++++++++++++++++++++++--- lib/techniques/outband/__init__.py | 25 +++++++++++++ lib/techniques/outband/stacked.py | 60 ++++++++++++++++++++++++++++++ sqlmap.conf | 8 +++- 9 files changed, 156 insertions(+), 23 deletions(-) create mode 100644 lib/techniques/outband/__init__.py create mode 100644 lib/techniques/outband/stacked.py diff --git a/lib/controller/action.py b/lib/controller/action.py index f2936dd53..6a139c6bb 100644 --- a/lib/controller/action.py +++ b/lib/controller/action.py @@ -33,6 +33,7 @@ from lib.core.exception import sqlmapUnsupportedDBMSException from lib.core.settings import SUPPORTED_DBMS from lib.techniques.blind.timebased import timeTest from lib.techniques.inband.union.test import unionTest +from lib.techniques.outband.stacked import stackedTest def action(): @@ -70,6 +71,9 @@ def action(): print "%s\n" % conf.dbmsHandler.getFingerprint() # Techniques options + if conf.stackedTest: + dumper.string("stacked queries support", stackedTest()) + if conf.timeTest: dumper.string("time based blind sql injection payload", timeTest()) diff --git a/lib/core/option.py b/lib/core/option.py index 4b7160cef..7d5cfbe72 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -613,6 +613,7 @@ def __setKnowledgeBaseAttributes(): kb.injType = None kb.parenthesis = None kb.resumedQueries = {} + kb.stackedTest = None kb.targetUrls = set() kb.timeTest = None kb.unionComment = "" @@ -656,6 +657,8 @@ def __saveCmdline(): elif datatype in ( "integer", "float" ): if option in ( "threads", "verbose" ): value = "1" + elif option == "timeout": + value = "10" else: value = "0" elif datatype == "string": diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index caae58f28..b5d25499b 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -45,7 +45,7 @@ optDict = { "proxy": "string", "threads": "integer", "delay": "float", - "timeout": "int", + "timeout": "float", }, "Injection": { @@ -60,6 +60,7 @@ optDict = { }, "Techniques": { + "stackedTest": "boolean", "timeTest": "boolean", "unionTest": "boolean", "unionUse": "boolean", diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 29f46d313..822dc72a3 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -153,10 +153,14 @@ def cmdLineParser(): "the affected parameter(s) rather than using " "the default blind SQL injection technique.") + techniques.add_option("--stacked-test", dest="stackedTest", + action="store_true", + help="Test for stacked queries (multiple " + "statements) support") + techniques.add_option("--time-test", dest="timeTest", action="store_true", help="Test for Time based blind SQL injection") - techniques.add_option("--union-test", dest="unionTest", action="store_true", help="Test for UNION query (inband) SQL injection") diff --git a/lib/request/inject.py b/lib/request/inject.py index 41d1b854a..ff794d91c 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -322,21 +322,15 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None) return value -def goStacked(expression, timeTest=False): +def goStacked(expression): """ TODO: write description """ - comment = queries[kb.dbms].comment - query = agent.prefixQuery("; %s" % expression) - query = agent.postfixQuery("%s; %s" % (query, comment)) - payload = agent.payload(newValue=query) + comment = queries[kb.dbms].comment + query = agent.prefixQuery("; %s" % expression) + query = agent.postfixQuery("%s;%s" % (query, comment)) + payload = agent.payload(newValue=query) + page = Request.queryPage(payload, content=True) - start = time.time() - Request.queryPage(payload) - duration = int(time.time() - start) - - if timeTest: - return (duration >= SECONDS, payload) - else: - return duration >= SECONDS + return payload, page diff --git a/lib/techniques/blind/timebased.py b/lib/techniques/blind/timebased.py index bbeaa7963..b05156b11 100644 --- a/lib/techniques/blind/timebased.py +++ b/lib/techniques/blind/timebased.py @@ -24,24 +24,62 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import time + +from lib.core.agent import agent from lib.core.data import kb from lib.core.data import logger from lib.core.data import queries from lib.core.settings import SECONDS from lib.request import inject +from lib.request.connect import Connect as Request def timeTest(): infoMsg = "testing time based blind sql injection on parameter " - infoMsg += "'%s'" % kb.injParameter + infoMsg += "'%s' with AND condition syntax" % kb.injParameter logger.info(infoMsg) - query = queries[kb.dbms].timedelay % SECONDS - timeTest = inject.goStacked(query, timeTest=True) + timeQuery = queries[kb.dbms].timedelay % SECONDS + + query = agent.prefixQuery(" AND %s" % timeQuery) + query = agent.postfixQuery(query) + payload = agent.payload(newValue=query) + start = time.time() + _ = Request.queryPage(payload) + duration = int(time.time() - start) + + if duration >= SECONDS: + infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter + infoMsg += "based blind sql injection with AND condition syntax" + logger.info(infoMsg) + + kb.timeTest = payload - if timeTest[0] == True: - kb.timeTest = timeTest[1] else: - kb.timeTest = False + warnMsg = "the parameter '%s' is not affected by a time " % kb.injParameter + warnMsg += "based blind sql injection with AND condition syntax" + logger.warn(warnMsg) + + infoMsg = "testing time based blind sql injection on parameter " + infoMsg += "'%s' with stacked query syntax" % kb.injParameter + logger.info(infoMsg) + + start = time.time() + payload, _ = inject.goStacked(timeQuery) + duration = int(time.time() - start) + + if duration >= SECONDS: + infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter + infoMsg += "based blind sql injection with stacked query syntax" + logger.info(infoMsg) + + kb.timeTest = payload + else: + warnMsg = "the parameter '%s' is not affected by a time " % kb.injParameter + warnMsg += "based blind sql injection with stacked query syntax" + logger.warn(warnMsg) + + kb.timeTest = False return kb.timeTest diff --git a/lib/techniques/outband/__init__.py b/lib/techniques/outband/__init__.py new file mode 100644 index 000000000..a6bc76923 --- /dev/null +++ b/lib/techniques/outband/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2006-2008 Bernardo Damele A. G. + and Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +with sqlmap; if not, write to the Free Software Foundation, Inc., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +pass diff --git a/lib/techniques/outband/stacked.py b/lib/techniques/outband/stacked.py new file mode 100644 index 000000000..397ca8682 --- /dev/null +++ b/lib/techniques/outband/stacked.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2006-2008 Bernardo Damele A. G. + and Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +with sqlmap; if not, write to the Free Software Foundation, Inc., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + + + +import time + +from lib.core.data import kb +from lib.core.data import logger +from lib.core.data import queries +from lib.core.settings import SECONDS +from lib.request import inject + + +def stackedTest(): + infoMsg = "testing stacked queries support on parameter " + infoMsg += "'%s'" % kb.injParameter + logger.info(infoMsg) + + query = queries[kb.dbms].timedelay % SECONDS + start = time.time() + payload, _ = inject.goStacked(query) + duration = int(time.time() - start) + + if duration >= SECONDS: + infoMsg = "the web application supports stacked queries " + infoMsg += "on parameter '%s'" % kb.injParameter + logger.info(infoMsg) + + kb.stackedTest = payload + + else: + warnMsg = "the web application does not support stacked queries " + warnMsg += "on parameter '%s'" % kb.injParameter + logger.warn(warnMsg) + + kb.stackedTest = False + + return kb.stackedTest diff --git a/sqlmap.conf b/sqlmap.conf index b9dcd7df6..73c8646da 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -3,8 +3,8 @@ # Target URL. # Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 # PHP and MySQL (local) -#url = http://127.0.0.1/sqlmap/mysql/get_int.php?id=1 -url = http://127.0.0.1/sqlmap/mysql/get_int_partialunion.php?id=1 +url = http://127.0.0.1/sqlmap/mysql/get_int.php?id=1 +#url = http://127.0.0.1/sqlmap/mysql/get_int_partialunion.php?id=1 # PHP and Oracle (local) #url = http://127.0.0.1/sqlmap/oracle/get_int.php?id=1 # PHP and PostgreSQL (local) @@ -146,6 +146,10 @@ eRegexp = [Techniques] +# Test for stacked queries (multiple statements) support. +# Valid: True or False +stackedTest = False + # Test for Time based blind SQL injection. # Valid: True or False timeTest = False