def _analyze_responses( self, oResponse, limit_response, error_response, mutant ): ''' Analyze responses; if error_response doesn't look like oResponse nor limit_response, then we have a vuln. @return: None ''' original_to_error = relative_distance(oResponse.getBody(), error_response.getBody() ) limit_to_error = relative_distance( limit_response.getBody(), error_response.getBody() ) original_to_limit = relative_distance( limit_response.getBody(), oResponse.getBody() ) ratio = self._diff_ratio + ( 1 - original_to_limit ) #om.out.debug('original_to_error: ' + str(original_to_error) ) #om.out.debug('limit_to_error: ' + str(limit_to_error) ) #om.out.debug('original_to_limit: ' + str(original_to_limit) ) #om.out.debug('ratio: ' + str(ratio) ) if original_to_error < ratio and limit_to_error < ratio: # Maybe the limit I requested wasn't really a non-existant one # (and the error page really found the limit), # let's request a new limit (one that hopefully doesn't exist) # in order to remove some false positives limit_response2 = self._get_limit_response( mutant ) id_list = [oResponse.id, limit_response.id, error_response.id] if relative_distance( limit_response2.getBody(), limit_response.getBody() ) > \ 1 - self._diff_ratio: # The two limits are "equal"; It's safe to suppose that we have found the # limit here and that the error string really produced an error v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setId( id_list ) v.setSeverity(severity.MEDIUM) v.setName( 'Unidentified vulnerability' ) v.setDesc( 'An unidentified vulnerability was found at: ' + mutant.foundAt() ) kb.kb.append( self, 'generic', v ) self._already_reported.append( (mutant.getURL(), mutant.getVar()) ) else: # *maybe* and just *maybe* this is a vulnerability i = info.info( mutant ) i.setPluginName(self.getName()) i.setId( id_list ) i.setName( 'Possible unidentified vulnerability' ) msg = '[Manual verification required] A possible vulnerability was found at: ' msg += mutant.foundAt() i.setDesc( msg ) kb.kb.append( self, 'generic', i ) self._already_reported.append( (mutant.getURL(), mutant.getVar()) )
def _relative_distance(self, a, b): ''' Calculates the distance between two responses based on the levenshtein distance @return: The distance ''' return 1 - relative_distance(a.getBody(), b.getBody())
def _relative_distance(self, a, b): ''' Calculates the distance between two responses based on the levenshtein distance :return: The distance ''' return 1 - relative_distance(a.get_body(), b.get_body())
def getLD(self, A, B): global num num = num + 1 result = int(relative_distance(A.getPage(), B.getPage())*100) print("\n-->(" + str(num) + ") " + str(len(A.getPage())) + " - " + str(len(B.getPage())) + " - " + str(result) ) return result
def _analyze_responses(self, orig_resp, limit_response, error_response, mutant): ''' Analyze responses; if error_response doesn't look like orig_resp nor limit_response, then we have a vuln. :return: None ''' original_to_error = relative_distance(orig_resp.get_body(), error_response.get_body()) limit_to_error = relative_distance(limit_response.get_body(), error_response.get_body()) original_to_limit = relative_distance(limit_response.get_body(), orig_resp.get_body()) ratio = self._diff_ratio + (1 - original_to_limit) #om.out.debug('original_to_error: ' + str(original_to_error) ) #om.out.debug('limit_to_error: ' + str(limit_to_error) ) #om.out.debug('original_to_limit: ' + str(original_to_limit) ) #om.out.debug('ratio: ' + str(ratio) ) if original_to_error < ratio and limit_to_error < ratio: # Maybe the limit I requested wasn't really a non-existant one # (and the error page really found the limit), # let's request a new limit (one that hopefully doesn't exist) # in order to remove some false positives limit_response2 = self._get_limit_response(mutant) id_list = [orig_resp.id, limit_response.id, error_response.id] if relative_distance(limit_response2.get_body(), limit_response.get_body()) > \ 1 - self._diff_ratio: # The two limits are "equal"; It's safe to suppose that we have found the # limit here and that the error string really produced an error self._potential_vulns.append( (mutant.get_url(), mutant.get_var(), mutant, id_list))
def _analyze_responses(self, orig_resp, limit_response, error_response, mutant): ''' Analyze responses; if error_response doesn't look like orig_resp nor limit_response, then we have a vuln. :return: None ''' original_to_error = relative_distance( orig_resp.get_body(), error_response.get_body()) limit_to_error = relative_distance( limit_response.get_body(), error_response.get_body()) original_to_limit = relative_distance( limit_response.get_body(), orig_resp.get_body()) ratio = self._diff_ratio + (1 - original_to_limit) #om.out.debug('original_to_error: ' + str(original_to_error) ) #om.out.debug('limit_to_error: ' + str(limit_to_error) ) #om.out.debug('original_to_limit: ' + str(original_to_limit) ) #om.out.debug('ratio: ' + str(ratio) ) if original_to_error < ratio and limit_to_error < ratio: # Maybe the limit I requested wasn't really a non-existant one # (and the error page really found the limit), # let's request a new limit (one that hopefully doesn't exist) # in order to remove some false positives limit_response2 = self._get_limit_response(mutant) id_list = [orig_resp.id, limit_response.id, error_response.id] if relative_distance(limit_response2.get_body(), limit_response.get_body()) > \ 1 - self._diff_ratio: # The two limits are "equal"; It's safe to suppose that we have found the # limit here and that the error string really produced an error self._potential_vulns.append((mutant.get_url(), mutant.get_var(), mutant, id_list))
def test_all(self): acceptance_tests = [] acceptance_tests.append(('a', 'a', 1.0)) acceptance_tests.append(('a', 'a', 0.1)) acceptance_tests.append(('a', 'a', 0.0)) acceptance_tests.append(('a', 'b', 1.0)) acceptance_tests.append(('a', 'b', 0.1)) acceptance_tests.append(('a', 'b', 0.0)) acceptance_tests.append(('a', 'ab', 1.0)) acceptance_tests.append(('a', 'ab', 0.1)) acceptance_tests.append(('a', 'b', 0.0000000000000000001)) acceptance_tests.append(('a', 'b' * 100, 1.0)) acceptance_tests.append(('a', 'ab', 0.66666666666)) acceptance_tests.append(('a', 'aab', 0.5)) acceptance_tests.append(('a', 'aaab', 0.4)) acceptance_tests.append( ('a', 'aaaab', 0.33333333333333333333333333333333333333333333333333333333)) acceptance_tests.append(('a' * 25, 'a', 1.0)) acceptance_tests.append(('aaa', 'aa', 1.0)) acceptance_tests.append(('a', 'a', 1.0)) acceptance_tests.append(('a' * 25, 'a', 0.076923076923076927)) acceptance_tests.append(('aaa', 'aa', 0.8)) acceptance_tests.append(('a', 'a', 0.0)) for e, d, f in acceptance_tests: res1 = relative_distance_boolean(e, d, f) res2 = relative_distance(e, d) >= f msg = 'relative_distance_boolean and relative_distance returned'\ ' different results for the same parameters:\n'\ ' - %s\n'\ ' - %s\n'\ ' - Threshold: %s\n'\ self.assertEqual(res1, res2, msg % (e, d, f))
def test_all(self): acceptance_tests = [] acceptance_tests.append(('a', 'a', 1.0)) acceptance_tests.append(('a', 'a', 0.1)) acceptance_tests.append(('a', 'a', 0.0)) acceptance_tests.append(('a', 'b', 1.0)) acceptance_tests.append(('a', 'b', 0.1)) acceptance_tests.append(('a', 'b', 0.0)) acceptance_tests.append(('a', 'ab', 1.0)) acceptance_tests.append(('a', 'ab', 0.1)) acceptance_tests.append(('a', 'b', 0.0000000000000000001)) acceptance_tests.append(('a', 'b' * 100, 1.0)) acceptance_tests.append(('a', 'ab', 0.66666666666)) acceptance_tests.append(('a', 'aab', 0.5)) acceptance_tests.append(('a', 'aaab', 0.4)) acceptance_tests.append(('a', 'aaaab', 0.33333333333333333333333333333333333333333333333333333333)) acceptance_tests.append(('a' * 25, 'a', 1.0)) acceptance_tests.append(('aaa', 'aa', 1.0)) acceptance_tests.append(('a', 'a', 1.0)) acceptance_tests.append(('a' * 25, 'a', 0.076923076923076927)) acceptance_tests.append(('aaa', 'aa', 0.8)) acceptance_tests.append(('a', 'a', 0.0)) for e, d, f in acceptance_tests: res1 = relative_distance_boolean(e, d, f) res2 = relative_distance(e, d) >= f msg = 'relative_distance_boolean and relative_distance returned'\ ' different results for the same parameters:\n'\ ' - %s\n'\ ' - %s\n'\ ' - Threshold: %s\n'\ self.assertEqual(res1, res2, msg % (e, d, f))