def _analyzeResult(self, mutant, response): ''' Analyze results of the _sendMutant method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug('remoteFileInclude', 'remoteFileInclude', mutant.getURL(), mutant.getVar()): if self._rfi_result in response: v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setId(response.id) v.setSeverity(severity.HIGH) v.setName('Remote file inclusion vulnerability') v.setDesc('Remote file inclusion was found at: ' + mutant.foundAt()) kb.kb.append(self, 'remoteFileInclude', v) else: # # Analyze some errors that indicate that there is a RFI but with some # "configuration problems" # rfi_errors = [ 'php_network_getaddresses: getaddrinfo', 'failed to open stream: Connection refused in' ] for error in rfi_errors: if error in response and not error in mutant.getOriginalResponseBody( ): v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setId(response.id) v.setSeverity(severity.MEDIUM) v.addToHighlight(error) v.setName('Remote file inclusion vulnerability') v.setDesc('Remote file inclusion was found at: ' + mutant.foundAt()) kb.kb.append(self, 'remoteFileInclude', v)
def _analyzeResult( self, mutant, response ): ''' Analyze results of the _sendMutant method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug( 'sqli' , 'sqli' , mutant.getURL() , mutant.getVar() ): sql_error_list = self._findsql_error( response ) for sql_regex, sql_error_string, dbms_type in sql_error_list: if not sql_regex.search( mutant.getOriginalResponseBody() ): # Create the vuln, v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setId( response.id ) v.setName( 'SQL injection vulnerability' ) v.setSeverity(severity.HIGH) v.addToHighlight( sql_error_string ) v['error'] = sql_error_string v['db'] = dbms_type v.setDesc( 'SQL injection in a '+ v['db'] +' was found at: ' + mutant.foundAt() ) kb.kb.append( self, 'sqli', v ) break
def _analyze_echo(self, mutant, response): ''' Analyze results of the _sendMutant method that was sent in the _fuzz_with_echo method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug('eval', 'eval', mutant.getURL(), mutant.getVar()): eval_error_list = self._find_eval_result(response) for eval_error in eval_error_list: if not re.search(eval_error, mutant.getOriginalResponseBody(), re.IGNORECASE): v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setId(response.id) v.setSeverity(severity.HIGH) v.setName('eval() input injection vulnerability') v.setDesc('eval() input injection was found at: ' + mutant.foundAt()) kb.kb.append(self, 'eval', v)
def _analyze_echo( self, mutant, response ): ''' Analyze results of the _sendMutant method that was sent in the _fuzz_with_echo method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug( 'eval' , 'eval' , mutant.getURL() , mutant.getVar() ): eval_error_list = self._find_eval_result( response ) for eval_error in eval_error_list: if not re.search( eval_error, mutant.getOriginalResponseBody(), re.IGNORECASE ): v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setId( response.id ) v.setSeverity(severity.HIGH) v.setName( 'eval() input injection vulnerability' ) v.setDesc( 'eval() input injection was found at: ' + mutant.foundAt() ) kb.kb.append( self, 'eval', v )
def _analyzeResult(self, mutant, response): ''' Analyze results of the _sendMutant method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug('sqli', 'sqli', mutant.getURL(), mutant.getVar()): sql_error_list = self._findsql_error(response) for sql_regex, sql_error_string, dbms_type in sql_error_list: if not sql_regex.search(mutant.getOriginalResponseBody()): # Create the vuln, v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setId(response.id) v.setName('SQL injection vulnerability') v.setSeverity(severity.HIGH) v.addToHighlight(sql_error_string) v['error'] = sql_error_string v['db'] = dbms_type v.setDesc('SQL injection in a ' + v['db'] + ' was found at: ' + mutant.foundAt()) kb.kb.append(self, 'sqli', v) break
def _analyze_wait( self, mutant, response ): ''' Analyze results of the _sendMutant method that was sent in the _with_time_delay method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug( 'osCommanding' , 'osCommanding' , mutant.getURL() , mutant.getVar() ): if response.getWaitTime() > (self._original_wait_time + self._wait_time-2) and \ response.getWaitTime() < (self._original_wait_time + self._wait_time+2): sentOs, sentSeparator = self._get_os_separator(mutant) # This could be because of an osCommanding vuln, or because of an error that # generates a delay in the response; so I'll resend changing the time and see # what happens original_wait_param = mutant.getModValue() more_wait_param = original_wait_param.replace( \ str(self._wait_time), \ str(self._second_wait_time) ) mutant.setModValue( more_wait_param ) response = self._sendMutant( mutant, analyze=False ) if response.getWaitTime() > (self._original_wait_time + self._second_wait_time-3) and \ response.getWaitTime() < (self._original_wait_time + self._second_wait_time+3): # Now I can be sure that I found a vuln, I control the time of the response. v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setName( 'OS commanding vulnerability' ) v.setSeverity(severity.HIGH) v['os'] = sentOs v['separator'] = sentSeparator v.setDesc( 'OS Commanding was found at: ' + mutant.foundAt() ) v.setDc( mutant.getDc() ) v.setId( response.id ) v.setURI( response.getURI() ) kb.kb.append( self, 'osCommanding', v ) else: # The first delay existed... I must report something... i = info.info() i.setPluginName(self.getName()) i.setName('Possible OS commanding vulnerability') i.setId( response.id ) i.setDc( mutant.getDc() ) i.setMethod( mutant.getMethod() ) i['os'] = sentOs i['separator'] = sentSeparator msg = 'A possible OS Commanding was found at: ' + mutant.foundAt() msg += 'Please review manually.' i.setDesc( msg ) kb.kb.append( self, 'osCommanding', i )
def tid_dup(web): while True: try: dispmenu() zop = raw_input('' + GR + ' [#] \033[1;4mTID\033[0m' + GR + ' :> ' + color.END) if zop == '1': print '\n' print G + ' [+] Module loaded : Reconnaissance' footprintban() footprint(web) elif zop == '2': print '\n' print G + ' [+] Module loaded : Scanning & Enumeration' scanenumban() scanenum_dup(web) elif zop == '3': print '\n' vulnban() vuln(web) elif zop == '4': print '\n' exploitsban() exploits(web) except KeyboardInterrupt: print R + "\n [!] " + color.UNDERLINE + "User Interruption detected!" + color.END print GR + ' [!] Stopping jobs...' time.sleep(0.4) print C + ' [!] Goodbye, see ya!\n' sys.exit(0) #except Exception as e: print R + ' [-] Something happened! :(' print R + ' [!] Error : ' + str(e)
def _analyzeResult(self, mutant, response): ''' Analyze results of the _sendMutant method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug('remoteFileInclude', 'remoteFileInclude', mutant.getURL(), mutant.getVar()): if self._rfi_result in response: v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setId(response.id) v.setSeverity(severity.HIGH) v.setName('Remote file inclusion vulnerability') v.setDesc('Remote file inclusion was found at: ' + mutant.foundAt()) kb.kb.append(self, 'remoteFileInclude', v) else: # # Analyze some errors that indicate that there is a RFI but with some # "configuration problems" # rfi_errors = ['php_network_getaddresses: getaddrinfo', 'failed to open stream: Connection refused in'] for error in rfi_errors: if error in response and not error in mutant.getOriginalResponseBody(): v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setId( response.id ) v.setSeverity(severity.MEDIUM) v.addToHighlight(error) v.setName('Remote file inclusion vulnerability') v.setDesc('Remote file inclusion was found at: ' + mutant.foundAt()) kb.kb.append(self, 'remoteFileInclude', v)
def _analyze_wait(self, mutant, response): ''' Analyze results of the _sendMutant method that was sent in the _fuzz_with_time_delay method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug('eval', 'eval', mutant.getURL(), mutant.getVar()): if response.getWaitTime() > (self._original_wait_time + self._wait_time - 2) and \ response.getWaitTime() < (self._original_wait_time + self._wait_time + 2): # generates a delay in the response; so I'll resend changing the time and see # what happens originalWaitParam = mutant.getModValue() moreWaitParam = originalWaitParam.replace( \ str(self._wait_time), \ str(self._second_wait_time) ) mutant.setModValue(moreWaitParam) response = self._sendMutant(mutant, analyze=False) if response.getWaitTime() > (self._original_wait_time + self._second_wait_time - 3) and \ response.getWaitTime() < (self._original_wait_time + self._second_wait_time + 3): # Now I can be sure that I found a vuln, I control the time of the response. v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setId(response.id) v.setSeverity(severity.HIGH) v.setName('eval() input injection vulnerability') v.setDesc('eval() input injection was found at: ' + mutant.foundAt()) kb.kb.append(self, 'eval', v) else: # The first delay existed... I must report something... i = info.info() i.setPluginName(self.getName()) i.setMethod(mutant.getMethod()) i.setURI(mutant.getURI()) i.setId(response.id) i.setDc(mutant.getDc()) i.setName('eval() input injection vulnerability') msg = 'eval() input injection was found at: ' + mutant.foundAt( ) msg += ' . Please review manually.' i.setDesc(msg) kb.kb.append(self, 'eval', i)
def is_injectable( self, freq, parameter ): ''' Check if "parameter" of the fuzzable request object is injectable or not. @freq: The fuzzableRequest object that I have to modify @parameter: A string with the parameter name to test @return: A vulnerability object or None if nothing is found ''' # First save the original wait time _original_wait_time = self._sendMutant( freq, analyze=False ).getWaitTime() # Create the mutants parameter_to_test = [ parameter, ] statement_list = self._get_statements() sql_commands_only = [ i.sql_command for i in statement_list ] mutants = createMutants( freq , sql_commands_only, fuzzableParamList=parameter_to_test ) # And now I assign the statement to the mutant for statement in statement_list: for mutant in mutants: if statement.sql_command in mutant.getModValue(): mutant.statement = statement.sql_command mutant.dbms = statement.dbms # Perform the test for mutant in mutants: # Send response = self._sendMutant( mutant, analyze=False ) # Compare times if response.getWaitTime() > (_original_wait_time + self._wait_time-2): # Resend the same request to verify that this wasn't because of network delay # or some other rare thing _original_wait_time = self._sendMutant( freq, analyze=False ).getWaitTime() response = self._sendMutant( mutant, analyze=False ) # Compare times (once again) if response.getWaitTime() > (_original_wait_time + self._wait_time-2): # Now I can be sure that I found a vuln, I control the time of the response. v = vuln.vuln( mutant ) v.setName( 'Blind SQL injection - ' + mutant.dbms ) v.setSeverity(severity.HIGH) v.setDesc( 'Blind SQL injection was found at: ' + mutant.foundAt() ) v.setDc( mutant.getDc() ) v.setId( response.id ) v.setURI( response.getURI() ) return v return None
def _analyzeResult( self, mutant, response ): ''' Do we have a reflected XSS? @return: None, record all the results in the kb. ''' # Add to the stored XSS checking self._addToPermanentXssChecking( mutant, response.id ) # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the XSS vulnerability once. # if self._hasNoBug( 'xss' , 'xss' , mutant.getURL() , mutant.getVar() ): # Internal variable for the analysis process vulnerable = False if mutant.getModValue() in response: # Ok, we MAY have found a xss. Let's remove some false positives. if mutant.getModValue().lower().count( 'javas' ): # I have to check if javascript was written inside a SRC parameter of html # afaik it is the only place this type (<IMG SRC="javascript:alert('XSS');">) # of xss works. if self._checkHTML( mutant.getModValue(), response ): vulnerable = True else: # Not a javascript type of xss, it's a <SCRIPT>...</SCRIPT> type vulnerable = True # Save it to the KB if vulnerable: v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setId( response.id ) v.setName( 'Cross site scripting vulnerability' ) v.setSeverity(severity.MEDIUM) msg = 'Cross Site Scripting was found at: ' + mutant.foundAt() msg += ' This vulnerability affects ' + ','.join(mutant.affected_browsers) v.setDesc( msg ) v.addToHighlight( mutant.getModValue() ) kb.append( self, 'xss', v )
def _analyze_echo(self, mutant, response): ''' Analyze results of the _sendMutant method that was sent in the _with_echo method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug('osCommanding', 'osCommanding', mutant.getURL(), mutant.getVar()): file_patterns = self._get_file_patterns() for file_pattern_re in file_patterns: match = file_pattern_re.search(response.getBody()) if match\ and not file_pattern_re.search( mutant.getOriginalResponseBody() ): # Search for the correct command and separator sentOs, sentSeparator = self._get_os_separator(mutant) # Create the vuln obj v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setName('OS commanding vulnerability') v.setSeverity(severity.HIGH) v['os'] = sentOs v['separator'] = sentSeparator v.setDesc('OS Commanding was found at: ' + mutant.foundAt()) v.setDc(mutant.getDc()) v.setId(response.id) v.setURI(response.getURI()) v.addToHighlight(match.group(0)) kb.kb.append(self, 'osCommanding', v) break
def end( self ): ''' This method is called to check for permanent Xss. Many times a xss isn't on the page we get after the GET/POST of the xss string. This method searches for the xss string on all the pages that are available. @return: None, vulns are saved to the kb. ''' # self._tm.join( self ) if self._check_stored_xss: for fuzzable_request in self._fuzzableRequests: response = self._sendMutant(fuzzable_request, analyze=False, useCache=False) for mutant, mutant_response_id in self._xssMutants: # Remember that httpResponse objects have a faster "__in__" than # the one in strings; so string in response.getBody() is slower than # string in response if mutant.getModValue() in response: v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setURL( fuzzable_request.getURL() ) v.setDc( fuzzable_request.getDc() ) v.setMethod( fuzzable_request.getMethod() ) v['permanent'] = True v['write_payload'] = mutant v['read_payload'] = fuzzable_request v.setName( 'Permanent cross site scripting vulnerability' ) v.setSeverity(severity.HIGH) msg = 'Permanent Cross Site Scripting was found at: ' + response.getURL() msg += ' . Using method: ' + v.getMethod() + '. The XSS was sent to the' msg += ' URL: ' + mutant.getURL()+ '. ' + mutant.printModValue() v.setDesc( msg ) v.setId( [response.id, mutant_response_id] ) v.addToHighlight( mutant.getModValue() ) kb.append( self, 'xss', v ) break self.printUniq( kb.getData( 'xss', 'xss' ), 'VAR' )
def _analyze_echo( self, mutant, response ): ''' Analyze results of the _sendMutant method that was sent in the _with_echo method. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # I will only report the vulnerability once. # if self._hasNoBug( 'osCommanding' , 'osCommanding' , mutant.getURL() , mutant.getVar() ): file_patterns = self._get_file_patterns() for file_pattern_re in file_patterns: match = file_pattern_re.search( response.getBody() ) if match\ and not file_pattern_re.search( mutant.getOriginalResponseBody() ): # Search for the correct command and separator sentOs, sentSeparator = self._get_os_separator(mutant) # Create the vuln obj v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setName( 'OS commanding vulnerability' ) v.setSeverity(severity.HIGH) v['os'] = sentOs v['separator'] = sentSeparator v.setDesc( 'OS Commanding was found at: ' + mutant.foundAt() ) v.setDc( mutant.getDc() ) v.setId( response.id ) v.setURI( response.getURI() ) v.addToHighlight( match.group(0) ) kb.kb.append( self, 'osCommanding', v ) break
def is_injectable(self, freq, parameter): ''' Check if "parameter" of the fuzzable request object is injectable or not. @freq: The fuzzableRequest object that I have to modify @parameter: A string with the parameter name to test @return: A vulnerability object or None if nothing is found ''' # First save the original wait time _original_wait_time = self._sendMutant(freq, analyze=False).getWaitTime() # Create the mutants parameter_to_test = [ parameter, ] statement_list = self._get_statements() sql_commands_only = [i.sql_command for i in statement_list] mutants = createMutants(freq, sql_commands_only, fuzzableParamList=parameter_to_test) # And now I assign the statement to the mutant for statement in statement_list: for mutant in mutants: if statement.sql_command in mutant.getModValue(): mutant.statement = statement.sql_command mutant.dbms = statement.dbms # Perform the test for mutant in mutants: # Send response = self._sendMutant(mutant, analyze=False) # Compare times if response.getWaitTime() > (_original_wait_time + self._wait_time - 2): # Resend the same request to verify that this wasn't because of network delay # or some other rare thing _original_wait_time = self._sendMutant( freq, analyze=False).getWaitTime() response = self._sendMutant(mutant, analyze=False) # Compare times (once again) if response.getWaitTime() > (_original_wait_time + self._wait_time - 2): # Now I can be sure that I found a vuln, I control the time of the response. v = vuln.vuln(mutant) v.setName('Blind SQL injection - ' + mutant.dbms) v.setSeverity(severity.HIGH) v.setDesc('Blind SQL injection was found at: ' + mutant.foundAt()) v.setDc(mutant.getDc()) v.setId(response.id) v.setURI(response.getURI()) return v return None
def _findBsql( self, mutant, statementTuple, statement_type ): ''' Is the main algorithm for finding blind sql injections. @return: A vulnerability object or None if nothing is found ''' trueStatement = statementTuple[0] falseStatement = statementTuple[1] mutant.setModValue( trueStatement ) trueResponse = self._sendMutant( mutant, analyze=False ) mutant.setModValue( falseStatement ) falseResponse = self._sendMutant( mutant, analyze=False ) om.out.debug('Comparing trueResponse and falseResponse.') if not self.equal( trueResponse.getBody() , falseResponse.getBody() ): sintaxError = "d'z'0" mutant.setModValue( sintaxError ) seResponse = self._sendMutant( mutant, analyze=False ) om.out.debug('Comparing trueResponse and sintaxErrorResponse.') if not self.equal( trueResponse.getBody() , seResponse.getBody() ): # Verify the injection! statements = self._get_statements( mutant ) secondTrueStm = statements[ statement_type ][0] secondFalseStm = statements[ statement_type ][1] mutant.setModValue( secondTrueStm ) secondTrueResponse = self._sendMutant( mutant, analyze=False ) mutant.setModValue( secondFalseStm ) secondFalseResponse = self._sendMutant( mutant, analyze=False ) om.out.debug('Comparing secondTrueResponse and trueResponse.') if self.equal( secondTrueResponse.getBody(), trueResponse.getBody() ): om.out.debug('Comparing secondFalseResponse and falseResponse.') if self.equal( secondFalseResponse.getBody(), falseResponse.getBody() ): v = vuln.vuln( mutant ) v.setId( [secondFalseResponse.id, secondTrueResponse.id] ) v.setSeverity(severity.HIGH) v.setName( 'Blind SQL injection vulnerability' ) # This is needed to be used in fuzz file name v.getMutant().setOriginalValue( '' ) v.getMutant().setModValue( '' ) desc = 'Blind SQL injection was found at: "' + v.getURL() + '",' desc += ' using HTTP method ' + v.getMethod() + '.' desc += ' The injectable parameter is: "' + mutant.getVar() + '".' v.setDesc( desc ) om.out.debug( v.getDesc() ) v['type'] = statement_type v['trueHtml'] = secondTrueResponse.getBody() v['falseHtml'] = secondFalseResponse.getBody() v['errorHtml'] = seResponse.getBody() return v return None
def _analyzeResult( self, mutant, response ): ''' Analyze results of the _sendMutant method. Try to find the local file inclusions. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # 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: if 'open_basedir restriction in effect' in response\ and 'open_basedir restriction in effect' not in mutant.getOriginalResponseBody(): self._open_basedir = True # # I will only report the vulnerability once. # if self._hasNoBug( 'localFileInclude' , 'localFileInclude' , mutant.getURL() , mutant.getVar() ): # # Identify the vulnerability # file_content_list = self._find_file( response ) for file_pattern_regex, file_content in file_content_list: if not file_pattern_regex.search( mutant.getOriginalResponseBody() ): v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setId( response.id ) v.setName( 'Local file inclusion vulnerability' ) v.setSeverity(severity.MEDIUM) v.setDesc( 'Local File Inclusion was found at: ' + mutant.foundAt() ) v['file_pattern'] = file_content v.addToHighlight( file_content ) kb.kb.append( self, 'localFileInclude', 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.getModValue() == mutant.getURL().getFileName(): match, lang = is_source_file( response.getBody() ) if match: # We were able to read the source code of the file that is vulnerable to # local file read v = vuln.vuln( mutant ) v.setPluginName(self.getName()) v.setId( response.id ) v.setName( 'Local file read vulnerability' ) v.setSeverity(severity.MEDIUM) msg = 'An arbitrary local file read vulnerability was found at: ' msg += mutant.foundAt() v.setDesc( msg ) # # Set which part of the source code to match # match_source_code = match.group(0) v['file_pattern'] = match_source_code kb.kb.append( self, 'localFileInclude', 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.getBody() ) if match and not \ regex.search( mutant.getOriginalResponseBody() ): i = info.info( mutant ) i.setPluginName(self.getName()) i.setId( response.id ) i.setName( 'File read error' ) i.setDesc( 'A file read error was found at: ' + mutant.foundAt() ) kb.kb.append( self, 'error', i )
def _analyzeResult(self, mutant, response): ''' Analyze results of the _sendMutant method. Try to find the local file inclusions. ''' # # Only one thread at the time can enter here. This is because I want to report each # vulnerability only once, and by only adding the "if self._hasNoBug" statement, that # could not be done. # if True: # # 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: if 'open_basedir restriction in effect' in response\ and 'open_basedir restriction in effect' not in mutant.getOriginalResponseBody(): self._open_basedir = True # # I will only report the vulnerability once. # if self._hasNoBug('localFileInclude', 'localFileInclude', mutant.getURL(), mutant.getVar()): # # Identify the vulnerability # file_content_list = self._find_file(response) for file_pattern_regex, file_content in file_content_list: if not file_pattern_regex.search( mutant.getOriginalResponseBody()): v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setId(response.id) v.setName('Local file inclusion vulnerability') v.setSeverity(severity.MEDIUM) v.setDesc('Local File Inclusion was found at: ' + mutant.foundAt()) v['file_pattern'] = file_content v.addToHighlight(file_content) kb.kb.append(self, 'localFileInclude', 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.getModValue() == mutant.getURL().getFileName(): match, lang = is_source_file(response.getBody()) if match: # We were able to read the source code of the file that is vulnerable to # local file read v = vuln.vuln(mutant) v.setPluginName(self.getName()) v.setId(response.id) v.setName('Local file read vulnerability') v.setSeverity(severity.MEDIUM) msg = 'An arbitrary local file read vulnerability was found at: ' msg += mutant.foundAt() v.setDesc(msg) # # Set which part of the source code to match # match_source_code = match.group(0) v['file_pattern'] = match_source_code kb.kb.append(self, 'localFileInclude', 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.getBody()) if match and not \ regex.search( mutant.getOriginalResponseBody() ): i = info.info(mutant) i.setPluginName(self.getName()) i.setId(response.id) i.setName('File read error') i.setDesc('A file read error was found at: ' + mutant.foundAt()) kb.kb.append(self, 'error', i)