#!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # # SECUREAUTH LABS. Copyright (C) 2021 SecureAuth Corporation. All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # # Description: # [MS-TDS] & [MC-SQLR] example. # # Author: # Alberto Solino (@agsolino) # # Reference for: # Structure # from __future__ import division from __future__ import print_function import argparse import sys import os import logging from impacket.examples import logger from impacket.examples.utils import parse_target from impacket import version, tds if __name__ == '__main__': import cmd class SQLSHELL(cmd.Cmd): def __init__(self, SQL): cmd.Cmd.__init__(self) self.sql = SQL self.prompt = 'SQL> ' self.intro = '[!] Press help for extra shell commands' def do_help(self, line): print(""" lcd {path} - changes the current local directory to {path} exit - terminates the server process (and this session) enable_xp_cmdshell - you know what it means disable_xp_cmdshell - you know what it means xp_cmdshell {cmd} - executes cmd using xp_cmdshell sp_start_job {cmd} - executes cmd using the sql server agent (blind) ! {cmd} - executes a local shell cmd """) def do_shell(self, s): os.system(s) def do_xp_cmdshell(self, s): try: self.sql.sql_query("exec master..xp_cmdshell '%s'" % s) self.sql.printReplies() self.sql.colMeta[0]['TypeData'] = 80*2 self.sql.printRows() except: pass def do_sp_start_job(self, s): try: self.sql.sql_query("DECLARE @job NVARCHAR(100);" "SET @job='IdxDefrag'+CONVERT(NVARCHAR(36),NEWID());" "EXEC msdb..sp_add_job @job_name=@job,@description='INDEXDEFRAG'," "@owner_login_name='sa',@delete_level=3;" "EXEC msdb..sp_add_jobstep @job_name=@job,@step_id=1,@step_name='Defragmentation'," "@subsystem='CMDEXEC',@command='%s',@on_success_action=1;" "EXEC msdb..sp_add_jobserver @job_name=@job;" "EXEC msdb..sp_start_job @job_name=@job;" % s) self.sql.printReplies() self.sql.printRows() except: pass def do_lcd(self, s): if s == '': print(os.getcwd()) else: os.chdir(s) def do_enable_xp_cmdshell(self, line): try: self.sql.sql_query("exec master.dbo.sp_configure 'show advanced options',1;RECONFIGURE;" "exec master.dbo.sp_configure 'xp_cmdshell', 1;RECONFIGURE;") self.sql.printReplies() self.sql.printRows() except: pass def do_disable_xp_cmdshell(self, line): try: self.sql.sql_query("exec sp_configure 'xp_cmdshell', 0 ;RECONFIGURE;exec sp_configure " "'show advanced options', 0 ;RECONFIGURE;") self.sql.printReplies() self.sql.printRows() except: pass def default(self, line): try: self.sql.sql_query(line) self.sql.printReplies() self.sql.printRows() except: pass def emptyline(self): pass def do_exit(self, line): return True # Init the example's logger theme logger.init() print(version.BANNER) parser = argparse.ArgumentParser(add_help = True, description = "TDS client implementation (SSL supported).") parser.add_argument('target', action='store', help='[[domain/]username[:password]@]') parser.add_argument('-port', action='store', default='1433', help='target MSSQL port (default 1433)') parser.add_argument('-db', action='store', help='MSSQL database instance (default None)') parser.add_argument('-windows-auth', action='store_true', default=False, help='whether or not to use Windows ' 'Authentication (default False)') parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') parser.add_argument('-file', type=argparse.FileType('r'), help='input file with commands to execute in the SQL shell') group = parser.add_argument_group('authentication') group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' '(KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ' 'ones specified in the command line') group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication ' '(128 or 256 bits)') group.add_argument('-dc-ip', action='store',metavar = "ip address", help='IP Address of the domain controller. If ' 'ommited it use the domain part (FQDN) specified in the target parameter') if len(sys.argv)==1: parser.print_help() sys.exit(1) options = parser.parse_args() if options.debug is True: logging.getLogger().setLevel(logging.DEBUG) # Print the Library's installation path logging.debug(version.getInstallationPath()) else: logging.getLogger().setLevel(logging.INFO) domain, username, password, address = parse_target(options.target) if domain is None: domain = '' if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: from getpass import getpass password = getpass("Password:") if options.aesKey is not None: options.k = True ms_sql = tds.MSSQL(address, int(options.port)) ms_sql.connect() try: if options.k is True: res = ms_sql.kerberosLogin(options.db, username, password, domain, options.hashes, options.aesKey, kdcHost=options.dc_ip) else: res = ms_sql.login(options.db, username, password, domain, options.hashes, options.windows_auth) ms_sql.printReplies() except Exception as e: logging.debug("Exception:", exc_info=True) logging.error(str(e)) res = False if res is True: shell = SQLSHELL(ms_sql) if options.file is None: shell.cmdloop() else: for line in options.file.readlines(): print("SQL> %s" % line, end=' ') shell.onecmd(line) ms_sql.disconnect()