Example #1
0
    def run(self, target):
        try:
            self.command = Command(self.rawcmd, self.type)
        except CommandException as e:
            logger.error(e)
            return None

        # Build script to run
        if self.type == 'rce-blind':
            logger.warning('WARNING: This attack box must be reachable from the target !')
            logger.info('If target is vulnerable, exploit will try to ping local ' \
                'IP = {localip} from target'.format(
                    localip=NetUtils.get_local_ip_address()))

            print(self.command.get_cmdline(target))

            script = SCRIPT_RCE_BLIND.format(
                exploit_dir=self.directory,
                command=self.command.get_cmdline(target))

        elif self.type == 'rce-standard':
            script = self.command.get_cmdline(target)

        else:
            logger.error('Unsupported exploit type')
            return None

        # Run subprocess
        try:
            logger.info('Exploit will be run from directory: {directory}'.format(
                directory=self.directory))

            proc = subprocess.Popen(script, 
                                    shell=True, 
                                    stdout=subprocess.PIPE, 
                                    stderr=subprocess.STDOUT)

            # Agressivelly get the output
            while True:
                out = proc.stdout.read(1)
                # We put that inside try block to avoid utf8 decoding error
                try:
                    out = out.decode(sys.stdout.encoding)
                    sys.stdout.write(out)
                    self.output += out
                except:
                    pass

                # Break if process has finished
                if out == ''  and proc.poll() != None:
                    break

        except Exception as e:
            logger.error('Error when trying to run command: {exception}'.format(
                exception=e))
            return None

        return self.output
Example #2
0
    def check(self):

        r = Requester.get('{}/console/j_security_check'.format(self.url))
        if 'name="j_password"' in r.text:
            self.interface = 'weblogic-admin'
            self.interface_url = '{}/console/j_security_check'.format(self.url)
            logger.info('Weblogic administration console detected: {}'.format(
                self.interface_url))
            logger.warning('Warning: By default, Weblogic has an account lockout ' \
                'feature (max 5 failures per 5 minutes, lockout duration of 30min)')
            return True

        logger.error('No Weblogic authentication interface detected')
        return False
Example #3
0
    def check(self):

        auth_type = Requester.get_http_auth_type('{}/manager/html'.format(self.url))
        if auth_type is not AuthMode.UNKNOWN:
            self.interface = 'tomcat-manager'
            self.interface_url = '{}/manager/html'.format(self.url)
            self.http_auth_type = auth_type
            logger.info('Tomcat Manager interface detected: {}'.format(
                self.interface_url))
            logger.warning('Warning: By default, Tomcat has an account lockout ' \
                'feature (max 5 failures, lockout duration of 300s)')
            return True

        logger.error('No Tomcat authentication interface detected')
        return False
Example #4
0
    def check(self):
        r = Requester.get(self.url)

        # Cookie potentially returned are kept to be sent in the auth request
        # because sometimes application might reject request if those cookies are not present
        self.cookies = r.cookies

        # Keep HTML source code of the page for diff calculation in heuristics checks
        # to determine if auth has failed/succeeded
        self.page_html = r.text
        soup = BeautifulSoup(r.text, 'html.parser')

        logger.warning('This module is based on heuristics and is prone to '
                       'false negatives/positives')

        # Get all <form> on the page
        forms = soup.find_all('form')
        #print(forms)
        if not forms:
            logger.error('No standard web <form> found on the page')
            return False

        # Detect form with password field
        # 1. Check for standard <input type="password" ...> field
        # 2. Otherwise, check for <input type="text" ...> field with evocative name
        target_form = None
        is_input_password_type_text = False
        i = 0
        for f in forms:
            input_password = f.find(
                'input',
                type=lambda x: x and x.lower() == 'password',
                attrs={'name': True})
            if not input_password:
                input_password = f.find(
                    'input',
                    type=lambda x: x and x.lower() == 'text',
                    attrs={
                        'name':
                        re.compile('.*(pass|pwd|pswd|pssw|pswrd).*',
                                   re.IGNORECASE)
                    })
                if input_password:
                    is_input_password_type_text = True
            if input_password:
                target_form = f
                self.password_field = input_password.attrs['name']
                self.form_number = i
                break
            i += 1

        if target_form:
            logger.info(
                'Standard web authentication <form> seems present on the page')
            logger.info('Detected password field name = {name}'.format(
                name=self.password_field))
        else:
            logger.error(
                'No standard web auth <form> with password field has been detected '
                'on the page')
            return False

        # Get action url (target) used when submitting form
        if target_form.has_attr('action'):
            form_action = target_form.attrs['action']
            # Absolute URL
            if form_action.lower().startswith('http://') \
               or form_action.lower().startswith('https://'):
                self.action_url = form_action
            # Relative path
            else:
                self.action_url = urljoin(self.url, form_action)
        else:
            self.action_url = r.url
        logger.info(
            'Detected form action URL = {url}'.format(url=self.action_url))

        # Get form method (default POST)
        try:
            self.method = target_form.attrs['method'].upper()
        except:
            self.method = 'POST'

        # Detect username field
        inputs_text = target_form.find_all('input',
                                           type=lambda x: x and x.lower() in
                                           ('text', 'email'),
                                           attrs={'name': True})
        if is_input_password_type_text:
            try:
                inputs_text.remove(
                    target_form.find('input',
                                     type=lambda x: x and x.lower() == 'text',
                                     attrs={'name': self.password_field}))
            except:
                pass
        if len(inputs_text) == 0:
            self.username_field = None
        elif len(inputs_text) == 1:
            # If only one input field type=text (except password field), take this one
            self.username_field = inputs_text[0].attrs['name']
        else:
            # Take the one with the most explicit name if found, otherwise the first one
            self.username_field = self.__find_username_field_via_name(
                inputs_text)
            if not self.username_field:
                self.username_field = inputs_text[0].attrs['name']

        # In rare case, username field can have no type
        if not self.username_field:
            inputs_no_type = target_form.find_all('input',
                                                  type=False,
                                                  attrs={'name': True})
            self.username_field = self.__find_username_field_via_name(
                inputs_no_type)

        if self.username_field:
            logger.info('Detected username field name = {name}'.format(
                name=self.username_field))
        else:
            logger.info(
                'No username field detected, probably password-only authentication'
            )

        # Heuristic check of anti-CSRF token
        self.has_csrftoken = target_form.find(
            'input', type=lambda x: x and x.lower() == 'hidden') is not None
        if self.has_csrftoken:
            logger.info(
                'Heuristic check determines form might have anti-CSRF token')

        # Get ordered list of all form parameters
        self.parameters = self.__extract_form_fields(target_form)
        return True
Example #5
0
    def run(self):

        # List supported modules
        if self.args.list:
            print('List of supported modules:')
            for mod in Utils.list_modules():
                print('- {}'.format(mod))
            return

        # Check if target is available
        logger.info(
            'Check if target {url} is reachable...'.format(url=self.args.url))
        try:
            r = Requester.get(self.args.url)
        except RequestException as e:
            logger.error('Target URL seems not reachable:')
            logger.error(e)
            sys.exit(0)
        logger.success('Connection to target OK. HTTP Status {}'.format(
            r.status_code))

        # Handle potential <meta> refresh
        meta_refresh_url = Requester.get_meta_redirect_url(
            r.text, self.args.url)
        if meta_refresh_url:
            logger.info(
                'Meta refresh mechanism has been detected. Following redirect...'
            )
            self.args.url = meta_refresh_url
            try:
                r = Requester.get(self.args.url)
            except RequestException as e:
                logger.error('Redirected URL seems not reachable:')
                logger.error(e)
                sys.exit(0)
            logger.success(
                'Connection to redirection OK. HTTP Status {}'.format(
                    r.status_code))

        # Create wordlist queue
        try:
            self.wordlist = Wordlist(self.args.username, self.args.userlist,
                                     self.args.password, self.args.passlist,
                                     self.args.combolist)
            logger.info('Number of creds that will be tested: {}'.format(
                self.wordlist.length))
        except Exception as e:
            logger.error(e)
            sys.exit(0)

        # Initialize module
        try:
            mod = importlib.import_module('lib.modules.{}'.format(
                self.args.type.capitalize()))
        except Exception as e:
            logger.error('Error while importing module lib.modules.{}'.format(
                self.args.type.capitalize()))
            traceback.print_exc()
            return
        module = getattr(mod, self.args.type.capitalize())(
            self.args.url, verbose=self.args.verbose)

        # Detect authentication interface
        try:
            if not module.check():
                return
        except RequestException as e:
            logger.warning(e)

        # Run bruteforce
        self.run_bruteforcer(module)
        self.output.newline('')

        logger.info('Bruteforce finished !')
        if self.args.verbose:
            if len(self.creds_found) > 0:
                logger.success('{} valid credentials found:'.format(
                    len(self.creds_found)))
                for username, password in self.creds_found:
                    logger.success('{}:{}'.format(username, password))
            else:
                logger.error('No valid credentials found :\'(')
Example #6
0
    def run(self, target, mode, rce_command=''):
        """
        :param Target targer: Target instance
        :param str mode: mode can be either "detect" or "exploit"
        :param str rce_command: RCE command to run when running exploit (requires mode=exploit)
        """
        try:
            if mode == 'detect':
                self.command = Command(self.detection_rawcmd, self.type)
            elif mode == 'exploit':
                self.command = Command(self.exploit_rawcmd, self.type, self.exploit_rce_output)
        except CommandException as e:
            logger.error(e)
            return None

        # Build script to run
        if mode == 'exploit':
            if self.type == 'rce':
                if not self.exploit_rce_output:
                    logger.warning('The exploit will attempt to execute command on remote system but no '
                        'output will be available !')
                    # For RCE exploit without command output in test mode (no rce_command provided):
                    # Use script template that check for reverse connection with ICMP ping and HTTP requests
                    if len(rce_command) == 0:
                        logger.warning('WARNING: This attack box must be reachable from the target !')
                        logger.info('No command supplied to run through RCE, automatic exploit test will be started...')
                        logger.info('If target is vulnerable, exploit will try to ping (ICMP Echo request) and '
                            'to send HTTP request to local IP = {localip} from target'.format(
                                localip=NetUtils.get_local_ip_address()))

                        cmdline = self.command.get_cmdline(target)
                        print(cmdline)

                        script = SCRIPT_RCE_BLIND.format(
                            exploit_dir=self.directory,
                            command=cmdline)
                    else:
                        cmdline = self.command.get_cmdline(target, rce_command)
                        print(cmdline)
                        script  = 'cd {exploit_dir}; '.format(exploit_dir=self.directory)
                        script += cmdline
                else:
                    if len(rce_command) == 0:
                        logger.info('No command supplied to run through RCE, automatic exploit test will be started...')
                        logger.info('If target is vulnerable, exploit will try to run an echo command on target')
                        cmdline = self.command.get_cmdline(target)
                        print(cmdline)
                        script  = 'cd {exploit_dir}; '.format(exploit_dir=self.directory)
                        script += cmdline
                    else:
                        cmdline = self.command.get_cmdline(target, rce_command)
                        print(cmdline)
                        script  = 'cd {exploit_dir}; '.format(exploit_dir=self.directory)
                        script += cmdline                        

            else:
                cmdline = self.command.get_cmdline(target)
                print(cmdline)
                script  = 'cd {exploit_dir}; '.format(exploit_dir=self.directory)
                script += cmdline
        else:
            logger.warning('The script will attempt to detect if remote system is vulnerable without '
                'actually exploiting the vulnerability.')
            logger.warning('WARNING: False Positive is possible !')
            cmdline = self.command.get_cmdline(target)
            script  = 'cd {exploit_dir}; '.format(exploit_dir=self.directory)
            script += cmdline            

        # Run subprocess
        try:
            logger.info('{script} will be run from directory: {directory}'.format(
                script='Exploit' if mode == 'exploit' else 'Detection script',
                directory=self.directory))

            proc = subprocess.Popen(script, 
                                    shell=True, 
                                    executable='/bin/bash',
                                    stdout=subprocess.PIPE, 
                                    stderr=subprocess.STDOUT)

            # Agressivelly get the output
            while True:
                out = proc.stdout.read(1)
                # We put that inside try block to avoid utf8 decoding error
                try:
                    out = out.decode(sys.stdout.encoding)
                    sys.stdout.write(out)
                    self.output += out
                except:
                    pass

                # Break if process has finished
                if out == ''  and proc.poll() != None:
                    break

        except Exception as e:
            logger.error('Error when trying to run command: {exception}'.format(
                exception=e))
            return None

        return self.output