mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-22 01:26:42 +03:00
Implementation for an Issue #832
This commit is contained in:
parent
57eb19377e
commit
7278af01ee
|
@ -342,3 +342,4 @@ class AUTH_TYPE:
|
||||||
class AUTOCOMPLETE_TYPE:
|
class AUTOCOMPLETE_TYPE:
|
||||||
SQL = 0
|
SQL = 0
|
||||||
OS = 1
|
OS = 1
|
||||||
|
SQLMAP = 2
|
||||||
|
|
|
@ -44,6 +44,9 @@ class SqlmapSilentQuitException(SqlmapBaseException):
|
||||||
class SqlmapUserQuitException(SqlmapBaseException):
|
class SqlmapUserQuitException(SqlmapBaseException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class SqlmapShellQuitException(SqlmapBaseException):
|
||||||
|
pass
|
||||||
|
|
||||||
class SqlmapSyntaxException(SqlmapBaseException):
|
class SqlmapSyntaxException(SqlmapBaseException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -239,6 +239,7 @@ BASIC_HELP_ITEMS = (
|
||||||
"checkTor",
|
"checkTor",
|
||||||
"flushSession",
|
"flushSession",
|
||||||
"tor",
|
"tor",
|
||||||
|
"sqlmapShell",
|
||||||
"wizard",
|
"wizard",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -583,6 +584,9 @@ MIN_BINARY_DISK_DUMP_SIZE = 100
|
||||||
# Regular expression used for extracting form tags
|
# Regular expression used for extracting form tags
|
||||||
FORM_SEARCH_REGEX = r"(?si)<form(?!.+<form).+?</form>"
|
FORM_SEARCH_REGEX = r"(?si)<form(?!.+<form).+?</form>"
|
||||||
|
|
||||||
|
# Maximum number of lines to save in history file
|
||||||
|
MAX_HISTORY_LENGTH = 1000
|
||||||
|
|
||||||
# Minimum field entry length needed for encoded content (hex, base64,...) check
|
# Minimum field entry length needed for encoded content (hex, base64,...) check
|
||||||
MIN_ENCODED_LEN_CHECK = 5
|
MIN_ENCODED_LEN_CHECK = 5
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,39 @@ from lib.core.data import logger
|
||||||
from lib.core.data import paths
|
from lib.core.data import paths
|
||||||
from lib.core.enums import AUTOCOMPLETE_TYPE
|
from lib.core.enums import AUTOCOMPLETE_TYPE
|
||||||
from lib.core.enums import OS
|
from lib.core.enums import OS
|
||||||
|
from lib.core.settings import MAX_HISTORY_LENGTH
|
||||||
|
|
||||||
|
def readlineAvailable():
|
||||||
|
"""
|
||||||
|
Check if the readline is available. By default
|
||||||
|
it is not in Python default installation on Windows
|
||||||
|
"""
|
||||||
|
|
||||||
|
return readline._readline is not None
|
||||||
|
|
||||||
|
def clearHistory():
|
||||||
|
if not readlineAvailable():
|
||||||
|
return
|
||||||
|
|
||||||
|
readline.clear_history()
|
||||||
|
|
||||||
def saveHistory():
|
def saveHistory():
|
||||||
|
if not readlineAvailable():
|
||||||
|
return
|
||||||
|
|
||||||
historyPath = os.path.expanduser(paths.SQLMAP_SHELL_HISTORY)
|
historyPath = os.path.expanduser(paths.SQLMAP_SHELL_HISTORY)
|
||||||
|
try:
|
||||||
|
os.remove(historyPath)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
readline.set_history_length(MAX_HISTORY_LENGTH)
|
||||||
readline.write_history_file(historyPath)
|
readline.write_history_file(historyPath)
|
||||||
|
|
||||||
def loadHistory():
|
def loadHistory():
|
||||||
|
if not readlineAvailable():
|
||||||
|
return
|
||||||
|
|
||||||
historyPath = os.path.expanduser(paths.SQLMAP_SHELL_HISTORY)
|
historyPath = os.path.expanduser(paths.SQLMAP_SHELL_HISTORY)
|
||||||
|
|
||||||
if os.path.exists(historyPath):
|
if os.path.exists(historyPath):
|
||||||
|
@ -47,15 +74,13 @@ class CompleterNG(rlcompleter.Completer):
|
||||||
matches.append(word)
|
matches.append(word)
|
||||||
|
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
def autoCompletion(completion=None):
|
def autoCompletion(completion=None, os=None, commands=None):
|
||||||
# First of all we check if the readline is available, by default
|
if not readlineAvailable():
|
||||||
# it is not in Python default installation on Windows
|
|
||||||
if not readline._readline:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if completion == AUTOCOMPLETE_TYPE.OS:
|
if completion == AUTOCOMPLETE_TYPE.OS:
|
||||||
if Backend.isOs(OS.WINDOWS):
|
if os == OS.WINDOWS:
|
||||||
# Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands
|
# Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands
|
||||||
completer = CompleterNG({
|
completer = CompleterNG({
|
||||||
"copy": None, "del": None, "dir": None,
|
"copy": None, "del": None, "dir": None,
|
||||||
|
@ -76,5 +101,11 @@ def autoCompletion(completion=None):
|
||||||
readline.set_completer(completer.complete)
|
readline.set_completer(completer.complete)
|
||||||
readline.parse_and_bind("tab: complete")
|
readline.parse_and_bind("tab: complete")
|
||||||
|
|
||||||
|
elif commands:
|
||||||
|
completer = CompleterNG(dict(((_, None) for _ in commands)))
|
||||||
|
readline.set_completer_delims(' ')
|
||||||
|
readline.set_completer(completer.complete)
|
||||||
|
readline.parse_and_bind("tab: complete")
|
||||||
|
|
||||||
loadHistory()
|
loadHistory()
|
||||||
atexit.register(saveHistory)
|
atexit.register(saveHistory)
|
||||||
|
|
|
@ -6,6 +6,7 @@ See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from optparse import OptionError
|
from optparse import OptionError
|
||||||
|
@ -17,13 +18,21 @@ from lib.core.common import checkDeprecatedOptions
|
||||||
from lib.core.common import checkSystemEncoding
|
from lib.core.common import checkSystemEncoding
|
||||||
from lib.core.common import expandMnemonics
|
from lib.core.common import expandMnemonics
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
|
from lib.core.data import cmdLineOptions
|
||||||
|
from lib.core.data import conf
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.defaults import defaults
|
from lib.core.defaults import defaults
|
||||||
|
from lib.core.enums import AUTOCOMPLETE_TYPE
|
||||||
|
from lib.core.exception import SqlmapShellQuitException
|
||||||
from lib.core.settings import BASIC_HELP_ITEMS
|
from lib.core.settings import BASIC_HELP_ITEMS
|
||||||
from lib.core.settings import DUMMY_URL
|
from lib.core.settings import DUMMY_URL
|
||||||
from lib.core.settings import IS_WIN
|
from lib.core.settings import IS_WIN
|
||||||
from lib.core.settings import MAX_HELP_OPTION_LENGTH
|
from lib.core.settings import MAX_HELP_OPTION_LENGTH
|
||||||
from lib.core.settings import VERSION_STRING
|
from lib.core.settings import VERSION_STRING
|
||||||
|
from lib.core.shell import autoCompletion
|
||||||
|
from lib.core.shell import clearHistory
|
||||||
|
from lib.core.shell import loadHistory
|
||||||
|
from lib.core.shell import saveHistory
|
||||||
|
|
||||||
def cmdLineParser():
|
def cmdLineParser():
|
||||||
"""
|
"""
|
||||||
|
@ -693,6 +702,9 @@ def cmdLineParser():
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Conduct through tests only if positive heuristic(s)")
|
help="Conduct through tests only if positive heuristic(s)")
|
||||||
|
|
||||||
|
miscellaneous.add_option("--sqlmap-shell", dest="sqlmapShell", action="store_true",
|
||||||
|
help="Prompt for an interactive sqlmap shell")
|
||||||
|
|
||||||
miscellaneous.add_option("--wizard", dest="wizard",
|
miscellaneous.add_option("--wizard", dest="wizard",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Simple wizard interface for beginner users")
|
help="Simple wizard interface for beginner users")
|
||||||
|
@ -765,22 +777,25 @@ def cmdLineParser():
|
||||||
option = parser.get_option("-h")
|
option = parser.get_option("-h")
|
||||||
option.help = option.help.capitalize().replace("this help", "basic help")
|
option.help = option.help.capitalize().replace("this help", "basic help")
|
||||||
|
|
||||||
args = []
|
argv = []
|
||||||
|
prompt = False
|
||||||
advancedHelp = True
|
advancedHelp = True
|
||||||
|
|
||||||
for arg in sys.argv:
|
for arg in sys.argv:
|
||||||
args.append(getUnicode(arg, system=True))
|
argv.append(getUnicode(arg, system=True))
|
||||||
|
|
||||||
checkDeprecatedOptions(args)
|
checkDeprecatedOptions(argv)
|
||||||
|
|
||||||
# Hide non-basic options in basic help case
|
# Hide non-basic options in basic help case
|
||||||
for i in xrange(len(sys.argv)):
|
for i in xrange(len(sys.argv)):
|
||||||
if sys.argv[i] == '-hh':
|
if sys.argv[i] == "-hh":
|
||||||
sys.argv[i] = '-h'
|
sys.argv[i] = "-h"
|
||||||
elif sys.argv[i] == '--version':
|
elif sys.argv[i] == "--version":
|
||||||
print VERSION_STRING
|
print VERSION_STRING
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
elif sys.argv[i] == '-h':
|
elif sys.argv[i] == "--sqlmap-shell":
|
||||||
|
prompt = True
|
||||||
|
elif sys.argv[i] == "-h":
|
||||||
advancedHelp = False
|
advancedHelp = False
|
||||||
for group in parser.option_groups[:]:
|
for group in parser.option_groups[:]:
|
||||||
found = False
|
found = False
|
||||||
|
@ -792,17 +807,56 @@ def cmdLineParser():
|
||||||
if not found:
|
if not found:
|
||||||
parser.option_groups.remove(group)
|
parser.option_groups.remove(group)
|
||||||
|
|
||||||
|
if prompt:
|
||||||
|
cmdLineOptions.sqlmapShell = True
|
||||||
|
|
||||||
|
_ = ["x", "q", "exit", "quit", "clear"]
|
||||||
|
for group in parser.option_groups:
|
||||||
|
for option in group.option_list:
|
||||||
|
_.extend(option._long_opts)
|
||||||
|
_.extend(option._short_opts)
|
||||||
|
|
||||||
|
autoCompletion(AUTOCOMPLETE_TYPE.SQLMAP, commands=_)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
command = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
command = raw_input("sqlmap-shell> ").strip()
|
||||||
|
except (KeyboardInterrupt, EOFError):
|
||||||
|
print
|
||||||
|
raise SqlmapShellQuitException
|
||||||
|
|
||||||
|
if not command:
|
||||||
|
continue
|
||||||
|
elif command.lower() == "clear":
|
||||||
|
clearHistory()
|
||||||
|
print "[i] history cleared"
|
||||||
|
saveHistory()
|
||||||
|
elif command.lower() in ("x", "q", "exit", "quit"):
|
||||||
|
raise SqlmapShellQuitException
|
||||||
|
elif command[0] != '-':
|
||||||
|
print "[!] invalid option(s) provided"
|
||||||
|
print "[i] proper example: '-u http://www.site.com/vuln.php?id=1 --banner'"
|
||||||
|
else:
|
||||||
|
saveHistory()
|
||||||
|
loadHistory()
|
||||||
|
break
|
||||||
|
|
||||||
|
for arg in shlex.split(command):
|
||||||
|
argv.append(getUnicode(arg, system=True))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
(args, _) = parser.parse_args(args)
|
(args, _) = parser.parse_args(argv)
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
if '-h' in sys.argv and not advancedHelp:
|
if "-h" in sys.argv and not advancedHelp:
|
||||||
print "\n[!] to see full list of options run with '-hh'"
|
print "\n[!] to see full list of options run with '-hh'"
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# Expand given mnemonic options (e.g. -z "ign,flu,bat")
|
# Expand given mnemonic options (e.g. -z "ign,flu,bat")
|
||||||
for i in xrange(len(sys.argv) - 1):
|
for i in xrange(len(argv) - 1):
|
||||||
if sys.argv[i] == '-z':
|
if argv[i] == "-z":
|
||||||
expandMnemonics(sys.argv[i + 1], parser, args)
|
expandMnemonics(argv[i + 1], parser, args)
|
||||||
|
|
||||||
if args.dummy:
|
if args.dummy:
|
||||||
args.url = args.url or DUMMY_URL
|
args.url = args.url or DUMMY_URL
|
||||||
|
|
|
@ -15,6 +15,7 @@ from lib.core.data import conf
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.enums import AUTOCOMPLETE_TYPE
|
from lib.core.enums import AUTOCOMPLETE_TYPE
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.enums import OS
|
||||||
from lib.core.exception import SqlmapFilePathException
|
from lib.core.exception import SqlmapFilePathException
|
||||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
from lib.core.shell import autoCompletion
|
from lib.core.shell import autoCompletion
|
||||||
|
@ -117,7 +118,7 @@ class Abstraction(Web, UDF, Xp_cmdshell):
|
||||||
infoMsg += "'x' or 'q' and press ENTER"
|
infoMsg += "'x' or 'q' and press ENTER"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
autoCompletion(AUTOCOMPLETE_TYPE.OS)
|
autoCompletion(AUTOCOMPLETE_TYPE.OS, OS.WINDOWS if Backend.isOs(OS.WINDOWS) else OS.LINUX)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
command = None
|
command = None
|
||||||
|
|
12
sqlmap.py
12
sqlmap.py
|
@ -33,6 +33,7 @@ from lib.core.data import logger
|
||||||
from lib.core.data import paths
|
from lib.core.data import paths
|
||||||
from lib.core.common import unhandledExceptionMessage
|
from lib.core.common import unhandledExceptionMessage
|
||||||
from lib.core.exception import SqlmapBaseException
|
from lib.core.exception import SqlmapBaseException
|
||||||
|
from lib.core.exception import SqlmapShellQuitException
|
||||||
from lib.core.exception import SqlmapSilentQuitException
|
from lib.core.exception import SqlmapSilentQuitException
|
||||||
from lib.core.exception import SqlmapUserQuitException
|
from lib.core.exception import SqlmapUserQuitException
|
||||||
from lib.core.option import initOptions
|
from lib.core.option import initOptions
|
||||||
|
@ -101,7 +102,10 @@ def main():
|
||||||
except (SqlmapSilentQuitException, bdb.BdbQuit):
|
except (SqlmapSilentQuitException, bdb.BdbQuit):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
except SqlmapBaseException, ex:
|
except SqlmapShellQuitException:
|
||||||
|
cmdLineOptions.sqlmapShell = False
|
||||||
|
|
||||||
|
except SqlmapBaseException as ex:
|
||||||
errMsg = getUnicode(ex.message)
|
errMsg = getUnicode(ex.message)
|
||||||
logger.critical(errMsg)
|
logger.critical(errMsg)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -138,6 +142,12 @@ def main():
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if cmdLineOptions.get("sqlmapShell"):
|
||||||
|
cmdLineOptions.clear()
|
||||||
|
conf.clear()
|
||||||
|
kb.clear()
|
||||||
|
main()
|
||||||
|
|
||||||
if hasattr(conf, "api"):
|
if hasattr(conf, "api"):
|
||||||
try:
|
try:
|
||||||
conf.database_cursor.disconnect()
|
conf.database_cursor.disconnect()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user