Exemplo n.º 1
0
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        """
        if self._has_bug(mutant):
            return

        if self._header_was_injected(mutant, response):
            desc = "Response splitting was found at: %s" % mutant.found_at()

            v = Vuln.from_mutant(
                "Response splitting vulnerability", desc, severity.MEDIUM, response.id, self.get_name(), mutant
            )

            self.kb_append_uniq(self, "response_splitting", v)

        # When trying to send a response splitting to php 5.1.2 I get :
        # Header may not contain more than a single header, new line detected
        for error in self.HEADER_ERRORS:

            if error in response:
                desc = (
                    'The variable "%s" at URL "%s" modifies the HTTP'
                    " response headers, but this error was sent while"
                    ' testing for response splitting: "%s".'
                )
                args = (mutant.get_token_name(), mutant.get_url(), error)
                desc = desc % args
                i = Info.from_mutant("Parameter modifies response headers", desc, response.id, self.get_name(), mutant)

                self.kb_append_uniq(self, "response_splitting", i)

                return
Exemplo n.º 2
0
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        """
        #
        #   I will only report the vulnerability once.
        #
        if self._has_no_bug(mutant):

            if self._header_was_injected(mutant, response):
                desc = 'Response splitting was found at: %s' % mutant.found_at()
                
                v = Vuln.from_mutant('Response splitting vulnerability', desc,
                                     severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                self.kb_append_uniq(self, 'response_splitting', v)
                
            # When trying to send a response splitting to php 5.1.2 I get :
            # Header may not contain more than a single header, new line detected
            for error in self.HEADER_ERRORS:

                if error in response:
                    desc = 'The variable "%s" at URL "%s" modifies the HTTP'\
                           ' response headers, but this error was sent while'\
                           ' testing for response splitting: "%s".'
                    desc = desc % (mutant.get_var(), mutant.get_url(), error)
                    i = Info.from_mutant('Parameter modifies response headers',
                                         desc, response.id, self.get_name(),
                                         mutant)
                    
                    self.kb_append_uniq(self, 'response_splitting', i)

                    return
Exemplo n.º 3
0
    def _header_was_injected(self, mutant, response):
        """
        This method verifies if a header was successfully injected

        :param mutant: The mutant that was sent to generate the response
        :param response: The HTTP response where I want to find the injected
                         header.
        :return: True / False
        """
        # Get the lower case headers
        headers = response.get_lower_case_headers()

        # Analyze injection
        for header, value in headers.items():
            if HEADER_NAME in header and value.lower() == HEADER_VALUE:
                return True

            elif HEADER_NAME in header and value.lower() != HEADER_VALUE:
                msg = ('The vulnerable header was added to the HTTP response,'
                       ' but the value is not what w3af expected (%s: %s).'
                       ' Please verify manually.')
                msg = msg % (HEADER_NAME, HEADER_VALUE)
                om.out.information(msg)

                i = Info.from_mutant('Parameter modifies response headers',
                                     msg, response.id, self.get_name(), mutant)

                self.kb_append_uniq(self, 'response_splitting', i)
                return False

        return False
Exemplo n.º 4
0
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        """
        if self._has_bug(mutant):
            return

        if self._header_was_injected(mutant, response):
            desc = 'Response splitting was found at: %s' % mutant.found_at()

            v = Vuln.from_mutant('Response splitting vulnerability',
                                 desc, severity.MEDIUM, response.id,
                                 self.get_name(), mutant)

            self.kb_append_uniq(self, 'response_splitting', v)

        # When trying to send a response splitting to php 5.1.2 I get :
        # Header may not contain more than a single header, new line detected
        for error in self.HEADER_ERRORS:

            if error in response:
                desc = ('The variable "%s" at URL "%s" modifies the HTTP'
                        ' response headers, but this error was sent while'
                        ' testing for response splitting: "%s".')
                args = (mutant.get_token_name(), mutant.get_url(), error)
                desc = desc % args
                i = Info.from_mutant('Parameter modifies response headers',
                                     desc, response.id, self.get_name(),
                                     mutant)

                self.kb_append_uniq(self, 'response_splitting', i)

                return
Exemplo n.º 5
0
    def _header_was_injected(self, mutant, response):
        """
        This method verifies if a header was successfully injected

        :param mutant: The mutant that was sent to generate the response
        :param response: The HTTP response where I want to find the injected
                         header.
        :return: True / False
        """
        # Get the lower case headers
        headers = response.get_lower_case_headers()

        # Analyze injection
        for header, value in headers.items():
            if HEADER_NAME in header and value.lower() == HEADER_VALUE:
                return True

            elif HEADER_NAME in header and value.lower() != HEADER_VALUE:
                msg = (
                    "The vulnerable header was added to the HTTP response,"
                    " but the value is not what w3af expected (%s: %s)."
                    " Please verify manually."
                )
                msg = msg % (HEADER_NAME, HEADER_VALUE)
                om.out.information(msg)

                i = Info.from_mutant("Parameter modifies response headers", msg, response.id, self.get_name(), mutant)

                self.kb_append_uniq(self, "response_splitting", i)
                return False

        return False
Exemplo n.º 6
0
    def test_from_mutant(self):
        dc = DataContainer()
        url = URL('http://moth/')
        payloads = ['abc', 'def']

        dc['a'] = [
            '1',
        ]
        dc['b'] = [
            '2',
        ]
        freq = FuzzableRequest(url, dc=dc)
        fuzzer_config = {}

        created_mutants = Mutant.create_mutants(freq, payloads, [], False,
                                                fuzzer_config)

        mutant = created_mutants[0]

        inst = Info.from_mutant('TestCase', 'desc' * 30, 1, 'plugin_name',
                                mutant)

        self.assertIsInstance(inst, Info)

        self.assertEqual(inst.get_uri(), mutant.get_uri())
        self.assertEqual(inst.get_url(), mutant.get_url())
        self.assertEqual(inst.get_method(), mutant.get_method())
        self.assertEqual(inst.get_dc(), mutant.get_dc())
        self.assertEqual(inst.get_var(), mutant.get_var())
Exemplo n.º 7
0
    def _report_php_errors(self, mutant, response):
        # When trying to send a response splitting to PHP 5.1.2 I get:
        # Header may not contain more than a single header, new line detected
        for error in self.HEADER_ERRORS:
            if error not in response:
                continue

            desc = ('The variable "%s" at URL "%s" modifies the HTTP'
                    ' response headers, but this error was sent while'
                    ' testing for response splitting: "%s".')
            args = (mutant.get_token_name(), mutant.get_url(), error)
            desc %= args
            i = Info.from_mutant('Parameter modifies response headers', desc,
                                 response.id, self.get_name(), mutant)

            self.kb_append_uniq(self, 'response_splitting', i)
            break
Exemplo n.º 8
0
    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 (BaseFrameworkException, ScanMustStopException):
            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, [], self.get_name(), mutant)
            
            self.kb_append_uniq(self, 'buffer_overflow', i)
        else:
            self._analyze_result(mutant, response)
Exemplo n.º 9
0
    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 (BaseFrameworkException, ScanMustStopException):
            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, [], self.get_name(), mutant)
            
            self.kb_append_uniq(self, 'buffer_overflow', i)
        else:
            self._analyze_result(mutant, response)
Exemplo n.º 10
0
    def test_from_mutant(self):
        url = URL("http://moth/?a=1&b=2")
        payloads = ["abc", "def"]

        freq = FuzzableRequest(url)
        fuzzer_config = {}

        created_mutants = QSMutant.create_mutants(freq, payloads, [], False, fuzzer_config)

        mutant = created_mutants[0]

        inst = Info.from_mutant("TestCase", "desc" * 30, 1, "plugin_name", mutant)

        self.assertIsInstance(inst, Info)

        self.assertEqual(inst.get_uri(), mutant.get_uri())
        self.assertEqual(inst.get_url(), mutant.get_url())
        self.assertEqual(inst.get_method(), mutant.get_method())
        self.assertEqual(inst.get_dc(), mutant.get_dc())
        self.assertIsInstance(inst.get_dc(), QueryString)
Exemplo n.º 11
0
    def test_from_mutant(self):
        url = URL('http://moth/?a=1&b=2')
        payloads = ['abc', 'def']

        freq = FuzzableRequest(url)
        fuzzer_config = {}

        created_mutants = QSMutant.create_mutants(freq, payloads, [], False,
                                                  fuzzer_config)

        mutant = created_mutants[0]

        inst = Info.from_mutant('TestCase', 'desc' * 30, 1, 'plugin_name',
                                mutant)

        self.assertIsInstance(inst, Info)

        self.assertEqual(inst.get_uri(), mutant.get_uri())
        self.assertEqual(inst.get_url(), mutant.get_url())
        self.assertEqual(inst.get_method(), mutant.get_method())
        self.assertEqual(inst.get_dc(), mutant.get_dc())
        self.assertIsInstance(inst.get_dc(), QueryString)
Exemplo n.º 12
0
    def _send_request(self, mutant, debugging_id):
        """
        Sends a mutant to the remote web server. I wrap urllib's _send_mutant
        just to handle errors in a different way.
        """
        # Only grep the request which sends the larger payload
        grep = mutant.get_token_value() == self.BUFFER_TESTS[-1]

        try:
            response = self._uri_opener.send_mutant(mutant,
                                                    debugging_id=debugging_id,
                                                    grep=grep)
        except (BaseFrameworkException, ScanMustStopException):
            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 %= (mutant.get_url(), mutant.get_method(), mutant.get_dc())

            i = Info.from_mutant('Potential buffer overflow vulnerability',
                                 desc, [], self.get_name(), mutant)
            
            self.kb_append_uniq(self, 'buffer_overflow', i)
        else:
            self._analyze_result(mutant, response)
Exemplo n.º 13
0
    def _send_request(self, mutant, debugging_id):
        """
        Sends a mutant to the remote web server. I wrap urllib's _send_mutant
        just to handle errors in a different way.
        """
        # Only grep the request which sends the larger payload
        grep = mutant.get_token_value() == self.BUFFER_TESTS[-1]

        try:
            response = self._uri_opener.send_mutant(mutant,
                                                    debugging_id=debugging_id,
                                                    grep=grep)
        except (BaseFrameworkException, ScanMustStopException):
            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 %= (mutant.get_url(), mutant.get_method(), mutant.get_dc())

            i = Info.from_mutant('Potential buffer overflow vulnerability',
                                 desc, [], self.get_name(), mutant)

            self.kb_append_uniq(self, 'buffer_overflow', i)
        else:
            self._analyze_result(mutant, response)
Exemplo n.º 14
0
    def test_from_mutant(self):
        dc = DataContainer()
        url = URL('http://moth/')
        payloads = ['abc', 'def']

        dc['a'] = ['1', ]
        dc['b'] = ['2', ]
        freq = FuzzableRequest(url, dc=dc)
        fuzzer_config = {}
        
        created_mutants = Mutant.create_mutants(freq, payloads, [], False,
                                                fuzzer_config)
                
        mutant = created_mutants[0]
        
        inst = Info.from_mutant('TestCase', 'desc' * 30, 1, 'plugin_name', mutant)
        
        self.assertIsInstance(inst, Info)
        
        self.assertEqual(inst.get_uri(), mutant.get_uri())
        self.assertEqual(inst.get_url(), mutant.get_url())
        self.assertEqual(inst.get_method(), mutant.get_method())
        self.assertEqual(inst.get_dc(), mutant.get_dc())
        self.assertEqual(inst.get_var(), mutant.get_var())
Exemplo n.º 15
0
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        Try to find the local file inclusions.
        """
        #
        #   I will only report the vulnerability once.
        #
        if self._has_bug(mutant):
            return

        #
        #   Identify the vulnerability
        #
        for file_pattern_match in self._find_common_file_fragments(response):
            if file_pattern_match not in mutant.get_original_response_body():

                desc = 'Local File Inclusion was found at: %s'
                desc %= mutant.found_at()

                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                v['file_pattern'] = file_pattern_match

                v.add_to_highlight(file_pattern_match)
                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        # If the vulnerability could not be identified by matching strings that
        # commonly appear in "/etc/passwd", then I'll check one more thing...
        # (note that this is run if no vulns were identified)
        #
        # http://host.tld/show_user.php?id=show_user.php
        #
        # The calls to smart_str_ignore fix a UnicodeDecoreError which appears when
        # the token value is a binary string which can't be converted to unicode.
        # This happens, for example, when trying to upload JPG files to a multipart form
        #
        # >>> u'' in '\x80'
        # ...
        # UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)
        #
        filename = smart_str_ignore(mutant.get_url().get_file_name())
        token_value = smart_str_ignore(mutant.get_token_value())

        if filename in token_value:
            match, lang = contains_source_code(response)
            if match:
                # We were able to read the source code of the file that is
                # vulnerable to local file read
                desc = ('An arbitrary local file read vulnerability was'
                        ' found at: %s')
                desc %= mutant.found_at()

                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                #
                #    Set which part of the source code to match
                #
                match_source_code = match.group(0)
                v['file_pattern'] = match_source_code

                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        #   Check for interesting errors (note that this is run if no vulns were
        #   identified)
        #
        body = response.get_body()
        for _, error_str, _ in self.file_read_error_multi_re.query(body):
            if error_str not in mutant.get_original_response_body():
                desc = 'A file read error was found at: %s'
                desc %= mutant.found_at()

                i = Info.from_mutant('File read error', desc, response.id,
                                     self.get_name(), mutant)
                i.add_to_highlight(error_str)

                self.kb_append_uniq(self, 'error', i)
Exemplo n.º 16
0
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        Try to find the local file inclusions.
        """
        #
        #   I will only report the vulnerability once.
        #
        if self._has_bug(mutant):
            return

        #
        #   Identify the vulnerability
        #
        for file_pattern_match in self._find_common_file_fragments(response):
            if file_pattern_match not in mutant.get_original_response_body():
                
                desc = 'Local File Inclusion was found at: %s'
                desc %= mutant.found_at()
                
                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                v['file_pattern'] = file_pattern_match
                
                v.add_to_highlight(file_pattern_match)
                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        # If the vulnerability could not be identified by matching strings that
        # commonly appear in "/etc/passwd", then I'll check one more thing...
        # (note that this is run if no vulns were identified)
        #
        # http://host.tld/show_user.php?id=show_user.php
        if mutant.get_url().get_file_name() in mutant.get_token_value():
            match, lang = contains_source_code(response)
            if match:
                # We were able to read the source code of the file that is
                # vulnerable to local file read
                desc = ('An arbitrary local file read vulnerability was'
                        ' found at: %s')
                desc %= mutant.found_at()
                
                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                #
                #    Set which part of the source code to match
                #
                match_source_code = match.group(0)
                v['file_pattern'] = match_source_code

                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        #   Check for interesting errors (note that this is run if no vulns were
        #   identified)
        #
        body = response.get_body()
        for _, error_str, _ in self.file_read_error_multi_re.query(body):
            if error_str not in mutant.get_original_response_body():
                desc = 'A file read error was found at: %s'
                desc %= mutant.found_at()
                
                i = Info.from_mutant('File read error', desc, response.id,
                                     self.get_name(), mutant)
                i.add_to_highlight(error_str)
                
                self.kb_append_uniq(self, 'error', i)
Exemplo n.º 17
0
Arquivo: lfi.py Projeto: zcr214/w3af
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        Try to find the local file inclusions.
        """
        #
        #   I will only report the vulnerability once.
        #
        if self._has_bug(mutant):
            return

        #
        #   Identify the vulnerability
        #
        for file_pattern_match in self._find_common_file_fragments(response):
            if file_pattern_match not in mutant.get_original_response_body():

                desc = 'Local File Inclusion was found at: %s'
                desc %= mutant.found_at()

                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                v['file_pattern'] = file_pattern_match

                v.add_to_highlight(file_pattern_match)
                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        # If the vulnerability could not be identified by matching strings that
        # commonly appear in "/etc/passwd", then I'll check one more thing...
        # (note that this is run if no vulns were identified)
        #
        # http://host.tld/show_user.php?id=show_user.php
        if mutant.get_url().get_file_name() in mutant.get_token_value():
            match, lang = contains_source_code(response)
            if match:
                # We were able to read the source code of the file that is
                # vulnerable to local file read
                desc = ('An arbitrary local file read vulnerability was'
                        ' found at: %s')
                desc %= mutant.found_at()

                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                #
                #    Set which part of the source code to match
                #
                match_source_code = match.group(0)
                v['file_pattern'] = match_source_code

                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        #   Check for interesting errors (note that this is run if no vulns were
        #   identified)
        #
        body = response.get_body()
        for _, error_str, _ in self.file_read_error_multi_re.query(body):
            if error_str not in mutant.get_original_response_body():
                desc = 'A file read error was found at: %s'
                desc %= mutant.found_at()

                i = Info.from_mutant('File read error', desc, response.id,
                                     self.get_name(), mutant)
                i.add_to_highlight(error_str)

                self.kb_append_uniq(self, 'error', i)
Exemplo n.º 18
0
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        Try to find the local file inclusions.
        """
        #
        #   I will only report the vulnerability once.
        #
        if self._has_bug(mutant):
            return

        #
        #   Identify the vulnerability
        #
        for file_pattern_match in self._find_common_file_fragments(response):
            if file_pattern_match not in mutant.get_original_response_body():
                
                desc = 'Local File Inclusion was found at: %s'
                desc %= mutant.found_at()
                
                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                v['file_pattern'] = file_pattern_match
                
                v.add_to_highlight(file_pattern_match)
                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        # If the vulnerability could not be identified by matching strings that
        # commonly appear in "/etc/passwd", then I'll check one more thing...
        # (note that this is run if no vulns were identified)
        #
        # http://host.tld/show_user.php?id=show_user.php
        #
        # The calls to smart_str_ignore fix a UnicodeDecoreError which appears when
        # the token value is a binary string which can't be converted to unicode.
        # This happens, for example, when trying to upload JPG files to a multipart form
        #
        # >>> u'' in '\x80'
        # ...
        # UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)
        #
        filename = smart_str_ignore(mutant.get_url().get_file_name())
        token_value = smart_str_ignore(mutant.get_token_value())

        if filename in token_value:
            match, lang = contains_source_code(response)
            if match:
                # We were able to read the source code of the file that is
                # vulnerable to local file read
                desc = ('An arbitrary local file read vulnerability was'
                        ' found at: %s')
                desc %= mutant.found_at()
                
                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                #
                #    Set which part of the source code to match
                #
                match_source_code = match.group(0)
                v['file_pattern'] = match_source_code

                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        #   Check for interesting errors (note that this is run if no vulns were
        #   identified)
        #
        body = response.get_body()
        for _, error_str, _ in self.file_read_error_multi_re.query(body):
            if error_str not in mutant.get_original_response_body():
                desc = 'A file read error was found at: %s'
                desc %= mutant.found_at()
                
                i = Info.from_mutant('File read error', desc, response.id,
                                     self.get_name(), mutant)
                i.add_to_highlight(error_str)
                
                self.kb_append_uniq(self, 'error', i)
Exemplo n.º 19
0
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        Try to find the local file inclusions.
        """
        # I analyze the response searching for a specific PHP error string
        # that tells me that open_basedir is enabled, and our request triggered
        # the restriction. If open_basedir is in use, it makes no sense to keep
        # trying to read "/etc/passwd", that is why this variable is used to
        # determine which tests to send if it was possible to detect the usage
        # of this security feature.
        if not self._open_basedir:

            basedir_warning = "open_basedir restriction in effect"

            if basedir_warning in response and basedir_warning not in mutant.get_original_response_body():
                self._open_basedir = True

        #
        #   I will only report the vulnerability once.
        #
        if self._has_bug(mutant):
            return

        #
        #   Identify the vulnerability
        #
        file_content_list = self._find_file(response)
        for file_pattern_match in file_content_list:
            if file_pattern_match not in mutant.get_original_response_body():

                desc = "Local File Inclusion was found at: %s"
                desc = desc % mutant.found_at()

                v = Vuln.from_mutant(
                    "Local file inclusion vulnerability", desc, severity.MEDIUM, response.id, self.get_name(), mutant
                )

                v["file_pattern"] = file_pattern_match

                v.add_to_highlight(file_pattern_match)
                self.kb_append_uniq(self, "lfi", v)
                return

        #
        # If the vulnerability could not be identified by matching strings that
        # commonly appear in "/etc/passwd", then I'll check one more thing...
        # (note that this is run if no vulns were identified)
        #
        # http://host.tld/show_user.php?id=show_user.php
        if mutant.get_token_value() == mutant.get_url().get_file_name():
            match, lang = is_source_file(response.get_body())
            if match:
                # We were able to read the source code of the file that is
                # vulnerable to local file read
                desc = "An arbitrary local file read vulnerability was" " found at: %s" % mutant.found_at()

                v = Vuln.from_mutant(
                    "Local file inclusion vulnerability", desc, severity.MEDIUM, response.id, self.get_name(), mutant
                )

                #
                #    Set which part of the source code to match
                #
                match_source_code = match.group(0)
                v["file_pattern"] = match_source_code

                self.kb_append_uniq(self, "lfi", v)
                return

        #
        #   Check for interesting errors (note that this is run if no vulns were
        #   identified)
        #
        for regex in self.get_include_errors():

            match = regex.search(response.get_body())

            if match and not regex.search(mutant.get_original_response_body()):
                desc = "A file read error was found at: %s"
                desc = desc % mutant.found_at()

                i = Info.from_mutant("File read error", desc, response.id, self.get_name(), mutant)

                self.kb_append_uniq(self, "error", i)
Exemplo n.º 20
0
    def _analyze_result(self, mutant, response):
        """
        Analyze results of the _send_mutant method.
        Try to find the local file inclusions.
        """
        # I analyze the response searching for a specific PHP error string
        # that tells me that open_basedir is enabled, and our request triggered
        # the restriction. If open_basedir is in use, it makes no sense to keep
        # trying to read "/etc/passwd", that is why this variable is used to
        # determine which tests to send if it was possible to detect the usage
        # of this security feature.
        if not self._open_basedir:

            basedir_warning = 'open_basedir restriction in effect'

            if basedir_warning in response and \
                            basedir_warning not in mutant.get_original_response_body():
                self._open_basedir = True

        #
        #   I will only report the vulnerability once.
        #
        if self._has_bug(mutant):
            return

        #
        #   Identify the vulnerability
        #
        file_content_list = self._find_file(response)
        for file_pattern_match in file_content_list:
            if file_pattern_match not in mutant.get_original_response_body():
                desc = 'Local File Inclusion was found at: %s'
                desc = desc % mutant.found_at()

                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                v['file_pattern'] = file_pattern_match

                v.add_to_highlight(file_pattern_match)
                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        # If the vulnerability could not be identified by matching strings that
        # commonly appear in "/etc/passwd", then I'll check one more thing...
        # (note that this is run if no vulns were identified)
        #
        # http://host.tld/show_user.php?id=show_user.php
        if mutant.get_token_value() == mutant.get_url().get_file_name():
            match, lang = is_source_file(response.get_body())
            if match:
                # We were able to read the source code of the file that is
                # vulnerable to local file read
                desc = 'An arbitrary local file read vulnerability was' \
                       ' found at: %s' % mutant.found_at()

                v = Vuln.from_mutant('Local file inclusion vulnerability',
                                     desc, severity.MEDIUM, response.id,
                                     self.get_name(), mutant)

                #
                #    Set which part of the source code to match
                #
                match_source_code = match.group(0)
                v['file_pattern'] = match_source_code

                self.kb_append_uniq(self, 'lfi', v)
                return

        #
        #   Check for interesting errors (note that this is run if no vulns were
        #   identified)
        #
        for regex in self.get_include_errors():

            match = regex.search(response.get_body())

            if match and not regex.search(mutant.get_original_response_body()):
                desc = 'A file read error was found at: %s'
                desc = desc % mutant.found_at()

                i = Info.from_mutant('File read error', desc, response.id,
                                     self.get_name(), mutant)

                self.kb_append_uniq(self, 'error', i)