Merge branch 'master' of github.com:sqlmapproject/sqlmap

This commit is contained in:
Miroslav Stampar 2013-01-22 11:29:15 +01:00
commit b8318efecc
7 changed files with 205 additions and 42 deletions

View File

@ -71,7 +71,7 @@ def main():
stdout, stderr = proc.communicate() stdout, stderr = proc.communicate()
if stderr: if stderr:
msg = prepare_email("Execution of regression test failed with error: %s" % stderr) msg = prepare_email("Execution of regression test failed with error:\n\n%s" % stderr)
send_email(msg) send_email(msg)
sys.exit(1) sys.exit(1)
@ -112,13 +112,15 @@ def main():
if parse: if parse:
content += " at parsing: %s:\n\n" % parse content += " at parsing: %s:\n\n" % parse
content += "### Log file:\n\n" content += "### Log file:\n\n"
content += "%s\n" % log content += "%s\n\n" % log
elif not detected: elif not detected:
content += " - SQL injection not detected\n\n" content += " - SQL injection not detected\n\n"
else:
content += "\n\n"
if traceback: if traceback:
content += "\n\n### Traceback:\n\n" content += "### Traceback:\n\n"
content += "%s\n" % str(traceback) content += "%s\n\n" % str(traceback)
content += "#######################################################################\n\n" content += "#######################################################################\n\n"
@ -137,4 +139,3 @@ def main():
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -139,6 +139,8 @@ def liveTest():
parse = [] parse = []
switches = dict(global_) switches = dict(global_)
value = "" value = ""
vulnerable = True
result = None
if case.hasAttribute("name"): if case.hasAttribute("name"):
name = case.getAttribute("name") name = case.getAttribute("name")
@ -165,12 +167,15 @@ def liveTest():
msg = "running live test case: %s (%d/%d)" % (name, count, length) msg = "running live test case: %s (%d/%d)" % (name, count, length)
logger.info(msg) logger.info(msg)
try:
result = runCase(switches, parse) result = runCase(switches, parse)
except SqlmapNotVulnerableException:
vulnerable = False
test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING) test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING)
test_case_fd.write("%s\n" % name) test_case_fd.write("%s\n" % name)
if result: if result is True:
logger.info("test passed") logger.info("test passed")
cleanCase() cleanCase()
else: else:
@ -182,7 +187,7 @@ def liveTest():
errMsg += "- scan folder: %s " % paths.SQLMAP_OUTPUT_PATH errMsg += "- scan folder: %s " % paths.SQLMAP_OUTPUT_PATH
errMsg += "- traceback: %s" % bool(failedTraceBack) errMsg += "- traceback: %s" % bool(failedTraceBack)
if result is False: if not vulnerable:
errMsg += " - SQL injection not detected" errMsg += " - SQL injection not detected"
logger.error(errMsg) logger.error(errMsg)

View File

@ -30,22 +30,12 @@ class Enumeration(GenericEnumeration):
return [] return []
def searchTable(self):
warnMsg = "on Firebird searching of tables is not implemented"
logger.warn(warnMsg)
return []
def searchColumn(self): def searchColumn(self):
warnMsg = "on Firebird searching of columns is not implemented" warnMsg = "on Firebird it is not possible to search columns"
logger.warn(warnMsg) logger.warn(warnMsg)
return [] return []
def search(self):
warnMsg = "on Firebird search option is not available"
logger.warn(warnMsg)
def getHostname(self): def getHostname(self):
warnMsg = "on Firebird it is not possible to enumerate the hostname" warnMsg = "on Firebird it is not possible to enumerate the hostname"
logger.warn(warnMsg) logger.warn(warnMsg)

View File

@ -10,6 +10,7 @@ from lib.core.common import arrayizeValue
from lib.core.common import Backend from lib.core.common import Backend
from lib.core.common import filterPairValues from lib.core.common import filterPairValues
from lib.core.common import getLimitRange from lib.core.common import getLimitRange
from lib.core.common import isInferenceAvailable
from lib.core.common import isNoneValue from lib.core.common import isNoneValue
from lib.core.common import isNumPosStrValue from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
@ -91,7 +92,8 @@ class Search:
for value in values: for value in values:
value = safeSQLIdentificatorNaming(value) value = safeSQLIdentificatorNaming(value)
foundDbs.append(value) foundDbs.append(value)
else:
if len(foundDbs) == 0 and isInferenceAvailable() and not conf.direct:
infoMsg = "fetching number of database" infoMsg = "fetching number of database"
if dbConsider == "1": if dbConsider == "1":
infoMsg += "s like" infoMsg += "s like"
@ -166,7 +168,7 @@ class Search:
for tbl in tblList: for tbl in tblList:
tbl = safeSQLIdentificatorNaming(tbl, True) tbl = safeSQLIdentificatorNaming(tbl, True)
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD):
tbl = tbl.upper() tbl = tbl.upper()
infoMsg = "searching table" infoMsg = "searching table"
@ -194,13 +196,14 @@ class Search:
query += whereDbsQuery query += whereDbsQuery
values = inject.getValue(query, blind=False, time=False) values = inject.getValue(query, blind=False, time=False)
if Backend.isDbms(DBMS.SQLITE): if values and Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD):
newValues = [] newValues = []
if isinstance(values, basestring): if isinstance(values, basestring):
values = [values] values = [values]
for value in values: for value in values:
newValues.append(["SQLite%s" % METADB_SUFFIX, value]) dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird"
newValues.append(["%s%s" % (dbName, METADB_SUFFIX), value])
values = newValues values = newValues
@ -215,8 +218,9 @@ class Search:
foundTbls[foundDb].append(foundTbl) foundTbls[foundDb].append(foundTbl)
else: else:
foundTbls[foundDb] = [foundTbl] foundTbls[foundDb] = [foundTbl]
else:
if not Backend.isDbms(DBMS.SQLITE): if len(foundTbls) == 0 and isInferenceAvailable() and not conf.direct:
if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD):
infoMsg = "fetching number of databases with table" infoMsg = "fetching number of databases with table"
if tblConsider == "1": if tblConsider == "1":
infoMsg += "s like" infoMsg += "s like"
@ -259,7 +263,8 @@ class Search:
if tblConsider == "2": if tblConsider == "2":
continue continue
else: else:
foundTbls["SQLite%s" % METADB_SUFFIX] = [] dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird"
foundTbls["%s%s" % (dbName, METADB_SUFFIX)] = []
for db in foundTbls.keys(): for db in foundTbls.keys():
db = safeSQLIdentificatorNaming(db) db = safeSQLIdentificatorNaming(db)
@ -271,7 +276,7 @@ class Search:
logger.info(infoMsg) logger.info(infoMsg)
query = rootQuery.blind.count2 query = rootQuery.blind.count2
if not Backend.isDbms(DBMS.SQLITE): if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD):
query = query % unsafeSQLIdentificatorNaming(db) query = query % unsafeSQLIdentificatorNaming(db)
query += " AND %s" % tblQuery query += " AND %s" % tblQuery
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
@ -290,9 +295,16 @@ class Search:
for index in indexRange: for index in indexRange:
query = rootQuery.blind.query2 query = rootQuery.blind.query2
if not Backend.isDbms(DBMS.SQLITE):
if Backend.isDbms(DBMS.FIREBIRD):
query = query % index
if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD):
query = query % unsafeSQLIdentificatorNaming(db) query = query % unsafeSQLIdentificatorNaming(db)
query += " AND %s" % tblQuery query += " AND %s" % tblQuery
if not Backend.isDbms(DBMS.FIREBIRD):
query = agent.limitQuery(index, query) query = agent.limitQuery(index, query)
foundTbl = unArrayizeValue(inject.getValue(query, union=False, error=False)) foundTbl = unArrayizeValue(inject.getValue(query, union=False, error=False))
@ -436,7 +448,8 @@ class Search:
foundCols[column][db] = [tbl] foundCols[column][db] = [tbl]
kb.data.cachedColumns = {} kb.data.cachedColumns = {}
else:
if len(dbs) == 0 and isInferenceAvailable() and not conf.direct:
if not conf.db: if not conf.db:
infoMsg = "fetching number of databases with tables containing column" infoMsg = "fetching number of databases with tables containing column"
if colConsider == "1": if colConsider == "1":

View File

@ -135,7 +135,7 @@ class Users:
if not kb.data.cachedUsers: if not kb.data.cachedUsers:
errMsg = "unable to retrieve the database users" errMsg = "unable to retrieve the database users"
raise SqlmapNoneDataException(errMsg) logger.error(errMsg)
return kb.data.cachedUsers return kb.data.cachedUsers

View File

@ -807,7 +807,7 @@
<item value="banner: '2.8.17'"/> <item value="banner: '2.8.17'"/>
<item value="r'Database: SQLite_masterdb.+1 table.+users'"/> <item value="r'Database: SQLite_masterdb.+1 table.+users'"/>
<item value="r'Database: SQLite_masterdb.+Table: users.+3 columns.+surname.+TEXT'"/> <item value="r'Database: SQLite_masterdb.+Table: users.+3 columns.+surname.+TEXT'"/>
<item value="r'Database: SQLite_masterdb.+Table: users.+4 entries.+luther.+user agent.+'"/> <item value="r'Database: SQLite_masterdb.+Table: users.+5 entries.+luther.+user agent.+'"/>
</parse> </parse>
</case> </case>
<case name="SQLite partial UNION query multi-threaded enumeration - all entries"> <case name="SQLite partial UNION query multi-threaded enumeration - all entries">
@ -839,7 +839,7 @@
<item value="banner: '2.8.17'"/> <item value="banner: '2.8.17'"/>
<item value="r'Database: SQLite_masterdb.+1 table.+users'"/> <item value="r'Database: SQLite_masterdb.+1 table.+users'"/>
<item value="r'Database: SQLite_masterdb.+Table: users.+3 columns.+surname.+TEXT'"/> <item value="r'Database: SQLite_masterdb.+Table: users.+3 columns.+surname.+TEXT'"/>
<item value="r'Database: SQLite_masterdb.+Table: users.+4 entries.+luther.+user agent.+'"/> <item value="r'Database: SQLite_masterdb.+Table: users.+5 entries.+luther.+user agent.+'"/>
</parse> </parse>
</case> </case>
<case name="SQLite 3 time-based single-threaded enumeration - all entries"> <case name="SQLite 3 time-based single-threaded enumeration - all entries">
@ -927,7 +927,7 @@
<item value="r'Database: Firebird_masterdb.+Table: USERS.+5 entries.+luther.+nameisnull.+'"/> <item value="r'Database: Firebird_masterdb.+Table: USERS.+5 entries.+luther.+nameisnull.+'"/>
</parse> </parse>
</case> </case>
<!-- TODO: this test case fails because of issue #358 --> <!-- TODO: this test case fails because of issue #358
<case name="Firebird error-based multi-threaded enumeration - all entries"> <case name="Firebird error-based multi-threaded enumeration - all entries">
<switches> <switches>
<url value="http://debiandev/sqlmap/firebird/get_int.php?id=1"/> <url value="http://debiandev/sqlmap/firebird/get_int.php?id=1"/>
@ -966,7 +966,7 @@
<item value="r'Database: Firebird_masterdb.+Table: USERS.+5 entries.+luther.+nameisnull.+'"/> <item value="r'Database: Firebird_masterdb.+Table: USERS.+5 entries.+luther.+nameisnull.+'"/>
</parse> </parse>
</case> </case>
<!-- TODO: this test case fails because of issue #357 --> -->
<case name="Firebird UNION query multi-threaded enumeration - all entries"> <case name="Firebird UNION query multi-threaded enumeration - all entries">
<switches> <switches>
<url value="http://debiandev/sqlmap/firebird/get_int.php?id=1"/> <url value="http://debiandev/sqlmap/firebird/get_int.php?id=1"/>
@ -1005,7 +1005,7 @@
<item value="r'Database: Firebird_masterdb.+Table: USERS.+5 entries.+luther.+nameisnull.+'"/> <item value="r'Database: Firebird_masterdb.+Table: USERS.+5 entries.+luther.+nameisnull.+'"/>
</parse> </parse>
</case> </case>
<!-- TODO: this test case fails because of issue #357 --> <!-- TODO: this test case fails because of a bug whereby partial UNION is no longer detected on Firebird -->
<case name="Firebird partial UNION query multi-threaded enumeration - all entries"> <case name="Firebird partial UNION query multi-threaded enumeration - all entries">
<switches> <switches>
<url value="http://debiandev/sqlmap/firebird/get_int_partialunion.php?id=1"/> <url value="http://debiandev/sqlmap/firebird/get_int_partialunion.php?id=1"/>
@ -2184,7 +2184,101 @@
<item value="r'Database: SYS.+Table: USERS.+1 column.+SURNAME.+VARCHAR2'"/> <item value="r'Database: SYS.+Table: USERS.+1 column.+SURNAME.+VARCHAR2'"/>
</parse> </parse>
</case> </case>
<!-- TODO: add IBM DB2 test cases --> <case name="IBM DB2 boolean-based multi-threaded search enumeration - database">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<search value="True"/>
<db value="d"/>
</switches>
<parse>
<item value="r'found databases.+:.+\[\*\] DB2INST1.+\[\*\] SYSIBMADM'"/>
</parse>
</case>
<case name="IBM DB2 boolean-based multi-threaded search enumeration - tables given database">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<search value="True"/>
<db value="db2inst1"/>
<tbl value="user,wrong"/>
<answer value="do you want to dump tables=N"/>
</switches>
<parse>
<item value="r'Database: DB2INST1.+1 table.+USERS'"/>
</parse>
</case>
<case name="IBM DB2 boolean-based multi-threaded search enumeration - tables without given database">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<search value="True"/>
<tbl value="users"/>
<answers value="do you want to dump=N"/>
</switches>
<parse>
<item value="r'Database: DB2INST1.+1 table.+USERS'"/>
</parse>
</case>
<case name="IBM DB2 boolean-based multi-threaded search enumeration - column without given db or table">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<search value="True"/>
<col value="surname,foobar"/>
<answers value="do you want to dump=N"/>
</switches>
<parse>
<item value="r'Database: DB2INST1.+Table: USERS.+1 column.+SURNAME'"/>
</parse>
</case>
<case name="IBM DB2 boolean-based multi-threaded search enumeration - column given databases">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<search value="True"/>
<db value="db2inst1,foobar"/>
<col value="surname"/>
<answers value="do you want to dump=N"/>
</switches>
<parse>
<item value="r'Database: DB2INST1.+Table: USERS.+1 column.+SURNAME'"/>
</parse>
</case>
<case name="IBM DB2 boolean-based multi-threaded search enumeration - column given tables">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<search value="True"/>
<tbl value="users,foobar"/>
<col value="surname"/>
<answers value="do you want to dump=N"/>
</switches>
<parse>
<item value="r'Database: DB2INST1.+Table: USERS.+1 column.+SURNAME'"/>
</parse>
</case>
<case name="IBM DB2 boolean-based multi-threaded search enumeration - column given databases and table">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<search value="True"/>
<db value="db2inst1,foobar"/>
<tbl value="users"/>
<col value="surname"/>
<answers value="do you want to dump=N"/>
</switches>
<parse>
<item value="r'Database: DB2INST1.+Table: USERS.+1 column.+SURNAME'"/>
</parse>
</case>
<case name="SQLite multi-threaded search enumeration - database"> <case name="SQLite multi-threaded search enumeration - database">
<switches> <switches>
<url value="http://debiandev/sqlmap/sqlite/get_int.php?id=1"/> <url value="http://debiandev/sqlmap/sqlite/get_int.php?id=1"/>
@ -2222,6 +2316,43 @@
<item value="r'Database: SQLite_masterdb.+1 table.+users'"/> <item value="r'Database: SQLite_masterdb.+1 table.+users'"/>
</parse> </parse>
</case> </case>
<case name="Firebird multi-threaded search enumeration - database">
<switches>
<url value="http://debiandev/sqlmap/firebird/get_int.php?id=1"/>
<threads value="4"/>
<search value="True"/>
<db value="e"/>
</switches>
<parse>
<item value="on Firebird it is not possible to search databases" console_output="True"/>
</parse>
</case>
<case name="Firebird boolean-based multi-threaded search enumeration - tables without given database">
<switches>
<url value="http://debiandev/sqlmap/firebird/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<search value="True"/>
<tbl value="user"/>
<answers value="do you want to dump=N"/>
</switches>
<parse>
<item value="r'Database: Firebird_masterdb.+1 table.+USERS'"/>
</parse>
</case>
<case name="Firebird UNION query multi-threaded search enumeration - tables without given database">
<switches>
<url value="http://debiandev/sqlmap/firebird/get_int.php?id=1"/>
<threads value="4"/>
<tech value="U"/>
<search value="True"/>
<tbl value="user"/>
<answers value="do you want to dump=N"/>
</switches>
<parse>
<item value="r'Database: Firebird_masterdb.+1 table.+USERS'"/>
</parse>
</case>
<!-- End of search enumeration switches --> <!-- End of search enumeration switches -->
<!-- User's provided statement enumeration switches --> <!-- User's provided statement enumeration switches -->
@ -2425,7 +2556,28 @@
<item value="r'SELECT \* FROM users ORDER BY name \[5\].+1, luther, blisset.+2, fluffy, bunny.+3, wu, ming'"/> <item value="r'SELECT \* FROM users ORDER BY name \[5\].+1, luther, blisset.+2, fluffy, bunny.+3, wu, ming'"/>
</parse> </parse>
</case> </case>
<!-- TODO: add IBM DB2 test cases --> <case name="IBM DB2 boolean-based multi-threaded custom SQL query enumeration">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<query value="SELECT * FROM db2inst1.users"/>
</switches>
<parse>
<item value="r'SELECT \* FROM db2inst1.users.+1, luther, blisset.+nameisnull'"/>
</parse>
</case>
<case name="IBM DB2 boolean-based multi-threaded custom ordered SQL query enumeration">
<switches>
<url value="http://debiandev/sqlmap/db2/get_int.php?id=1"/>
<threads value="4"/>
<tech value="B"/>
<query value="SELECT * FROM db2inst1.users ORDER BY name"/>
</switches>
<parse>
<item value="r'SELECT \* FROM db2inst1.users ORDER BY name \[5\].+1, luther, blisset.+2, fluffy, bunny.+3, wu, ming'"/>
</parse>
</case>
<case name="SQLite boolean-based multi-threaded custom SQL query enumeration"> <case name="SQLite boolean-based multi-threaded custom SQL query enumeration">
<switches> <switches>
<url value="http://debiandev/sqlmap/sqlite/get_int.php?id=1"/> <url value="http://debiandev/sqlmap/sqlite/get_int.php?id=1"/>
@ -2467,7 +2619,7 @@
<query value="SELECT * FROM users ORDER BY name"/> <query value="SELECT * FROM users ORDER BY name"/>
</switches> </switches>
<parse> <parse>
<item value="r'SELECT \* FROM users ORDER BY name \[4\].+1, luther, blisset.+2, fluffy, bunny.+3, wu, ming'"/> <item value="r'SELECT \* FROM users ORDER BY name \[5\].+1, luther, blisset.+2, fluffy, bunny.+3, wu, ming'"/>
</parse> </parse>
</case> </case>
<!-- End of user's provided statement enumeration switches --> <!-- End of user's provided statement enumeration switches -->

View File

@ -431,17 +431,19 @@
<blind query="SELECT FIRST 1 SKIP %d %s FROM %s" count="SELECT COUNT(*) FROM %s"/> <blind query="SELECT FIRST 1 SKIP %d %s FROM %s" count="SELECT COUNT(*) FROM %s"/>
</dump_table> </dump_table>
<search_db/> <search_db/>
<search_table/> <search_table>
<inband query="SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$VIEW_BLR IS NULL AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0) AND " condition="RDB$RELATION_NAME" condition2=""/>
<blind query="" query2="SELECT FIRST 1 SKIP %d RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$VIEW_BLR IS NULL AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)" count="" count2="SELECT COUNT(RDB$RELATION_NAME) FROM RDB$RELATIONS WHERE RDB$VIEW_BLR IS NULL AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)" condition="RDB$RELATION_NAME" condition2=""/>
</search_table>
<search_column/> <search_column/>
</dbms> </dbms>
<!-- SAP MaxDB -->
<!-- http://dev.mysql.com/tech-resources/articles/maxdb-php-ready-for-web.html --> <!-- http://dev.mysql.com/tech-resources/articles/maxdb-php-ready-for-web.html -->
<!-- http://dev.mysql.com/doc/refman/5.0/es/maxdb-reserved-words.html --> <!-- http://dev.mysql.com/doc/refman/5.0/es/maxdb-reserved-words.html -->
<!-- http://maxdb.sap.com/doc/7_6/default.htm --> <!-- http://maxdb.sap.com/doc/7_6/default.htm -->
<!-- http://www.sapdb.org/7.4/htmhelp/35/f8823cb7e5d42be10000000a114027/content.htm --> <!-- http://www.sapdb.org/7.4/htmhelp/35/f8823cb7e5d42be10000000a114027/content.htm -->
<!-- http://www.ximido.de/research/PenTestingMaxDB.pdf --> <!-- http://www.ximido.de/research/PenTestingMaxDB.pdf -->
<!-- SAP MaxDB -->
<dbms value="SAP MaxDB"> <dbms value="SAP MaxDB">
<length query="LENGTH(%s)"/> <length query="LENGTH(%s)"/>
<isnull query="VALUE(%s,' ')" query2="IFNULL(%s,' ')"/> <isnull query="VALUE(%s,' ')" query2="IFNULL(%s,' ')"/>