From 2463e51e737cd311e757ffc1c95076f3846eb9b1 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 20:37:20 +0000 Subject: [PATCH 01/35] added one more test case for DB2 and a few search-related cases for Oracle (issue #312) --- xml/livetests.xml | 305 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) diff --git a/xml/livetests.xml b/xml/livetests.xml index 841d2f174..8a83a5fce 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -1044,6 +1044,21 @@ + + + + + + + + + + + + + + + @@ -1671,6 +1686,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 2550bbc05e6ec549ea19c996c7b0ff93dfb8b96c Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 20:40:38 +0000 Subject: [PATCH 02/35] fix for #353 --- plugins/generic/databases.py | 4 +++- xml/queries.xml | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index 03d3e8256..8746eb23c 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -513,7 +513,7 @@ class Databases: query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): - query = rootQuery.inband.query % unsafeSQLIdentificatorNaming(tbl.upper()) + query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery elif Backend.isDbms(DBMS.MSSQL): query = rootQuery.inband.query % (conf.db, conf.db, conf.db, conf.db, @@ -526,9 +526,11 @@ class Databases: if Backend.isDbms(DBMS.MSSQL) and isNoneValue(values): index, values = 1, [] + while True: query = rootQuery.inband.query2 % (conf.db, tbl, index) value = unArrayizeValue(inject.getValue(query, blind=False, time=False)) + if isNoneValue(value) or value == " ": break else: diff --git a/xml/queries.xml b/xml/queries.xml index dce39fa72..931cc2718 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -269,8 +269,8 @@ - - + + From f3d7be9200066c37ed7746267a67baa0e7967222 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 20:44:56 +0000 Subject: [PATCH 03/35] more adjustments for #353 --- plugins/generic/databases.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index 8746eb23c..b28697060 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -513,7 +513,7 @@ class Databases: query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): - query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db)) + query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper())) query += condQuery elif Backend.isDbms(DBMS.MSSQL): query = rootQuery.inband.query % (conf.db, conf.db, conf.db, conf.db, @@ -593,7 +593,7 @@ class Databases: query += condQuery elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): - query = rootQuery.blind.count % unsafeSQLIdentificatorNaming(tbl.upper()) + query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper())) query += condQuery elif Backend.isDbms(DBMS.MSSQL): @@ -641,7 +641,7 @@ class Databases: query += condQuery field = None elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): - query = rootQuery.blind.query % unsafeSQLIdentificatorNaming(tbl.upper()) + query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper())) query += condQuery field = None elif Backend.isDbms(DBMS.MSSQL): @@ -661,7 +661,7 @@ class Databases: if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column, unsafeSQLIdentificatorNaming(conf.db)) elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): - query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column) + query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column, unsafeSQLIdentificatorNaming(conf.db.upper())) elif Backend.isDbms(DBMS.MSSQL): query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, conf.db, column, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl).split(".")[-1]) From bab94855615964fb6a8f3203c0a25843dac2a533 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 20:48:08 +0000 Subject: [PATCH 04/35] typo fix --- xml/queries.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/queries.xml b/xml/queries.xml index 931cc2718..7e69e4e5d 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -270,7 +270,7 @@ - + From d5949788579a6554f2534a9dfb1ac20913de3d6b Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 20:48:37 +0000 Subject: [PATCH 05/35] typo fix again --- xml/queries.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/queries.xml b/xml/queries.xml index 7e69e4e5d..f6ce92a99 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -270,7 +270,7 @@ - + From ebd1d3095b9c94ba62cd3a25c47ce0cbe85d6375 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 21:40:11 +0000 Subject: [PATCH 06/35] done with test cases for Oracle - issue #312 --- xml/livetests.xml | 70 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/xml/livetests.xml b/xml/livetests.xml index 8a83a5fce..f564c5d4c 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -1928,7 +1928,6 @@ - @@ -1974,7 +1973,6 @@ - @@ -2150,6 +2148,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2191,7 +2256,6 @@ - From 1ad9e26a210f59c5a3fc5206c1b3772b1f7de4b5 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 21:40:50 +0000 Subject: [PATCH 07/35] bug fix for ORDER BY users provided statements (issue #354) --- lib/core/agent.py | 4 ++-- xml/queries.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/core/agent.py b/lib/core/agent.py index d81d4be83..8ea2ceef9 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -822,8 +822,7 @@ class Agent(object): limitedQuery += " %s" % limitStr elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): - if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery: - orderBy = limitedQuery[limitedQuery.index(" ORDER BY "):] + if " ORDER BY " in limitedQuery and "SELECT " in limitedQuery: limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")] if query.startswith("SELECT "): @@ -831,6 +830,7 @@ class Agent(object): limitedQuery = "%s FROM (%s,%s" % (untilFrom, untilFrom.replace(delimiter, ','), limitStr) else: limitedQuery = "%s FROM (SELECT %s,%s" % (untilFrom, ','.join(f for f in field), limitStr) + limitedQuery = limitedQuery % fromFrom limitedQuery += "=%d" % (num + 1) diff --git a/xml/queries.xml b/xml/queries.xml index f6ce92a99..90014e7a6 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -209,7 +209,7 @@ - + From 2471f325b2af89c11294ad7c703f8aba86168025 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 21:47:25 +0000 Subject: [PATCH 08/35] minor adjustments --- xml/livetests.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xml/livetests.xml b/xml/livetests.xml index f564c5d4c..a0e1922fc 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -2156,7 +2156,7 @@ - + @@ -2167,7 +2167,7 @@ - + From b80e195c78e7ac608dec98702b6e61a3aa0bb3d0 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 22:10:10 +0000 Subject: [PATCH 09/35] bug fix for #355 --- plugins/generic/databases.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index b28697060..a54449d87 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -519,7 +519,7 @@ class Databases: query = rootQuery.inband.query % (conf.db, conf.db, conf.db, conf.db, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl).split(".")[-1]) query += condQuery.replace("[DB]", conf.db) - elif Backend.isDbms(DBMS.SQLITE): + elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD): query = rootQuery.inband.query % tbl values = inject.getValue(query, blind=False, time=False) From 1f4c6a837194738f3d96ce2ed3bfb0a97a57d81c Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 22:10:36 +0000 Subject: [PATCH 10/35] avoid blank line if password hashes have not been fetched --- lib/core/dump.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/core/dump.py b/lib/core/dump.py index b7b98818e..4b553f424 100644 --- a/lib/core/dump.py +++ b/lib/core/dump.py @@ -175,7 +175,8 @@ class Dump(object): for setting in settings: self._write(" %s: %s" % (subHeader, setting)) - self.singleString("") + if userSettings: + self.singleString("") def dbs(self, dbs): self.lister("available databases", dbs) From b176cdb578d52b94b443333bf56dbc9c7a0c9e3e Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 22:10:52 +0000 Subject: [PATCH 11/35] layout adjustment --- xml/queries.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xml/queries.xml b/xml/queries.xml index 90014e7a6..75961459d 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -359,12 +359,12 @@ + - @@ -401,16 +401,16 @@ + + - - From 4526e314856957a5b2609454ea96b95a65108160 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 22:32:58 +0000 Subject: [PATCH 12/35] bug fix for Firebird fingerprint (issue #357) --- plugins/dbms/firebird/fingerprint.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/dbms/firebird/fingerprint.py b/plugins/dbms/firebird/fingerprint.py index cf005bd9d..8d192d3cb 100644 --- a/plugins/dbms/firebird/fingerprint.py +++ b/plugins/dbms/firebird/fingerprint.py @@ -74,6 +74,7 @@ class Fingerprint(GenericFingerprint): ("1.5", ("NULLIF(%d,%d) IS NULL", "EXISTS(SELECT CURRENT_TRANSACTION FROM RDB$DATABASE)")), ("2.0", ("EXISTS(SELECT CURRENT_TIME(0) FROM RDB$DATABASE)", "BIT_LENGTH(%d)>0", "CHAR_LENGTH(%d)>0")), ("2.1", ("BIN_XOR(%d,%d)=0", "PI()>0.%d", "RAND()<1.%d", "FLOOR(1.%d)>=0")), + # TODO: add test for Firebird 2.5 ) for i in xrange(len(table)): @@ -122,7 +123,7 @@ class Fingerprint(GenericFingerprint): logger.info(infoMsg) randInt = randomInt() - result = inject.checkBooleanExpression("EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt)) + result = inject.checkBooleanExpression("(SELECT COUNT(*) FROM RDB$DATABASE WHERE %d=%d)>0" % (randInt, randInt)) if result: infoMsg = "confirming %s" % DBMS.FIREBIRD From a4b0b98f8f9ac8c000ce306da7b3994c865c9d3c Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 22:57:57 +0000 Subject: [PATCH 13/35] aligned Firebird to recent DB2 string escaping syntax fix --- plugins/dbms/firebird/syntax.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/dbms/firebird/syntax.py b/plugins/dbms/firebird/syntax.py index f0d91c78f..a77359249 100644 --- a/plugins/dbms/firebird/syntax.py +++ b/plugins/dbms/firebird/syntax.py @@ -16,6 +16,9 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): if isDBMSVersionAtLeast('2.1'): + if expression == u"'''": + return "ASCII_CHAR(%d)" % (ord("'")) + if quote: while True: index = expression.find("'") From a390c486923dff17f81584c18ec15bb073305e8c Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 23:04:01 +0000 Subject: [PATCH 14/35] code refactoring --- plugins/generic/search.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/generic/search.py b/plugins/generic/search.py index 6917b10da..238ec8471 100644 --- a/plugins/generic/search.py +++ b/plugins/generic/search.py @@ -29,6 +29,7 @@ from lib.core.enums import PAYLOAD from lib.core.exception import SqlmapMissingMandatoryOptionException from lib.core.exception import SqlmapUserQuitException from lib.core.settings import CURRENT_DB +from lib.core.settings import METADB_SUFFIX from lib.request import inject from lib.techniques.brute.use import columnExists from lib.techniques.brute.use import tableExists @@ -199,7 +200,7 @@ class Search: if isinstance(values, basestring): values = [values] for value in values: - newValues.append(["SQLite_masterdb", value]) + newValues.append(["SQLite_%s" % METADB_SUFFIX, value]) values = newValues @@ -258,7 +259,7 @@ class Search: if tblConsider == "2": continue else: - foundTbls["SQLite_masterdb"] = [] + foundTbls["SQLite_%s" % METADB_SUFFIX] = [] for db in foundTbls.keys(): db = safeSQLIdentificatorNaming(db) From 8748cceff3a9a79734f0a6ef38b426ba9f98f58c Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 23:04:28 +0000 Subject: [PATCH 15/35] no point enumerating current database for --count on some DBMSes --- plugins/generic/databases.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index a54449d87..6ec2dbfd7 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -761,7 +761,7 @@ class Databases: if not conf.db: conf.db, conf.tbl = conf.tbl.split(".") - if conf.tbl is not None and conf.db is None: + if conf.tbl is not None and conf.db is None and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD): warnMsg = "missing database parameter. sqlmap is going to " warnMsg += "use the current database to retrieve the " warnMsg += "number of entries for table '%s'" % unsafeSQLIdentificatorNaming(conf.tbl) From d1acdee9c41643bc3d461408e91690dd209e1c0a Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 23:07:16 +0000 Subject: [PATCH 16/35] fixed --count for DBMSes that are single-database --- plugins/generic/databases.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index 6ec2dbfd7..0dbb6d6f8 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -738,7 +738,11 @@ class Databases: db = db.upper() table = table.upper() - query = "SELECT %s FROM %s.%s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(db), safeSQLIdentificatorNaming(table, True)) + if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD): + query = "SELECT %s FROM %s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(table, True)) + else: + query = "SELECT %s FROM %s.%s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(db), safeSQLIdentificatorNaming(table, True)) + count = inject.getValue(query, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if isNumPosStrValue(count): From edeb181c4f408c6f4b4ee4f45a180e2465925aed Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 23:17:43 +0000 Subject: [PATCH 17/35] added first bunch of test cases for Firebird, issue #312 --- xml/livetests.xml | 213 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/xml/livetests.xml b/xml/livetests.xml index a0e1922fc..7f0388778 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -888,6 +888,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 56eaa073cecb3b57d7438dabaf58f720768b64b1 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 23:32:39 +0000 Subject: [PATCH 18/35] fixed test cases for Firebird - #312 --- lib/core/testing.py | 3 +++ xml/livetests.xml | 14 ++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/core/testing.py b/lib/core/testing.py index 376747012..2d760569b 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -275,6 +275,9 @@ def runCase(switches=None, parse=None): console = getUnicode(console, system=True) + print "result:", result + print "console:", console + if parse and retVal: with codecs.open(conf.dumper.getOutputFile(), "rb", UNICODE_ENCODING) as f: content = f.read() diff --git a/xml/livetests.xml b/xml/livetests.xml index 7f0388778..aa4177d1b 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -913,7 +913,7 @@ - + @@ -953,7 +953,7 @@ - + @@ -968,6 +968,7 @@ + @@ -992,7 +993,7 @@ - + @@ -1007,6 +1008,7 @@ + @@ -1031,7 +1033,7 @@ - + @@ -1057,7 +1059,7 @@ - + @@ -1086,7 +1088,7 @@ - + From 6be7eee8d69d50ca7c75ef62c649d964a89bc0c8 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 23:35:16 +0000 Subject: [PATCH 19/35] more fixes --- lib/core/testing.py | 3 --- xml/livetests.xml | 10 +++++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/core/testing.py b/lib/core/testing.py index 2d760569b..376747012 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -275,9 +275,6 @@ def runCase(switches=None, parse=None): console = getUnicode(console, system=True) - print "result:", result - print "console:", console - if parse and retVal: with codecs.open(conf.dumper.getOutputFile(), "rb", UNICODE_ENCODING) as f: content = f.read() diff --git a/xml/livetests.xml b/xml/livetests.xml index aa4177d1b..bbc333967 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -916,7 +916,7 @@ - + @@ -956,7 +956,7 @@ - + @@ -996,7 +996,7 @@ - + @@ -1036,7 +1036,7 @@ - + @@ -1091,7 +1091,7 @@ - + From e76213ef5dc379ade8888e8f3f1a1197effd49c1 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 23:37:13 +0000 Subject: [PATCH 20/35] more fixes --- xml/livetests.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xml/livetests.xml b/xml/livetests.xml index bbc333967..147adf4e5 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -917,7 +917,7 @@ - + @@ -957,7 +957,7 @@ - + @@ -997,7 +997,7 @@ - + @@ -1037,7 +1037,7 @@ - + @@ -1092,7 +1092,7 @@ - + From 10d86d042cdb97ceab8bde299491ffdfeaadaa9e Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 18 Jan 2013 23:46:26 +0000 Subject: [PATCH 21/35] enough.. --- xml/livetests.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/xml/livetests.xml b/xml/livetests.xml index 147adf4e5..d17a9624b 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -917,7 +917,6 @@ - @@ -957,7 +956,6 @@ - @@ -997,7 +995,6 @@ - @@ -1037,7 +1034,6 @@ - @@ -1092,7 +1088,6 @@ - From 89ddd54a75949b93fee13944792ffbc7e0229545 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 00:05:15 +0000 Subject: [PATCH 22/35] added Firebird inline query payload, requires some work though engine-side for the vector to be usable --- xml/payloads.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/xml/payloads.xml b/xml/payloads.xml index d9cb48b22..ad3c4c9e9 100644 --- a/xml/payloads.xml +++ b/xml/payloads.xml @@ -1996,6 +1996,25 @@ Formats: SQLite + + Firebird inline queries + 6 + 2 + 1 + 1,2,3,8 + 3 + + SELECT '[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]' + + SELECT '[DELIMITER_START]'||(CASE [RANDNUM] WHEN [RANDNUM] THEN 1 ELSE 0 END)||'[DELIMITER_STOP]' FROM RDB$DATABASE + + + [DELIMITER_START](?P<result>.*?)[DELIMITER_STOP] + +
+ Firebird +
+
From 32a12c7e2b4656fdf3ba1eca163a5e664c8f49be Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 00:24:15 +0000 Subject: [PATCH 23/35] handle exception reported in issue #359 --- plugins/dbms/mssqlserver/connector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/dbms/mssqlserver/connector.py b/plugins/dbms/mssqlserver/connector.py index c859f9632..7eb0a82bb 100644 --- a/plugins/dbms/mssqlserver/connector.py +++ b/plugins/dbms/mssqlserver/connector.py @@ -41,7 +41,7 @@ class Connector(GenericConnector): try: self.connector = pymssql.connect(host="%s:%d" % (self.hostname, self.port), user=self.user, password=self.password, database=self.db, login_timeout=conf.timeout, timeout=conf.timeout) - except pymssql.OperationalError, msg: + except (pymssql.InterfaceError, pymssql.OperationalError), msg: raise SqlmapConnectionException(msg) self.initCursor() From 0e78fbef563341a6b8d66d45467210b55accce2c Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 00:28:03 +0000 Subject: [PATCH 24/35] correctly format SQLi payload for inline query technique --- lib/core/agent.py | 2 +- lib/techniques/error/use.py | 5 +++++ xml/payloads.xml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/core/agent.py b/lib/core/agent.py index 8ea2ceef9..0e0770b01 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -535,7 +535,7 @@ class Agent(object): elif fieldsNoSelect: concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop) - elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2): + elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD): if fieldsExists: concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) concatenatedQuery += "||'%s'" % kb.chars.stop diff --git a/lib/techniques/error/use.py b/lib/techniques/error/use.py index d2edbb1ec..44e662043 100644 --- a/lib/techniques/error/use.py +++ b/lib/techniques/error/use.py @@ -23,6 +23,7 @@ from lib.core.common import incrementCounter from lib.core.common import initTechnique from lib.core.common import isListLike from lib.core.common import isNumPosStrValue +from lib.core.common import isTechniqueAvailable from lib.core.common import listToStrValue from lib.core.common import readInput from lib.core.common import unArrayizeValue @@ -34,6 +35,7 @@ from lib.core.data import logger from lib.core.data import queries from lib.core.dicts import FROM_DUMMY_TABLE from lib.core.enums import DBMS +from lib.core.enums import PAYLOAD from lib.core.settings import CHECK_ZERO_COLUMNS_THRESHOLD from lib.core.settings import MYSQL_ERROR_CHUNK_LENGTH from lib.core.settings import MSSQL_ERROR_CHUNK_LENGTH @@ -180,6 +182,9 @@ def _errorFields(expression, expressionFields, expressionFieldsList, num=None, e else: expressionReplaced = expression.replace(expressionFields, field, 1) + if isTechniqueAvailable(PAYLOAD.TECHNIQUE.QUERY) and Backend.isDbms(DBMS.FIREBIRD) and expressionReplaced.startswith("SELECT "): + expressionReplaced = "SELECT %s" % agent.concatQuery(expressionReplaced) + output = NULL if emptyFields and field in emptyFields else _oneShotErrorUse(expressionReplaced, field) if not kb.threadContinue: diff --git a/xml/payloads.xml b/xml/payloads.xml index ad3c4c9e9..e574d12be 100644 --- a/xml/payloads.xml +++ b/xml/payloads.xml @@ -2004,7 +2004,7 @@ Formats: 1,2,3,8 3 - SELECT '[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]' + [QUERY] SELECT '[DELIMITER_START]'||(CASE [RANDNUM] WHEN [RANDNUM] THEN 1 ELSE 0 END)||'[DELIMITER_STOP]' FROM RDB$DATABASE From 30273e03feb2730f0583af24716a6f39533de578 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 00:28:48 +0000 Subject: [PATCH 25/35] leftover --- xml/payloads.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/xml/payloads.xml b/xml/payloads.xml index e574d12be..63245157c 100644 --- a/xml/payloads.xml +++ b/xml/payloads.xml @@ -2003,7 +2003,6 @@ Formats: 1 1,2,3,8 3 - [QUERY] SELECT '[DELIMITER_START]'||(CASE [RANDNUM] WHEN [RANDNUM] THEN 1 ELSE 0 END)||'[DELIMITER_STOP]' FROM RDB$DATABASE From b05c6cbd132d242298963e2a7851f086f6d39583 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 00:29:42 +0000 Subject: [PATCH 26/35] leftover --- xml/livetests.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/xml/livetests.xml b/xml/livetests.xml index d17a9624b..6d74eec1b 100644 --- a/xml/livetests.xml +++ b/xml/livetests.xml @@ -1065,6 +1065,7 @@ + From c95119559ee473f8d101fdc011c88b3948db96bb Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 00:41:51 +0000 Subject: [PATCH 27/35] minor bug fix --- lib/techniques/error/use.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/techniques/error/use.py b/lib/techniques/error/use.py index 44e662043..e84f0680a 100644 --- a/lib/techniques/error/use.py +++ b/lib/techniques/error/use.py @@ -182,7 +182,7 @@ def _errorFields(expression, expressionFields, expressionFieldsList, num=None, e else: expressionReplaced = expression.replace(expressionFields, field, 1) - if isTechniqueAvailable(PAYLOAD.TECHNIQUE.QUERY) and Backend.isDbms(DBMS.FIREBIRD) and expressionReplaced.startswith("SELECT "): + if kb.technique == PAYLOAD.TECHNIQUE.QUERY and Backend.isDbms(DBMS.FIREBIRD) and expressionReplaced.startswith("SELECT "): expressionReplaced = "SELECT %s" % agent.concatQuery(expressionReplaced) output = NULL if emptyFields and field in emptyFields else _oneShotErrorUse(expressionReplaced, field) From 1923ef691ef4dd3165215ca8d9357e9b61ef3b8c Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 16:06:46 +0000 Subject: [PATCH 28/35] just in case, add also the test case name inside the temp folder for debug purposes --- lib/core/testing.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/core/testing.py b/lib/core/testing.py index 376747012..647035487 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -184,6 +184,10 @@ def liveTest(): logger.error(errMsg) + test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING) + test_case_fd.write(msg) + test_case_fd.close() + if failedParseOn: console_output_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "console_output"), "wb", UNICODE_ENCODING) console_output_fd.write(failedParseOn) From ab607bd3782510a617eaf4112e43167217300442 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 16:07:30 +0000 Subject: [PATCH 29/35] minor bug fix to verify test case file exists before it gets read --- extra/shutils/regressiontest.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/extra/shutils/regressiontest.py b/extra/shutils/regressiontest.py index 24b62a801..b836372f6 100644 --- a/extra/shutils/regressiontest.py +++ b/extra/shutils/regressiontest.py @@ -87,18 +87,23 @@ def main(): test_counts.append(test_count) - console_output_fd = codecs.open(os.path.join(output_folder, "console_output"), "rb", "utf8") - console_output = console_output_fd.read() - console_output_fd.close() + console_output_file = os.path.join(output_folder, "console_output") + log_file = os.path.join(output_folder, "debiandev", "log") + traceback_file = os.path.join(output_folder, "traceback") - attachments[test_count] = str(console_output) + if os.path.exists(console_output_file): + console_output_fd = codecs.open(console_output_file, "rb", "utf8") + console_output = console_output_fd.read() + console_output_fd.close() + attachments[test_count] = str(console_output) - log_fd = codecs.open(os.path.join(output_folder, "debiandev", "log"), "rb", "utf8") - log = log_fd.read() - log_fd.close() + if os.path.exists(log_file): + log_fd = codecs.open(log_file, "rb", "utf8") + log = log_fd.read() + log_fd.close() - if traceback: - traceback_fd = codecs.open(os.path.join(output_folder, "traceback"), "rb", "utf8") + if os.path.exists(traceback_file): + traceback_fd = codecs.open(traceback_file, "rb", "utf8") traceback = traceback_fd.read() traceback_fd.close() From a24eaffaccd9dd277388f93b96a14e490a729c84 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 16:14:25 +0000 Subject: [PATCH 30/35] fixed --columns on DB2, inline with Oracle and other DBMSes now --- xml/queries.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xml/queries.xml b/xml/queries.xml index 75961459d..254242824 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -603,8 +603,8 @@ - - + + From 640e0eecc6f41b2d3012624ad7eef93e3be3a305 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 16:25:41 +0000 Subject: [PATCH 31/35] improved cron script to report any malfunction by email --- extra/shutils/regressiontest_cronjob.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/extra/shutils/regressiontest_cronjob.sh b/extra/shutils/regressiontest_cronjob.sh index 9a20bd3d6..b569b4e8d 100755 --- a/extra/shutils/regressiontest_cronjob.sh +++ b/extra/shutils/regressiontest_cronjob.sh @@ -6,9 +6,18 @@ SQLMAP_HOME="/opt/sqlmap" REGRESSION_SCRIPT="${SQLMAP_HOME}/extra/shutils" +FROM="regressiontest@sqlmap.org" +TO="bernardo.damele@gmail.com, miroslav.stampar@gmail.com" +SUBJECT="Automated regression test failed on $(date)" + cd $SQLMAP_HOME git pull rm -f output 2>/dev/null cd $REGRESSION_SCRIPT -python regressiontest.py +python regressiontest.py 1>/tmp/regressiontest.log 2>&1 + +if [ $? -ne 0 ] +then + cat /tmp/regressiontest.log | mailx -s "${SUBJECT}" -aFrom:${FROM} ${TO} +fi From 47f0d89fc5b40406b3139a0e39a223d2fd37e4f8 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 16:26:22 +0000 Subject: [PATCH 32/35] sqlmap.org mail server rejects the email, hence use Gmail --- extra/shutils/regressiontest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/shutils/regressiontest.py b/extra/shutils/regressiontest.py index b836372f6..52c5d1b81 100644 --- a/extra/shutils/regressiontest.py +++ b/extra/shutils/regressiontest.py @@ -26,7 +26,7 @@ SMTP_SERVER = "127.0.0.1" SMTP_PORT = 25 SMTP_TIMEOUT = 30 FROM = "regressiontest@sqlmap.org" -TO = "dev@sqlmap.org" +TO = ["bernardo.damele@gmail.com", "miroslav.stampar@gmail.com"] SUBJECT = "Regression test results on %s using revision %s" % (TIME, REVISION) def prepare_email(content): From f22fd396ef882b97c82f1dc938d4bf8a9a311bef Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 16:41:19 +0000 Subject: [PATCH 33/35] write the test case name before it is run so if the test case crashes badly, we can trace back what test case it was at a later stage --- lib/core/testing.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/core/testing.py b/lib/core/testing.py index 647035487..f6ef2acab 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -167,6 +167,10 @@ def liveTest(): result = runCase(switches, parse) + test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING) + test_case_fd.write(name) + test_case_fd.close() + if result: logger.info("test passed") cleanCase() @@ -184,10 +188,6 @@ def liveTest(): logger.error(errMsg) - test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING) - test_case_fd.write(msg) - test_case_fd.close() - if failedParseOn: console_output_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "console_output"), "wb", UNICODE_ENCODING) console_output_fd.write(failedParseOn) From dcf2dcd03dfe2c7a7e957d58ac50583878cfe277 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 17:04:57 +0000 Subject: [PATCH 34/35] all we need to debug failed test cases while regression test run.. --- lib/core/testing.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/core/testing.py b/lib/core/testing.py index f6ef2acab..ecaaec7f5 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -169,7 +169,6 @@ def liveTest(): test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING) test_case_fd.write(name) - test_case_fd.close() if result: logger.info("test passed") @@ -187,6 +186,7 @@ def liveTest(): errMsg += " - SQL injection not detected" logger.error(errMsg) + test_case_fd.write("\n%s" % errMsg) if failedParseOn: console_output_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "console_output"), "wb", UNICODE_ENCODING) @@ -203,6 +203,7 @@ def liveTest(): if conf.stopFail is True: return retVal + test_case_fd.close() retVal &= bool(result) dataToStdout("\n") From 6a62292a3f6e7e404ad9f6138f77af8d62d4c025 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 19 Jan 2013 17:11:16 +0000 Subject: [PATCH 35/35] layout adjustment --- lib/core/testing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/testing.py b/lib/core/testing.py index ecaaec7f5..ff4ed5258 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -168,7 +168,7 @@ def liveTest(): result = runCase(switches, parse) test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING) - test_case_fd.write(name) + test_case_fd.write("%s\n" % name) if result: logger.info("test passed") @@ -186,7 +186,7 @@ def liveTest(): errMsg += " - SQL injection not detected" logger.error(errMsg) - test_case_fd.write("\n%s" % errMsg) + test_case_fd.write("%s\n" % errMsg) if failedParseOn: console_output_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "console_output"), "wb", UNICODE_ENCODING)