Skip to content

Commit 06af405

Browse files
committed
Adapted and merged in patch to support XML output (-x switch) - still in beta.
Minor bug fixes and adjustments.
1 parent a138dbe commit 06af405

File tree

14 files changed

+964
-86
lines changed

14 files changed

+964
-86
lines changed

doc/THANKS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ Krzysztof Kotowicz <kkotowicz@gmail.com>
157157
Nicolas Krassas <krasn@ans.gr>
158158
for reporting a bug
159159

160+
Alex Landa <landa.alex86@gmail.com>
161+
for providing a patch adding support for XML output
162+
160163
Guido Landi <lists@keamera.org>
161164
for reporting a couple of bugs
162165
for the great technical discussions
@@ -193,7 +196,7 @@ Enrico Milanese <enricomilanese@gmail.com>
193196
for reporting a bugs when using (-a) a single line User-Agent file
194197
for providing me with some ideas for the PHP backdoor
195198

196-
Alejo Murillo <alex@65535.com>
199+
Alejo Murillo Moya <alex@65535.com>
197200
for suggesting a feature
198201

199202
Roberto Nemirovsky <roberto.paes@gmail.com>

lib/controller/action.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
from lib.core.common import getHtmlErrorFp
2727
from lib.core.data import conf
2828
from lib.core.data import kb
29-
from lib.core.dump import dumper
3029
from lib.core.exception import sqlmapUnsupportedDBMSException
3130
from lib.core.settings import SUPPORTED_DBMS
3231
from lib.techniques.blind.timebased import timeTest
@@ -69,53 +68,53 @@ def action():
6968

7069
# Techniques options
7170
if conf.stackedTest:
72-
dumper.string("stacked queries support", stackedTest())
71+
conf.dumper.technic("stacked queries support", stackedTest())
7372

7473
if conf.timeTest:
75-
dumper.string("time based blind sql injection payload", timeTest())
74+
conf.dumper.technic("time based blind sql injection payload", timeTest())
7675

7776
if ( conf.unionUse or conf.unionTest ) and not kb.unionPosition:
78-
dumper.string("valid union", unionTest())
77+
conf.dumper.technic("valid union", unionTest())
7978

8079
# Enumeration options
8180
if conf.getBanner:
82-
dumper.string("banner", conf.dbmsHandler.getBanner())
81+
conf.dumper.banner(conf.dbmsHandler.getBanner())
8382

8483
if conf.getCurrentUser:
85-
dumper.string("current user", conf.dbmsHandler.getCurrentUser())
84+
conf.dumper.currentUser(conf.dbmsHandler.getCurrentUser())
8685

8786
if conf.getCurrentDb:
88-
dumper.string("current database", conf.dbmsHandler.getCurrentDb())
87+
conf.dumper.currentDb(conf.dbmsHandler.getCurrentDb())
8988

9089
if conf.isDba:
91-
dumper.string("current user is DBA", conf.dbmsHandler.isDba())
90+
conf.dumper.dba(conf.dbmsHandler.isDba())
9291

9392
if conf.getUsers:
94-
dumper.lister("database management system users", conf.dbmsHandler.getUsers())
93+
conf.dumper.users(conf.dbmsHandler.getUsers())
9594

9695
if conf.getPasswordHashes:
97-
dumper.userSettings("database management system users password hashes",
98-
conf.dbmsHandler.getPasswordHashes(), "password hash")
96+
conf.dumper.userSettings("database management system users password hashes",
97+
conf.dbmsHandler.getPasswordHashes(), "password hash")
9998

10099
if conf.getPrivileges:
101-
dumper.userSettings("database management system users privileges",
102-
conf.dbmsHandler.getPrivileges(), "privilege")
100+
conf.dumper.userSettings("database management system users privileges",
101+
conf.dbmsHandler.getPrivileges(), "privilege")
103102

104103
if conf.getRoles:
105-
dumper.userSettings("database management system users roles",
106-
conf.dbmsHandler.getRoles(), "role")
104+
conf.dumper.userSettings("database management system users roles",
105+
conf.dbmsHandler.getRoles(), "role")
107106

108107
if conf.getDbs:
109-
dumper.lister("available databases", conf.dbmsHandler.getDbs())
108+
conf.dumper.dbs(conf.dbmsHandler.getDbs())
110109

111110
if conf.getTables:
112-
dumper.dbTables(conf.dbmsHandler.getTables())
111+
conf.dumper.dbTables(conf.dbmsHandler.getTables())
113112

114113
if conf.getColumns:
115-
dumper.dbTableColumns(conf.dbmsHandler.getColumns())
114+
conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns())
116115

117116
if conf.dumpTable:
118-
dumper.dbTableValues(conf.dbmsHandler.dumpTable())
117+
conf.dumper.dbTableValues(conf.dbmsHandler.dumpTable())
119118

120119
if conf.dumpAll:
121120
conf.dbmsHandler.dumpAll()
@@ -124,7 +123,7 @@ def action():
124123
conf.dbmsHandler.search()
125124

126125
if conf.query:
127-
dumper.string(conf.query, conf.dbmsHandler.sqlQuery(conf.query))
126+
conf.dumper.query(conf.query, conf.dbmsHandler.sqlQuery(conf.query))
128127

129128
if conf.sqlShell:
130129
conf.dbmsHandler.sqlShell()
@@ -135,7 +134,7 @@ def action():
135134

136135
# File system options
137136
if conf.rFile:
138-
dumper.string("%s file saved to" % conf.rFile, conf.dbmsHandler.readFile(conf.rFile), sort=False)
137+
conf.dumper.rFile(conf.rFile, conf.dbmsHandler.readFile(conf.rFile))
139138

140139
if conf.wFile:
141140
conf.dbmsHandler.writeFile(conf.wFile, conf.dFile, conf.wFileType)
@@ -158,7 +157,7 @@ def action():
158157

159158
# Windows registry options
160159
if conf.regRead:
161-
dumper.string("Registry key value data", conf.dbmsHandler.regRead())
160+
conf.dumper.registerValue(conf.dbmsHandler.regRead())
162161

163162
if conf.regAdd:
164163
conf.dbmsHandler.regAdd()

lib/core/dump.py

Lines changed: 74 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class Dump:
4040
def __init__(self):
4141
self.__outputFile = None
4242
self.__outputFP = None
43-
43+
4444
def __write(self, data, n=True):
4545
if n:
4646
print data
@@ -52,11 +52,19 @@ def __write(self, data, n=True):
5252
self.__outputFP.flush()
5353

5454
conf.loggedToOut = True
55-
55+
56+
def __formatString(self, string):
57+
string = unicode(string)
58+
string = string.replace("__NEWLINE__", "\n").replace("__TAB__", "\t")
59+
string = string.replace("__START__", "").replace("__STOP__", "")
60+
string = string.replace("__DEL__", ", ")
61+
62+
return string
63+
5664
def setOutputFile(self):
5765
self.__outputFile = "%s%slog" % (conf.outputPath, os.sep)
58-
self.__outputFP = codecs.open(self.__outputFile, "a", conf.dataEncoding)
59-
66+
self.__outputFP = codecs.open(self.__outputFile, "ab", conf.dataEncoding)
67+
6068
def string(self, header, data, sort=True):
6169
if isinstance(data, (list, tuple, set)):
6270
self.lister(header, data, sort)
@@ -66,9 +74,7 @@ def string(self, header, data, sort=True):
6674
data = unicode(data)
6775

6876
if data:
69-
data = data.replace("__NEWLINE__", "\n").replace("__TAB__", "\t")
70-
data = data.replace("__START__", "").replace("__STOP__", "")
71-
data = data.replace("__DEL__", ", ")
77+
data = self.__formatString(data)
7278

7379
if "\n" in data:
7480
self.__write("%s:\n---\n%s\n---\n" % (header, data))
@@ -97,7 +103,25 @@ def lister(self, header, elements, sort=True):
97103

98104
if elements:
99105
self.__write("")
100-
106+
107+
def technic(self,header,data):
108+
self.string(header, data)
109+
110+
def banner(self,data):
111+
self.string("banner", data)
112+
113+
def currentUser(self,data):
114+
self.string("current user", data)
115+
116+
def currentDb(self,data):
117+
self.string("current database", data)
118+
119+
def dba(self,data):
120+
self.string("current user is DBA", data)
121+
122+
def users(self,users):
123+
self.lister("database management system users", users)
124+
101125
def userSettings(self, header, userSettings, subHeader):
102126
self.__areAdmins = set()
103127

@@ -125,35 +149,8 @@ def userSettings(self, header, userSettings, subHeader):
125149
self.__write(" %s: %s" % (subHeader, setting))
126150
print
127151

128-
def dbColumns(self, dbColumns, colConsider, dbs):
129-
for column in dbColumns.keys():
130-
if colConsider == "1":
131-
colConsiderStr = "s like '" + column + "' were"
132-
else:
133-
colConsiderStr = " '%s' was" % column
134-
135-
msg = "Column%s found in the " % colConsiderStr
136-
msg += "following databases:"
137-
self.__write(msg)
138-
139-
printDbs = {}
140-
141-
for db, tblData in dbs.items():
142-
for tbl, colData in tblData.items():
143-
for col, dataType in colData.items():
144-
if column.lower() in col.lower():
145-
if db in printDbs:
146-
if tbl in printDbs[db]:
147-
printDbs[db][tbl][col] = dataType
148-
else:
149-
printDbs[db][tbl] = { col: dataType }
150-
else:
151-
printDbs[db] = {}
152-
printDbs[db][tbl] = { col: dataType }
153-
154-
continue
155-
156-
self.dbTableColumns(printDbs)
152+
def dbs(self,dbs):
153+
self.lister("available databases", dbs)
157154

158155
def dbTables(self, dbTables):
159156
if not isinstance(dbTables, dict):
@@ -268,7 +265,7 @@ def dbTableValues(self, tableValues):
268265
os.makedirs(dumpDbPath, 0755)
269266

270267
dumpFileName = "%s%s%s.csv" % (dumpDbPath, os.sep, table)
271-
dumpFP = codecs.open(dumpFileName, "w", conf.dataEncoding)
268+
dumpFP = codecs.open(dumpFileName, "wb", conf.dataEncoding)
272269

273270
count = int(tableValues["__infos__"]["count"])
274271
separator = ""
@@ -350,6 +347,45 @@ def dbTableValues(self, tableValues):
350347

351348
logger.info("Table '%s.%s' dumped to CSV file '%s'" % (db, table, dumpFileName))
352349

350+
def dbColumns(self, dbColumns, colConsider, dbs):
351+
for column in dbColumns.keys():
352+
if colConsider == "1":
353+
colConsiderStr = "s like '" + column + "' were"
354+
else:
355+
colConsiderStr = " '%s' was" % column
356+
357+
msg = "Column%s found in the " % colConsiderStr
358+
msg += "following databases:"
359+
self.__write(msg)
360+
361+
printDbs = {}
362+
363+
for db, tblData in dbs.items():
364+
for tbl, colData in tblData.items():
365+
for col, dataType in colData.items():
366+
if column.lower() in col.lower():
367+
if db in printDbs:
368+
if tbl in printDbs[db]:
369+
printDbs[db][tbl][col] = dataType
370+
else:
371+
printDbs[db][tbl] = { col: dataType }
372+
else:
373+
printDbs[db] = {}
374+
printDbs[db][tbl] = { col: dataType }
375+
376+
continue
377+
378+
self.dbTableColumns(printDbs)
379+
380+
def query(self, query, queryRes):
381+
self.string(query, queryRes)
382+
383+
def rFile(self,filePath,fileData):
384+
self.string("%s file saved to" % filePath,fileData,sort=False)
385+
386+
def registerValue(self,registerData):
387+
self.string("Registry key value data", registerData,sort=False)
388+
353389
# object to manage how to print the retrieved queries output to
354390
# standard output and sessions file
355391
dumper = Dump()

lib/core/optiondict.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,6 @@
110110
"limitStop": "integer",
111111
"firstChar": "integer",
112112
"lastChar": "integer",
113-
"getNumOfTables": "integer",
114-
"getNumOfDBs": "integer",
115113
"query": "string",
116114
"sqlShell": "boolean"
117115
},

lib/core/target.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from lib.core.exception import sqlmapGenericException
3838
from lib.core.exception import sqlmapSyntaxException
3939
from lib.core.session import resumeConfKb
40+
from lib.core.xmldump import dumper as xmldumper
4041

4142
def __setRequestParams():
4243
"""
@@ -202,6 +203,14 @@ def __createDumpDir():
202203
if not os.path.isdir(conf.dumpPath):
203204
os.makedirs(conf.dumpPath, 0755)
204205

206+
def __configureDumper():
207+
if conf.xmlFile:
208+
conf.dumper = xmldumper
209+
else:
210+
conf.dumper = dumper
211+
212+
conf.dumper.setOutputFile()
213+
205214
def __createTargetDirs():
206215
"""
207216
Create the output directory.
@@ -215,10 +224,9 @@ def __createTargetDirs():
215224
if not os.path.isdir(conf.outputPath):
216225
os.makedirs(conf.outputPath, 0755)
217226

218-
dumper.setOutputFile()
219-
220227
__createDumpDir()
221228
__createFilesDir()
229+
__configureDumper()
222230

223231
def initTargetEnv():
224232
"""

0 commit comments

Comments
 (0)