def end(self): om.out.debug("File upload shell is going to delete the webshell that was uploaded before.") file_to_del = urlParser.getFileName(self.getExploitURL()) try: self.unlink(file_to_del) except w3afException, e: om.out.error("File upload shell cleanup failed with exception: " + str(e))
def _rm_file(self): ''' Stop the server, remove the file from the webroot. ''' # Remove the file filename = urlParser.getFileName(self._rfi_url) os.remove(os.path.join(get_home_dir(), 'webroot', filename))
def audit(self, freq ): ''' Tests an URL for local file inclusion vulnerabilities. @param freq: A fuzzableRequest ''' om.out.debug( 'localFileInclude plugin is testing: ' + freq.getURL() ) oResponse = self._sendMutant( freq , analyze=False ).getBody() # What payloads do I want to send to the remote end? local_files = [] local_files.append( urlParser.getFileName( freq.getURL() ) ) if not self._open_basedir: local_files.extend( self._get_local_file_list(freq.getURL()) ) mutants = createMutants( freq , local_files, oResponse=oResponse ) for mutant in mutants: # Only spawn a thread if the mutant has a modified variable # that has no reported bugs in the kb if self._hasNoBug( 'localFileInclude' , 'localFileInclude', mutant.getURL() , mutant.getVar() ): targs = (mutant,) # I don't grep the result, because if I really find a local file inclusion, # I will be requesting /etc/passwd and that would generate A LOT of false # positives in the grep.pathDisclosure plugin kwds = {'grepResult':False} self._tm.startFunction( target=self._sendMutant, args=targs , \ kwds=kwds, ownerObj=self ) self._tm.join( self )
def _mangle_digits(self, fuzzableRequest): ''' Mangle those digits. @param fuzzableRequest: The original fuzzableRequest @return: A list of fuzzableRequests. ''' res = [] # First i'll mangle the digits in the URL file filename = urlParser.getFileName( fuzzableRequest.getURL() ) domain_path = urlParser.getDomainPath( fuzzableRequest.getURL() ) for fname in self._do_combinations( filename ): fr_copy = fuzzableRequest.copy() fr_copy.setURL( domain_path + fname) res.append( fr_copy ) # Now i'll mangle the query string variables if fuzzableRequest.getMethod() == 'GET': for parameter in fuzzableRequest.getDc(): # to support repeater parameter names... for element_index in xrange(len(fuzzableRequest.getDc()[parameter])): for modified_value in self._do_combinations( fuzzableRequest.getDc()[ parameter ][element_index] ): fr_copy = fuzzableRequest.copy() new_dc = fr_copy.getDc() new_dc[ parameter ][ element_index ] = modified_value fr_copy.setDc( new_dc ) res.append( fr_copy ) return res
def _get_filename( self, url ): ''' @return: The filename, without the extension ''' fname = urlParser.getFileName( url ) splitted_fname = fname.split('.') name = '' if len(splitted_fname) != 0: name = splitted_fname[0] return name
def _createFileNameMutants( freq, mutantClass, mutant_str_list, fuzzableParamList , append ): ''' @parameter freq: A fuzzable request with a dataContainer inside. @parameter mutantClass: The class to use to create the mutants @parameter fuzzableParamList: What parameters should be fuzzed @parameter append: True/False, if we should append the value or replace it. @parameter mutant_str_list: a list with mutant strings to use @return: Mutants that have the filename URL changed with the strings at mutant_str_list ''' res = [] fileName = urlParser.getFileName( freq.getURL() ) splittedFileName = [ x for x in re.split( r'([a-zA-Z0-9]+)', fileName ) if x != '' ] for i in xrange( len( splittedFileName ) ): for mutant_str in mutant_str_list: if re.match('[a-zA-Z0-9]', splittedFileName[i] ): divided_file_name = dc() divided_file_name['start'] = ''.join( splittedFileName[: i] ) if append: divided_file_name['fuzzedFname'] = splittedFileName[i] + urllib.quote_plus( mutant_str ) else: divided_file_name['fuzzedFname'] = urllib.quote_plus( mutant_str ) divided_file_name['end'] = ''.join( splittedFileName[i+1:] ) freq_copy = freq.copy() freq_copy.setURL( freq.getURL() ) # Create the mutant m = mutantClass( freq_copy ) m.setOriginalValue( splittedFileName[i] ) m.setVar( 'fuzzedFname' ) m._mutant_dc = divided_file_name m.setModValue( mutant_str ) # Special for filename fuzzing and some configurations of mod_rewrite m.setDoubleEncoding( False ) # The same but with a different type of encoding! (mod_rewrite) m2 = m.copy() m2.setSafeEncodeChars('/') res.append( m ) res.append( m2 ) return res
def _generate_URLs(self, original_url): ''' Generate new URLs based on original_url. @parameter original_url: The original url that has to be modified in order to trigger errors in the remote application. ''' res = [] special_chars = ['|', '~'] filename = urlParser.getFileName( original_url ) if filename != '' and '.' in filename: splitted_filename = filename.split('.') extension = splitted_filename[-1:][0] name = '.'.join( splitted_filename[0:-1] ) for char in special_chars: new_filename = name + char + '.' + extension new_url = urlParser.urlJoin( urlParser.getDomainPath(original_url), new_filename) res.append( new_url ) return res
def _generate_URL_from_result( self, analyzed_variable, element_index, result_set, fuzzableRequest ): ''' Based on the result, create the new URLs to test. @parameter analyzed_variable: The parameter name that is being analyzed @parameter element_index: 0 in most cases, >0 if we have repeated parameter names @parameter result_set: The set of results that wordnet gave use @parameter fuzzableRequest: The fuzzable request that we got as input in the first place. @return: An URL list. ''' if analyzed_variable is None: # The URL was analyzed url = fuzzableRequest.getURL() fname = urlParser.getFileName( url ) dp = urlParser.getDomainPath( url ) # The result result = [] splitted_fname = fname.split('.') if len(splitted_fname) == 2: name = splitted_fname[0] extension = splitted_fname[1] else: name = '.'.join(splitted_fname[:-1]) extension = 'html' for set_item in result_set: new_fname = fname.replace( name, set_item ) frCopy = fuzzableRequest.copy() frCopy.setURL( urlParser.urlJoin( dp, new_fname ) ) result.append( frCopy ) return result else: mutants = createMutants( fuzzableRequest , result_set, \ fuzzableParamList=[analyzed_variable,] ) return mutants
def _find_OS( self, fuzzableRequest ): ''' Analyze responses and determine if remote web server runs on windows or *nix @Return: None, the knowledge is saved in the knowledgeBase ''' dirs = urlParser.getDirectories( fuzzableRequest.getURL() ) filename = urlParser.getFileName( fuzzableRequest.getURL() ) if len( dirs ) > 1 and filename: last = dirs[-1] windowsURL = last[0:-1] + '\\' + filename windows_response = self._urlOpener.GET( windowsURL ) original_response = self._urlOpener.GET( fuzzableRequest.getURL() ) self._found_OS = True if relative_distance_ge(original_response.getBody(), windows_response.getBody(), 0.98): i = info.info() i.setPluginName(self.getName()) i.setName('Operating system') i.setURL( windows_response.getURL() ) i.setMethod( 'GET' ) i.setDesc('Fingerprinted this host as a Microsoft Windows system.' ) i.setId( [windows_response.id, original_response.id] ) kb.kb.append( self, 'operating_system_str', 'windows' ) kb.kb.append( self, 'operating_system', i ) om.out.information( i.getDesc() ) else: i = info.info() i.setPluginName(self.getName()) i.setName('Operating system') i.setURL( original_response.getURL() ) i.setMethod( 'GET' ) msg = 'Fingerprinted this host as a *nix system. Detection for this operating' msg += ' system is weak, "if not windows: is linux".' i.setDesc( msg ) i.setId( [original_response.id, windows_response.id] ) kb.kb.append( self, 'operating_system_str', 'unix' ) kb.kb.append( self, 'operating_system', i ) om.out.information( i.getDesc() )
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. # with self._plugin_lock: # # 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() == urlParser.getFileName( mutant.getURL() ): 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 )
/es/ga.js/google-analytics.com /ga.js/google-analytics.com /es/ga.js/google-analytics.com/ga.js/google-analytics.com/ga.js /ga.js/google-analytics.com/google-analytics.com/ga.js/ /es/ga.js/google-analytics.com/google-analytics.com/ga.js/ /es/ga.js/google-analytics.com/google-analytics.com/ /es/ga.js/google-analytics.com/google-analytics.com/google-analytics.com/ga.js /ga.js/google-analytics.com/google-analytics.com/ga.js /services/google-analytics.com/google-analytics.com/ /services/google-analytics.com/google-analytics.com/google-analytics.com/ga.js /es/ga.js/google-analytics.com/ga.js/google-analytics.com/ga.js/ /ga.js/google-analytics.com/ga.js/google-analytics.com/ga.js/ /ga.js/google-analytics.com/ga.js/google-analytics.com/ /ga.js/google-analytics.com/ga.js/google-analytics.com/google-analytics.com/ga.js """ filename = urlParser.getFileName(reference) if filename: rindex = reference.rindex(filename) # 'ar9k' is just a random string to get a 404 new_reference = reference[:rindex] + "ar9k" + reference[rindex:] check_response = self._urlOpener.GET(new_reference, useCache=True, headers=headers) resp_body = response.getBody() check_resp_body = check_response.getBody() if relative_distance_ge(resp_body, check_resp_body, IS_EQUAL_RATIO): # If they are equal, then they are both a 404 (or something invalid) # om.out.debug( reference + ' was broken!') return else: