Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/plugins/generic/custom.py
2989 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 __future__ import print_function
9
10
import re
11
import sys
12
13
from lib.core.common import Backend
14
from lib.core.common import dataToStdout
15
from lib.core.common import getSQLSnippet
16
from lib.core.common import isListLike
17
from lib.core.common import isStackingAvailable
18
from lib.core.common import joinValue
19
from lib.core.compat import xrange
20
from lib.core.convert import getUnicode
21
from lib.core.data import conf
22
from lib.core.data import logger
23
from lib.core.dicts import SQL_STATEMENTS
24
from lib.core.enums import AUTOCOMPLETE_TYPE
25
from lib.core.enums import DBMS
26
from lib.core.exception import SqlmapNoneDataException
27
from lib.core.settings import METADB_SUFFIX
28
from lib.core.settings import NULL
29
from lib.core.settings import PARAMETER_SPLITTING_REGEX
30
from lib.core.shell import autoCompletion
31
from lib.request import inject
32
from thirdparty.six.moves import input as _input
33
34
class Custom(object):
35
"""
36
This class defines custom enumeration functionalities for plugins.
37
"""
38
39
def __init__(self):
40
pass
41
42
def sqlQuery(self, query):
43
output = None
44
sqlType = None
45
query = query.rstrip(';')
46
47
48
try:
49
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
50
for sqlStatement in sqlStatements:
51
if query.lower().startswith(sqlStatement):
52
sqlType = sqlTitle
53
break
54
55
if not re.search(r"\b(OPENROWSET|INTO)\b", query, re.I) and (not sqlType or "SELECT" in sqlType):
56
infoMsg = "fetching %s query output: '%s'" % (sqlType if sqlType is not None else "SQL", query)
57
logger.info(infoMsg)
58
59
if Backend.isDbms(DBMS.MSSQL):
60
match = re.search(r"(\bFROM\s+)([^\s]+)", query, re.I)
61
if match and match.group(2).count('.') == 1:
62
query = query.replace(match.group(0), "%s%s" % (match.group(1), match.group(2).replace('.', ".dbo.")))
63
64
query = re.sub(r"(?i)\w+%s\.?" % METADB_SUFFIX, "", query)
65
66
output = inject.getValue(query, fromUser=True)
67
68
if sqlType and "SELECT" in sqlType and isListLike(output):
69
for i in xrange(len(output)):
70
if isListLike(output[i]):
71
output[i] = joinValue(output[i])
72
73
return output
74
elif not isStackingAvailable() and not conf.direct:
75
warnMsg = "execution of non-query SQL statements is only "
76
warnMsg += "available when stacked queries are supported"
77
logger.warning(warnMsg)
78
79
return None
80
else:
81
if sqlType:
82
infoMsg = "executing %s statement: '%s'" % (sqlType if sqlType is not None else "SQL", query)
83
else:
84
infoMsg = "executing unknown SQL command: '%s'" % query
85
logger.info(infoMsg)
86
87
inject.goStacked(query)
88
89
output = NULL
90
91
except SqlmapNoneDataException as ex:
92
logger.warning(ex)
93
94
return output
95
96
def sqlShell(self):
97
infoMsg = "calling %s shell. To quit type " % Backend.getIdentifiedDbms()
98
infoMsg += "'x' or 'q' and press ENTER"
99
logger.info(infoMsg)
100
101
autoCompletion(AUTOCOMPLETE_TYPE.SQL)
102
103
while True:
104
query = None
105
106
try:
107
query = _input("sql-shell> ")
108
query = getUnicode(query, encoding=sys.stdin.encoding)
109
query = query.strip("; ")
110
except UnicodeDecodeError:
111
print()
112
errMsg = "invalid user input"
113
logger.error(errMsg)
114
except KeyboardInterrupt:
115
print()
116
errMsg = "user aborted"
117
logger.error(errMsg)
118
except EOFError:
119
print()
120
errMsg = "exit"
121
logger.error(errMsg)
122
break
123
124
if not query:
125
continue
126
127
if query.lower() in ("x", "q", "exit", "quit"):
128
break
129
130
output = self.sqlQuery(query)
131
132
if output and output != "Quit":
133
conf.dumper.sqlQuery(query, output)
134
135
elif not output:
136
pass
137
138
elif output != "Quit":
139
dataToStdout("No output\n")
140
141
def sqlFile(self):
142
infoMsg = "executing SQL statements from given file(s)"
143
logger.info(infoMsg)
144
145
for filename in re.split(PARAMETER_SPLITTING_REGEX, conf.sqlFile):
146
filename = filename.strip()
147
148
if not filename:
149
continue
150
151
snippet = getSQLSnippet(Backend.getDbms(), filename)
152
153
if snippet and all(query.strip().upper().startswith("SELECT") for query in (_ for _ in snippet.split(';' if ';' in snippet else '\n') if _)):
154
for query in (_ for _ in snippet.split(';' if ';' in snippet else '\n') if _):
155
query = query.strip()
156
if query:
157
conf.dumper.sqlQuery(query, self.sqlQuery(query))
158
else:
159
conf.dumper.sqlQuery(snippet, self.sqlQuery(snippet))
160
161