sqlmap/lib/core/dump.py

411 lines
13 KiB
Python
Raw Normal View History

2008-10-15 19:38:22 +04:00
#!/usr/bin/env python
"""
2008-10-15 19:56:32 +04:00
$Id$
2008-10-15 19:38:22 +04:00
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
2010-03-03 18:26:27 +03:00
Copyright (c) 2007-2010 Bernardo Damele A. G. <bernardo.damele@gmail.com>
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
2008-10-15 19:38:22 +04:00
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 codecs
import re
import os
2008-10-15 19:38:22 +04:00
from lib.core.common import dataToDumpFile
from lib.core.common import dataToStdout
2010-06-02 16:31:36 +04:00
from lib.core.common import getUnicode
2008-10-15 19:38:22 +04:00
from lib.core.data import conf
2010-09-24 17:19:35 +04:00
from lib.core.data import kb
2008-10-15 19:38:22 +04:00
from lib.core.data import logger
2010-09-24 17:19:35 +04:00
from lib.core.replication import Replication
2008-10-15 19:38:22 +04:00
class Dump:
"""
This class defines methods used to parse and output the results
of SQL injection actions
"""
def __init__(self):
self.__outputFile = None
self.__outputFP = None
def __write(self, data, n=True):
2010-09-24 17:19:35 +04:00
text = "%s%s" % (data, "\n" if n else " ")
2008-10-15 19:38:22 +04:00
dataToStdout(text)
self.__outputFP.write(text)
2008-10-15 19:38:22 +04:00
self.__outputFP.flush()
conf.loggedToOut = True
def __formatString(self, string):
2010-06-02 16:31:36 +04:00
string = getUnicode(string)
string = string.replace("__NEWLINE__", "\n").replace("__TAB__", "\t")
string = string.replace("__START__", "").replace("__STOP__", "")
string = string.replace("__DEL__", ", ")
return string
2008-10-15 19:38:22 +04:00
def setOutputFile(self):
self.__outputFile = "%s%slog" % (conf.outputPath, os.sep)
self.__outputFP = codecs.open(self.__outputFile, "ab", conf.dataEncoding)
def string(self, header, data, sort=True):
2008-10-15 19:38:22 +04:00
if isinstance(data, (list, tuple, set)):
self.lister(header, data, sort)
2008-10-15 19:38:22 +04:00
return
2010-06-02 16:31:36 +04:00
data = getUnicode(data)
2008-10-15 19:38:22 +04:00
if data:
data = self.__formatString(data)
2008-10-15 19:38:22 +04:00
if "\n" in data:
self.__write("%s:\n---\n%s\n---\n" % (header, data))
2008-10-15 19:38:22 +04:00
else:
self.__write("%s: '%s'\n" % (header, data))
else:
self.__write("%s:\tNone\n" % header)
2010-09-24 17:19:35 +04:00
def lister(self, header, elements, sort=True):
if elements:
self.__write("%s [%d]:" % (header, len(elements)))
2008-10-15 19:38:22 +04:00
if sort:
try:
elements = set(elements)
elements = list(elements)
elements.sort(key=lambda x: x.lower())
except:
pass
2008-10-15 19:38:22 +04:00
for element in elements:
if isinstance(element, basestring):
2008-10-15 19:38:22 +04:00
self.__write("[*] %s" % element)
elif isinstance(element, (list, tuple, set)):
2010-06-02 16:31:36 +04:00
self.__write("[*] " + ", ".join(getUnicode(e) for e in element))
2008-10-15 19:38:22 +04:00
if elements:
self.__write("")
def technic(self,header,data):
self.string(header, data)
def banner(self,data):
self.string("banner", data)
def currentUser(self,data):
self.string("current user", data)
def currentDb(self,data):
self.string("current database", data)
def dba(self,data):
self.string("current user is DBA", data)
def users(self,users):
self.lister("database management system users", users)
2008-10-15 19:38:22 +04:00
def userSettings(self, header, userSettings, subHeader):
self.__areAdmins = set()
if userSettings:
self.__write("%s:" % header)
2008-10-15 19:38:22 +04:00
if isinstance(userSettings, (tuple, list, set)):
self.__areAdmins = userSettings[1]
userSettings = userSettings[0]
users = userSettings.keys()
users.sort(key=lambda x: x.lower())
for user in users:
settings = userSettings[user]
if user in self.__areAdmins:
self.__write("[*] %s (administrator) [%d]:" % (user, len(settings)))
else:
self.__write("[*] %s [%d]:" % (user, len(settings)))
settings.sort()
for setting in settings:
self.__write(" %s: %s" % (subHeader, setting))
print
def dbs(self,dbs):
self.lister("available databases", dbs)
2008-10-15 19:38:22 +04:00
def dbTables(self, dbTables):
2009-04-29 23:45:12 +04:00
if not isinstance(dbTables, dict):
self.string("tables", dbTables)
return
2008-10-15 19:38:22 +04:00
maxlength = 0
for tables in dbTables.values():
for table in tables:
maxlength = max(maxlength, len(table))
lines = "-" * (int(maxlength) + 2)
for db, tables in dbTables.items():
tables.sort(key=lambda x: x.lower())
self.__write("Database: %s" % db)
if len(tables) == 1:
self.__write("[1 table]")
else:
self.__write("[%d tables]" % len(tables))
self.__write("+%s+" % lines)
for table in tables:
blank = " " * (maxlength - len(table))
self.__write("| %s%s |" % (table, blank))
self.__write("+%s+\n" % lines)
2008-10-15 19:38:22 +04:00
def dbTableColumns(self, tableColumns):
for db, tables in tableColumns.items():
if not db:
db = "All"
for table, columns in tables.items():
maxlength1 = 0
maxlength2 = 0
colList = columns.keys()
colList.sort(key=lambda x: x.lower())
for column in colList:
colType = columns[column]
maxlength1 = max(maxlength1, len(column))
if colType is not None:
maxlength2 = max(maxlength2, len(colType))
2008-10-15 19:38:22 +04:00
maxlength1 = max(maxlength1, len("COLUMN"))
lines1 = "-" * (int(maxlength1) + 2)
if colType is not None:
maxlength2 = max(maxlength2, len("TYPE"))
lines2 = "-" * (int(maxlength2) + 2)
2008-10-15 19:38:22 +04:00
self.__write("Database: %s\nTable: %s" % (db, table))
if len(columns) == 1:
self.__write("[1 column]")
else:
self.__write("[%d columns]" % len(columns))
if colType is not None:
self.__write("+%s+%s+" % (lines1, lines2))
else:
self.__write("+%s+" % lines1)
2008-10-15 19:38:22 +04:00
blank1 = " " * (maxlength1 - len("COLUMN"))
if colType is not None:
blank2 = " " * (maxlength2 - len("TYPE"))
if colType is not None:
self.__write("| Column%s | Type%s |" % (blank1, blank2))
self.__write("+%s+%s+" % (lines1, lines2))
else:
self.__write("| Column%s |" % blank1)
self.__write("+%s+" % lines1)
2008-10-15 19:38:22 +04:00
for column in colList:
colType = columns[column]
blank1 = " " * (maxlength1 - len(column))
if colType is not None:
blank2 = " " * (maxlength2 - len(colType))
self.__write("| %s%s | %s%s |" % (column, blank1, colType, blank2))
else:
self.__write("| %s%s |" % (column, blank1))
if colType is not None:
self.__write("+%s+%s+\n" % (lines1, lines2))
else:
self.__write("+%s+\n" % lines1)
2008-10-15 19:38:22 +04:00
def dbTableValues(self, tableValues):
if tableValues is None:
return
2008-10-15 19:38:22 +04:00
db = tableValues["__infos__"]["db"]
if not db:
db = "All"
table = tableValues["__infos__"]["table"]
if not conf.multipleTargets:
2008-10-15 19:38:22 +04:00
dumpDbPath = "%s%s%s" % (conf.dumpPath, os.sep, db)
if not os.path.isdir(dumpDbPath):
os.makedirs(dumpDbPath, 0755)
dumpFileName = "%s%s%s.csv" % (dumpDbPath, os.sep, table)
dumpFP = codecs.open(dumpFileName, "wb", conf.dataEncoding)
2008-10-15 19:38:22 +04:00
2010-09-24 17:19:35 +04:00
count = int(tableValues["__infos__"]["count"])
separator = str()
field = 1
fields = len(tableValues) - 1
replication = None
rtable = None
2008-10-15 19:38:22 +04:00
columns = tableValues.keys()
columns.sort(key=lambda x: x.lower())
for column in columns:
if column != "__infos__":
info = tableValues[column]
lines = "-" * (int(info["length"]) + 2)
2008-10-15 19:38:22 +04:00
separator += "+%s" % lines
separator += "+"
self.__write("Database: %s\nTable: %s" % (db, table))
2010-09-24 17:19:35 +04:00
if conf.replicate:
replication = Replication("%s%s%s.sqlite" % (conf.outputPath, os.sep, db))
cols = list(columns)
if "__infos__" in cols:
cols.remove("__infos__")
rtable = replication.createTable(table, cols, True)
2008-10-15 19:38:22 +04:00
if count == 1:
self.__write("[1 entry]")
else:
self.__write("[%d entries]" % count)
self.__write(separator)
for column in columns:
if column != "__infos__":
info = tableValues[column]
2008-10-15 19:38:22 +04:00
maxlength = int(info["length"])
blank = " " * (maxlength - len(column))
2008-10-15 19:38:22 +04:00
self.__write("| %s%s" % (column, blank), n=False)
if not conf.multipleTargets and field == fields:
2010-03-03 22:23:43 +03:00
dataToDumpFile(dumpFP, "%s" % column)
elif not conf.multipleTargets:
2010-03-03 22:23:43 +03:00
dataToDumpFile(dumpFP, "%s," % column)
2008-10-15 19:38:22 +04:00
field += 1
self.__write("|\n%s" % separator)
if not conf.multipleTargets:
2008-10-15 19:38:22 +04:00
dataToDumpFile(dumpFP, "\n")
for i in range(count):
field = 1
2010-09-24 17:19:35 +04:00
values = []
2008-10-15 19:38:22 +04:00
for column in columns:
if column != "__infos__":
info = tableValues[column]
2010-06-02 16:31:36 +04:00
value = getUnicode(info["values"][i])
if re.search("^[\ *]*$", value):
2008-10-15 19:38:22 +04:00
value = "NULL"
2010-09-24 17:19:35 +04:00
values.append(value)
2008-10-15 19:38:22 +04:00
maxlength = int(info["length"])
blank = " " * (maxlength - len(value))
2008-10-15 19:38:22 +04:00
self.__write("| %s%s" % (value, blank), n=False)
if not conf.multipleTargets and field == fields:
2008-10-15 19:38:22 +04:00
dataToDumpFile(dumpFP, "\"%s\"" % value)
elif not conf.multipleTargets:
2008-10-15 19:38:22 +04:00
dataToDumpFile(dumpFP, "\"%s\"," % value)
field += 1
2010-09-24 17:19:35 +04:00
if conf.replicate:
rtable.insert(values)
2008-10-15 19:38:22 +04:00
self.__write("|")
if not conf.multipleTargets:
2008-10-15 19:38:22 +04:00
dataToDumpFile(dumpFP, "\n")
self.__write("%s\n" % separator)
if not conf.multipleTargets:
2008-10-15 19:38:22 +04:00
dataToDumpFile(dumpFP, "\n")
dumpFP.close()
logger.info("Table '%s.%s' dumped to CSV file '%s'" % (db, table, dumpFileName))
2010-09-24 17:19:35 +04:00
if conf.replicate:
logger.info("Table '%s.%s' dumped to sqlite3 file '%s'" % (db, table, replication.dbpath))
def dbColumns(self, dbColumns, colConsider, dbs):
for column in dbColumns.keys():
if colConsider == "1":
colConsiderStr = "s like '" + column + "' were"
else:
colConsiderStr = " '%s' was" % column
msg = "Column%s found in the " % colConsiderStr
msg += "following databases:"
self.__write(msg)
printDbs = {}
for db, tblData in dbs.items():
for tbl, colData in tblData.items():
for col, dataType in colData.items():
if column.lower() in col.lower():
if db in printDbs:
if tbl in printDbs[db]:
printDbs[db][tbl][col] = dataType
else:
printDbs[db][tbl] = { col: dataType }
else:
printDbs[db] = {}
printDbs[db][tbl] = { col: dataType }
continue
self.dbTableColumns(printDbs)
def query(self, query, queryRes):
self.string(query, queryRes)
def rFile(self,filePath,fileData):
self.string("%s file saved to" % filePath,fileData,sort=False)
def registerValue(self,registerData):
self.string("Registry key value data", registerData,sort=False)
2008-10-15 19:38:22 +04:00
# object to manage how to print the retrieved queries output to
# standard output and sessions file
dumper = Dump()