Example #1
0
    def __init__(self, source_host, port=50000, target=None):
        """
        Creates a metasploit class to connect and use metasploit functionality.

        Args:
            source_host (str): the host that uses metasploit.
            port (int): on which port the msfrpc listens to.
            target (str): target host to perform actions.

        Raises:
            MsfrpcdConnectionError: in case metasploit connection attempt has failed.
            InvalidHostName: in case the provided target host name is invalid.
        """
        self._source_host = source_host

        try:
            if target:
                self._target_host = socket.gethostbyname(target)
                self._ssh = SSH(hostname=source_host)
                ping_cmd = f"ping -c3 {self._target_host}"
                is_ping_success, _ = self._ssh.execute_commands(
                    commands=[ping_cmd])
                if not is_ping_success:
                    raise HostIsUnreachable(source_host=self._source_host,
                                            target_host=self._target_host)
        except socket.gaierror:
            raise InvalidHostName(invalid_host=target)

        try:
            self._metasploit = Metasploit(server=source_host, port=port)
        except ConnectionError:
            raise MsfrpcdConnectionError(host=source_host, port=port)
Example #2
0
    def __init__(self, docker_server_ip, protocol='tcp', docker_port=2375):
        """
        Initialize the connection to the docker server over an AWS ec2 instance using a chosen protocol,
        docker server ip and a port that the docker server listens to.

        Args:
            docker_server_ip (str): the docker server public ip.
            protocol (str): a protocol to use in order to connect to the docker server. etc: tcp/udp.
            docker_port (int): the port that the docker server listens to.
        """
        base_url = f"{protocol}://{docker_server_ip}:{docker_port}"

        ssh = None
        connection_attempts = 0
        while connection_attempts < 5:
            try:
                self._docker_client = docker.DockerClient(base_url=base_url)
                self._api_client = docker.APIClient(base_url=base_url)

                self._docker_client.ping()
                break
            except ConnectionError:
                if not ssh:
                    ssh = SSH(hostname=docker_server_ip)

                are_commands_successful, cmd = ssh.execute_commands(commands=aws_const.RELOAD_DOCKER_DAEMON)
                if not are_commands_successful:
                    raise CommandFailureError(cmd=cmd, instance_fqdn=docker_server_ip)

                connection_attempts += 1

        if connection_attempts >= 5:
            raise DockerServerConnectionError(docker_server=docker_server_ip, url=base_url)
Example #3
0
    def __init__(self, instance_obj, ssh_flag=False, init_docker_server_flag=False):
        """
        Args:
            instance_obj (Aws.Instance): Aws instance obj.
            ssh_flag (bool): indicate if the instance requires a SSH connection.
            True to open connection, False otherwise.
            init_docker_server_flag (bool): indicate if the instance needs to be configured with a docker server.
            True to deploy docker server, False means it's already deployed.

        """
        self._instance_obj = instance_obj

        if ssh_flag:
            self._ssh = SSH(hostname=self.public_dns_name)

        if init_docker_server_flag:
            self._init_docker_server_on_instance()

        self._docker = Docker(docker_server_ip=self.public_dns_name)
Example #4
0
def stop_docker_daemon(docker_server_dns):
    """
    Stops the docker servers docker daemon.
    """
    stop_docker_daemon_cmd = ["sudo systemctl stop docker"]

    for docker_dns in docker_server_dns:
        logger.info(f"Stop docker daemon at {docker_dns}")
        is_cmd_success, cmd = SSH(hostname=docker_dns).execute_commands(commands=stop_docker_daemon_cmd)

        assert is_cmd_success, f"Failed to stop docker daemon at {docker_dns} using cmd {cmd}"
Example #5
0
    def __init__(self, docker_server_ip, protocol='tcp', docker_port=2375, max_connection_attempts=5):
        """
        Initialize the connection to the docker server over an AWS ec2 instance using a chosen protocol,
        docker server ip and a port that the docker server listens to.

        Args:
            docker_server_ip (str): the docker server public ip.
            protocol (str): a protocol to use in order to connect to the docker server. etc: tcp/udp.
            docker_port (int): the port that the docker server listens to.
            max_connection_attempts (int): maximum times to try and connect the docker API.
        """
        base_url = f"{protocol}://{docker_server_ip}:{docker_port}"

        is_docker_daemon_recovered = False
        ssh = None
        connection_attempts = 0
        while connection_attempts < max_connection_attempts:
            try:

                self._docker_client = docker.DockerClient(base_url=base_url)
                self._api_client = docker.APIClient(base_url=base_url)

                if self._docker_client.ping():
                    if is_docker_daemon_recovered:
                        recover_containers(containers=self._docker_client.containers.list(all=True))
                    break
            except (ConnectionError, DockerException):
                if not ssh:
                    ssh = SSH(hostname=docker_server_ip)

                are_commands_successful, cmd = ssh.execute_commands(commands=aws_const.RELOAD_DOCKER_DAEMON)
                if not are_commands_successful:
                    raise CommandFailureError(cmd=cmd, instance_fqdn=docker_server_ip)

                connection_attempts += 1
                is_docker_daemon_recovered = True

        if connection_attempts >= max_connection_attempts:
            raise DockerServerConnectionError(docker_server=docker_server_ip, url=base_url)
Example #6
0
class DockerServerInstance(object):
    """
    This class represents an instance in AWS with a docker server configured.

    Attributes:
        _instance_obj (Aws.Instance): a aws instance obj.
        _ssh (SSH): a SSH client that opens a connection to the instance.
        _docker (Docker): a docker class that represents docker-container over an instance.
    """

    def __init__(self, instance_obj, ssh_flag=False, init_docker_server_flag=False):
        """
        Args:
            instance_obj (Aws.Instance): Aws instance obj.
            ssh_flag (bool): indicate if the instance requires a SSH connection.
            True to open connection, False otherwise.
            init_docker_server_flag (bool): indicate if the instance needs to be configured with a docker server.
            True to deploy docker server, False means it's already deployed.

        """
        self._instance_obj = instance_obj

        if ssh_flag:
            self._ssh = SSH(hostname=self.public_dns_name)

        if init_docker_server_flag:
            self._init_docker_server_on_instance()

        self._docker = Docker(docker_server_ip=self.public_dns_name)

    @property
    def docker(self):
        return self._docker

    @property
    def instance_id(self):
        return self._instance_obj.instance_id

    @property
    def public_ip_address(self):
        return self._instance_obj.public_ip_address

    @property
    def public_dns_name(self):
        return self._instance_obj.public_dns_name

    @property
    def state(self):
        return self._instance_obj.state

    @property
    def key_name(self):
        return self._instance_obj.key_name

    @property
    def security_groups(self):
        return self._instance_obj.security_groups

    @property
    def image_id(self):
        return self._instance_obj.image_id

    @property
    def private_ip_address(self):
        return self._instance_obj.private_ip_address

    @property
    def private_dns_name(self):
        return self._instance_obj.private_dns_name

    @property
    def instance_obj(self):
        return self._instance_obj

    def _reload(self):
        self._instance_obj.reload()

    def start(self):
        """
        Start the instance and wait till is is on running state
        """
        if self.state['Name'] == aws_constants.STOPPED_STATE:
            self._instance_obj.start()
            self._instance_obj.wait_until_running()
            self._reload()

    def stop(self):
        """
        Stop the instance and wait till it's in a stopped state
        """
        if self.state['Name'] == aws_constants.RUNNING_STATE:
            self._instance_obj.stop()
            self._instance_obj.wait_until_stopped()
            self._reload()

    def reboot(self):
        """
        Reboot the instance and wait till it's in a running state
        """
        if self.state['Name'] == aws_constants.RUNNING_STATE:
            self._instance_obj.reboot()
            self._instance_obj.wait_until_running()
            self._reload()

    def terminate(self):
        """
        Terminate the instance and delete the current instance
        """
        self._instance_obj.terminate()

    def execute_shell_commands(self, commands):
        """
        Executes the given commands over the instance.

        Args:
            commands (list(str)) - list of all the commands to execute on the instance.

        Raises:
            CommandFailureError in case the command fails over the instance
        """
        if self.state['Name'] == aws_constants.RUNNING_STATE:
            are_commands_successful, cmd = self._ssh.execute_commands(commands=commands)
            if not are_commands_successful:
                raise CommandFailureError(
                    cmd=cmd, instance_fqdn=self.public_dns_name
                )

    def write_to_file(self, filename, mode, data=None):
        """
        Write to a file in the instance.

        Args:
            filename (str): the exact file path. etc: /etc/docker/my_file.
            mode (str): read or write on the file etc ("w" for write, "r" for read).
            data (str): which data should be written on the file.

        Returns:
            True if the write operation is success, False otherwise.
        """
        sftp = self._ssh.get_sftp()

        file_obj = sftp.open(filename=filename, mode=mode)
        if mode == 'w':
            file_obj.write(data=data)

    def _init_docker_server_on_instance(self):
        """
        Initialize the docker server over an instance in AWS.
        """
        self.execute_shell_commands(
            commands=aws_constants.MAKE_DOCKER_FILES_COMMANDS
        )

        self.write_to_file(
            filename='/etc/docker/daemon.json',
            mode='w',
            data='{"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]}\n'
        )

        self.write_to_file(
            filename='/etc/systemd/system/docker.service.d/override.conf',
            mode='w',
            data='[Service]\nExecStart=\nExecStart=/usr/bin/dockerd\n'
        )

        self.execute_shell_commands(
            commands=aws_constants.RELOAD_DOCKER_DAEMON
        )
Example #7
0
class MetasploitModule(object):
    def __init__(self, source_host, port=50000, target=None):
        """
        Creates a metasploit class to connect and use metasploit functionality.

        Args:
            source_host (str): the host that uses metasploit.
            port (int): on which port the msfrpc listens to.
            target (str): target host to perform actions.

        Raises:
            MsfrpcdConnectionError: in case metasploit connection attempt has failed.
            InvalidHostName: in case the provided target host name is invalid.
        """
        self._source_host = source_host

        try:
            if target:
                self._target_host = socket.gethostbyname(target)
                self._ssh = SSH(hostname=source_host)
                ping_cmd = f"ping -c3 {self._target_host}"
                is_ping_success, _ = self._ssh.execute_commands(
                    commands=[ping_cmd])
                if not is_ping_success:
                    raise HostIsUnreachable(source_host=self._source_host,
                                            target_host=self._target_host)
        except socket.gaierror:
            raise InvalidHostName(invalid_host=target)

        try:
            self._metasploit = Metasploit(server=source_host, port=port)
        except ConnectionError:
            raise MsfrpcdConnectionError(host=source_host, port=port)

    def init_module(self, module_name, module_type):
        """
        initializes the requested module of the metasploit.

        Args:
            module_name (str): module name.
            module_type (str): module type.

        Returns:
            MsfModule: a msfmodule object. e.g. ExploitModule, AuxiliaryModule, PayloadModule.
        """
        return self._metasploit.modules.use(mtype=module_type,
                                            mname=module_name)

    def execute_shell_commands(self, commands, session_id):
        """
        Executes shell commands on a remote host that we gained a remote shell to.

        Args:
            commands (list(str)): a list of commands to execute.
            session_id (str): session ID of the required shell.

        Yields:
            str: output of a command that was executed in the remote shell.
        """
        shell = self._metasploit.metasploit_client.sessions.session(
            sid=session_id)

        for cmd in commands:
            shell.write(data=cmd)
            yield shell.read()

    def execute_host_console_commands(self, commands, timeout=90, sleep=3):
        """
        executes host console commands in msf console.

        Args:
            commands (list(str)): set of commands to be done on the msf console.
            timeout (int): timeout limit to sample the duration of each command.
            sleep (int): sleep time between each sampling of the console status for every command.

        Yields:
            str: data output from the console of each command.
        """
        console = self._metasploit.host_console

        for cmd in commands:
            console.write(command=cmd)
            try:
                for is_busy in TimeoutSampler(timeout=timeout,
                                              sleep=sleep,
                                              func=console.is_busy):
                    if not is_busy:
                        break
            except TimeoutExpiredError:
                pass
            yield console.read()["data"]

        self._metasploit.destory_console()

    def job_info(self, job_id):
        """
        Gets information about an existing job in metasploit, ignores jobs that produce errors.

        Args:
            job_id (int): job ID.

        Returns:
            dict: job information in case exists, empty dict otherwise.
        """
        if str(job_id) in self._metasploit.metasploit_client.jobs.list:
            job_details = self._metasploit.metasploit_client.jobs.info(
                jobid=job_id)
            if "error" not in job_details:
                return job_details
        return {}

    def stop_job(self, job_id):
        """
        Stops a job performed by metasploit.

        Args:
            job_id (int): job ID.

        Returns:
            bool: True if job was stopped successfully, False otherwise.
        """
        self._metasploit.metasploit_client.jobs.stop(jobid=job_id)
        return True if str(
            job_id
        ) not in self._metasploit.metasploit_client.jobs.list else False

    def build_module(self, name, options, type='payload'):
        """
        Builds up the MsfModule along with the options for the module.

        Args:
            name (str): module name.
            options (dict): module options.
            type (str): module type.

        Returns:
            MsfModule: a msfmodule object. e.g. ExploitModule, PayloadModule.
        """
        msf_module = self.init_module(module_name=name, module_type=type)

        for option, option_value in options.items():
            msf_module[option] = option_value
        return msf_module

    def execute(self, *args, **kwargs):
        """
        Base method to execute metasploit modules.
        """
        pass

    def info(self, *args, **kwargs):
        """
        Base method to collect information about metasploit modules.
        """
        pass