class dotNetErrors(baseDiscoveryPlugin):
    '''
    Request specially crafted URLs that generate ASP.NET errors in order to gather information.
    @author: Andres Riancho ( [email protected] )
    '''

    def __init__(self):
        baseDiscoveryPlugin.__init__(self)

        # Internal variables
        self._already_tested = ScalableBloomFilter()

    def discover(self, fuzzableRequest ):
        '''
        Requests the special filenames.
        
        @parameter fuzzableRequest: A fuzzableRequest instance that contains (among other things) the URL to test.
        '''
        if fuzzableRequest.getURL() not in self._already_tested:
            self._already_tested.add( fuzzableRequest.getURL() )

            # Generate the URLs to GET
            to_test = self._generate_URLs( fuzzableRequest.getURL() )
            for url in to_test:
                try:
                    response = self._urlOpener.GET( url, useCache=True )
                except KeyboardInterrupt,e:
                    raise e
                except w3afException,w3:
                    om.out.error( str(w3) )
                else:
                    self._analyze_response( response )
class frontpage_version(baseDiscoveryPlugin):
    '''
    Search FrontPage Server Info file and if it finds it will determine its version.
    @author: Viktor Gazdag ( [email protected] )
    '''

    def __init__(self):
        baseDiscoveryPlugin.__init__(self)
        
        # Internal variables
        self._analyzed_dirs = ScalableBloomFilter()
        self._exec = True

    def discover(self, fuzzableRequest ):
        '''
        For every directory, fetch a list of files and analyze the response.
        
        @parameter fuzzableRequest: A fuzzableRequest instance that contains (among other things) the URL to test.
        '''
        fuzzable_return_value = []
        
        if not self._exec:
            # This will remove the plugin from the discovery plugins to be runned.
            raise w3afRunOnce()
            
        else:
            # Run the plugin.
            self._exec = False

        for domain_path in urlParser.getDirectories(fuzzableRequest.getURL() ):

            if domain_path not in self._analyzed_dirs:

                # Save the domain_path so I know I'm not working in vane
                self._analyzed_dirs.add( domain_path )

                # Request the file
                frontpage_info_url = urlParser.urlJoin(  domain_path , "_vti_inf.html" )
                try:
                    response = self._urlOpener.GET( frontpage_info_url, useCache=True )
                    om.out.debug( '[frontpage_version] Testing "' + frontpage_info_url + '".' )
                except w3afException,  w3:
                    msg = 'Failed to GET Frontpage Server _vti_inf.html file: "'
                    msg += frontpage_info_url + '". Exception: "' + str(w3) + '".'
                    om.out.debug( msg )
                else:
                    # Check if it's a Fronpage Info file
                    if not is_404( response ):
                        fuzzable_return_value.extend( self._createFuzzableRequests( response ) )
                        self._analyze_response( response )
                        return fuzzable_return_value
Exemple #3
0
 def __init__(self):
     baseGrepPlugin.__init__(self)
     self._rss_tag_attr = [('rss', 'version', 'RSS'),# <rss version="...">
                           ('feed', 'version', 'OPML'),# <feed version="..."
                           ('opml', 'version', 'OPML') # <opml version="...">
                           ]
     self._already_inspected = ScalableBloomFilter()
    def __init__(self):
        baseDiscoveryPlugin.__init__(self)

        # Internal variables
        self._exec = True
        self._already_tested = ScalableBloomFilter()
        self._bad_codes = [ httpConstants.UNAUTHORIZED, httpConstants.NOT_IMPLEMENTED,
                                    httpConstants.METHOD_NOT_ALLOWED, httpConstants.FORBIDDEN]
        
        # Methods
        self._dav_methods = [ 'DELETE', 'PROPFIND', 'PROPPATCH', 'COPY', 'MOVE', 'LOCK', 
                                        'UNLOCK', 'MKCOL']
        self._common_methods = [ 'OPTIONS', 'GET', 'HEAD', 'POST', 'TRACE', 'PUT']
        self._uncommon_methods = ['*', 'SUBSCRIPTIONS', 'NOTIFY', 'DEBUG', 'TRACK', 'POLL', 'PIN', 
                                                    'INVOKE', 'SUBSCRIBE', 'UNSUBSCRIBE']
        
        # Methods taken from http://www.w3.org/Protocols/HTTP/Methods.html 
        self._proposed_methods = [ 'CHECKOUT', 'SHOWMETHOD', 'LINK', 'UNLINK', 'CHECKIN', 
                                                'TEXTSEARCH', 'SPACEJUMP', 'SEARCH', 'REPLY']
        self._extra_methods = [ 'CONNECT', 'RMDIR', 'MKDIR', 'REPORT', 'ACL', 'DELETE', 'INDEX', 
                                        'LABEL', 'INVALID']
        self._version_control = [ 'VERSION_CONTROL', 'CHECKIN', 'UNCHECKOUT', 'PATCH', 'MERGE', 
                                            'MKWORKSPACE', 'MKACTIVITY', 'BASELINE_CONTROL']       
        
        self._supported_methods = self._dav_methods  + self._common_methods + self._uncommon_methods
        self._supported_methods += self._proposed_methods + self._extra_methods
        self._supported_methods += self._version_control

 
        # User configured variables
        self._exec_one_time = True
        self._report_dav_only = True
Exemple #5
0
    def __init__(self):
        baseDiscoveryPlugin.__init__(self)
        
        # internal variables
        self._exec = True
        self._already_visited = ScalableBloomFilter()
        self._first_time = True
        self._show_remote_server = True
        
        # User configured parameters
        self._db_file = 'plugins' + os.path.sep + 'discovery' + os.path.sep + 'pykto'
        self._db_file += os.path.sep + 'scan_database.db'
        
        self._extra_db_file = 'plugins' + os.path.sep + 'discovery' + os.path.sep
        self._extra_db_file += 'pykto' + os.path.sep + 'w3af_scan_database.db'
        
        self._cgi_dirs = ['/cgi-bin/']
        self._admin_dirs = ['/admin/', '/adm/'] 
        self._users = ['adm', 'bin', 'daemon', 'ftp', 'guest', 'listen', 'lp',
        'mysql', 'noaccess', 'nobody', 'nobody4', 'nuucp', 'operator',
        'root', 'smmsp', 'smtp', 'sshd', 'sys', 'test', 'unknown']                  
        self._nuke = ['/', '/postnuke/', '/postnuke/html/', '/modules/', '/phpBB/', '/forum/']

        self._mutate_tests = False
        self._generic_scan = False
        self._update_scandb = False
        self._source = ''
 def __init__(self):
     baseGrepPlugin.__init__(self)
     
     self._already_reported = ScalableBloomFilter()
     
     # regex to split between words
     self._split_re = re.compile('[^\w]')
 def __init__(self):
     baseDiscoveryPlugin.__init__(self)
     
     # Internal variables
     self._already_visited = ScalableBloomFilter()
     
     # User configured parameters
     self._max_depth = 3
Exemple #8
0
 def __init__(self):
     baseGrepPlugin.__init__(self)
     
     self._tag_names = []
     self._tag_names.append('object')
     self._tag_names.append('applet')
     
     self._already_analyzed = ScalableBloomFilter()
 def __init__(self):
     baseDiscoveryPlugin.__init__(self)
     
     # Internal variables
     self._first_exec = True
     self._already_queried = ScalableBloomFilter()
     self._can_resolve_domain_names = False
     self._non_existant_response = None
    def __init__(self):
        baseGrepPlugin.__init__(self)

        # Only generate the lists once.
        # Adding 0,001% performance ;)
        self._already_inspected = ScalableBloomFilter()
        self._wsdl_strings = self._get_WSDL_strings()
        self._disco_strings = ['disco:discovery ']
 def __init__(self):
     baseGrepPlugin.__init__(self)
     
     self._already_visited = ScalableBloomFilter()
     
     # Added performance by compiling all the regular expressions
     # before using them. The setup time of the whole plugin raises,
     # but the execution time is lowered *a lot*.
     self._compiled_regex_list = [ re.compile(regex, re.IGNORECASE | re.DOTALL) for regex in self._get_indexing_regex() ]
Exemple #12
0
 def __init__(self):
     baseGrepPlugin.__init__(self)
     
     # Internal variables
     self._already_inspected = ScalableBloomFilter()
     
     # Create the regular expression to search for AJAX
     ajax_regex_string = '(XMLHttpRequest|eval\(|ActiveXObject|Msxml2\.XMLHTTP|'
     ajax_regex_string += 'ActiveXObject|Microsoft\.XMLHTTP)'
     self._ajax_regex_re = re.compile( ajax_regex_string, re.IGNORECASE )
Exemple #13
0
 def __init__(self):
     baseDiscoveryPlugin.__init__(self)
     self._already_visited = ScalableBloomFilter()
     self._first_time = True
     
     # This is for the Referer
     self._headers = {}
     
     # User options
     self._fuzz_images = False
     self._max_digit_sections = 4
Exemple #14
0
 def __init__(self):
     baseGrepPlugin.__init__(self)
     self._already_inspected = ScalableBloomFilter()
     # Add the regex to match something like this:
     #
     #   $Id: lzio.c,v 1.24 2003/03/20 16:00:56 roberto Exp $
     #   $Id: file name, version, timestamp, creator Exp $
     #
     regex = '\$.{1,12}: .*? .*? \d{4}[-/]\d{1,2}[-/]\d{1,2}'
     regex += ' \d{1,2}:\d{1,2}:\d{1,2}.*? (.*?) (Exp )?\$'
     self._regex_list = [ re.compile(regex) ]
Exemple #15
0
 def __init__(self):
     baseGrepPlugin.__init__(self)
     
     self._comments = {}
     self._search404 = False
     
     self._interesting_words = {'user':None, 'pass':None, 'microsoft':None,
     'visual':None, 'linux':None, 'source':None, 'author':None, 'release':None,
     'version':None, 'verify-v1':'Google Sitemap' }
     self._already_inspected = ScalableBloomFilter()
     
     '''
 def __init__(self):
     baseGrepPlugin.__init__(self)
     
     self._already_inspected = ScalableBloomFilter()
     
     # re that searches for
     #GET / HTTP/1.0
     self._re_request = re.compile('[a-zA-Z]{3,6} .*? HTTP/1.[01]')
     
     # re that searches for
     #HTTP/1.1 200 OK
     self._re_response = re.compile('HTTP/1.[01] [0-9][0-9][0-9] [a-zA-Z]*')
    def __init__(self):
        baseGrepPlugin.__init__(self)

        vsRegex = r'<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value=".*?" />'
        self._viewstate = re.compile( vsRegex, re.IGNORECASE|re.DOTALL)
        
        evRegex = r'<input type="hidden" name="__EVENTVALIDATION" '
        evRegex += 'id="__EVENTVALIDATION" value=".*?" />'
        self._eventvalidation = re.compile( evRegex, re.IGNORECASE|re.DOTALL)

        encryptedVsRegex = r'<input type="hidden" name="__VIEWSTATEENCRYPTED" '
        encryptedVsRegex += 'id="__VIEWSTATEENCRYPTED" value=".*?" />'
        self._encryptedVs = re.compile( encryptedVsRegex, re.IGNORECASE|re.DOTALL)

        self._already_reported = ScalableBloomFilter()
    def __init__(self):
        baseDiscoveryPlugin.__init__(self)

        # Internal variables
        self._compiled_ignore_re = None
        self._compiled_follow_re = None
        self._brokenLinks = []
        self._fuzzableRequests = []
        self._first_run = True
        self._already_crawled = disk_list()
        self._already_filled_form = ScalableBloomFilter()

        # User configured variables
        self._ignore_regex = ""
        self._follow_regex = ".*"
        self._only_forward = False
        self._compileRE()
Exemple #19
0
class phpEggs(baseDiscoveryPlugin):
    '''
    Fingerprint the PHP version using documented easter eggs that exist in PHP.
    @author: Andres Riancho ( [email protected] )
    '''
    def __init__(self):
        baseDiscoveryPlugin.__init__(self)
        self._exec = True
        
        # Already analyzed extensions
        self._already_analyzed_ext = ScalableBloomFilter()
        
        # This is a list of hashes and description of the egg for every PHP version.
        self._egg_DB = {}
        self._egg_DB["4.1.2"] = [ 
                ("744aecef04f9ed1bc39ae773c40017d1", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("85be3b4be7bfe839cbb3b4f2d30ff983", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.2.2"] = [ 
                ("758ccaa9094cdeedcfc60017e768137e", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("85be3b4be7bfe839cbb3b4f2d30ff983", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.3.10"] = [ 
                ("1e8fe4ae1bf06be222c1643d32015f0c", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("a57bd73e27be03a62dd6b3e1b537a72c", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.3.10-18"] = [ 
                ("1e8fe4ae1bf06be222c1643d32015f0c", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.3.11"] = [ 
                ("1e8fe4ae1bf06be222c1643d32015f0c", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("a8ad323e837fa00771eda6b709f40e37", "PHP Logo 2"), 
                ("a8ad323e837fa00771eda6b709f40e37", "Zend Logo") ]
        self._egg_DB["4.3.2"] = [ 
                ("8a8b4a419103078d82707cf68226a482", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("a57bd73e27be03a62dd6b3e1b537a72c", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.3.8"] = [ 
                ("96714a0fbe23b5c07c8be343adb1ba90", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("a57bd73e27be03a62dd6b3e1b537a72c", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.3.9"] = [ 
                ("f9b56b361fafd28b668cc3498425a23b", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB['4.3.10'] = [
                ('7b27e18dc6f846b80e2f29ecf67e4133', 'PHP Logo'),
                ('43af90bcfa66f16af62744e8c599703d', 'Zend Logo'),
                ('b233cc756b06655f47489aa2779413d7', 'PHP Credits'),
                ('185386dd4b2eff044bd635d22ae7dd9e', 'PHP Logo 2')] 
        self._egg_DB["4.4.0"] = [ 
                ("ddf16ec67e070ec6247ec1908c52377e", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.4.0 for Windows"] = [ 
                ("6d974373683ecfcf30a7f6873f2d234a", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.4.4"] = [ 
                ("bed7ceff09e9666d96fdf3518af78e0e", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.4.4-8+etch6"] = [ 
                ("31a2553efc348a21b85e606e5e6c2424", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["4.4.7"] = [ 
                ("72b7ad604fe1362f1e8bf4f6d80d4edc", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB['4.4.7, PleskWin, ASP.NET'] = [
                ('b8477b9b88e90f12e3200660a70eb765', 'Zend Logo'),
                ('b8477b9b88e90f12e3200660a70eb765', 'PHP Credits'),
                ('b8477b9b88e90f12e3200660a70eb765', 'PHP Logo 2'),
                ('b8477b9b88e90f12e3200660a70eb765', 'PHP Logo')]
        self._egg_DB["4.4.8"] = [ 
                ("4cdfec8ca11691a46f4f63839e559fc5", "PHP Credits"), 
                ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
                ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
                ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
        self._egg_DB["5.0.3"] = [ 
                ("def61a12c3b0a533146810403d325451", "PHP Credits"), 
                ("8ac5a686135b923664f64fe718ea55cd", "PHP Logo"), 
                ("37e194b799d4aaff10e39c4e3b2679a2", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.1.1"] = [ 
                ("5518a02af41478cfc492c930ace45ae5", "PHP Credits"), 
                ("8ac5a686135b923664f64fe718ea55cd", "PHP Logo"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.1.6"] = [ 
                ("4b689316409eb09b155852e00657a0ae", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.0"] = [ 
                ("e566715bcb0fd2cb1dc43ed076c091f1", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.0-8+etch10"] = [ 
                ("e566715bcb0fd2cb1dc43ed076c091f1", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.0-8+etch7"] = [ 
                ("307f5a1c02155ca38744647eb94b3543", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.1"] = [ 
                ("d3894e19233d979db07d623f608b6ece", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.2"] = [ 
                ("56f9383587ebcc94558e11ec08584f05", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.3-1+b1"] = [ 
                ("c37c96e8728dc959c55219d47f2d543f", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.4"] = [ 
                ("74c33ab9745d022ba61bc43a5db717eb", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.5"] = [ 
                ("f26285281120a2296072f21e21e7b4b0", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.4-2ubuntu5.3"] = [ 
                ("f26285281120a2296072f21e21e7b4b0", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.5-3"] = [ 
                ("b7e4385bd7f07e378d92485b4722c169", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("0152ed695f4291488741d98ba066d280", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.6"] = [ 
                ("bbd44c20d561a0fc5a4aa76093d5400f", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB["5.2.6RC4-pl0-gentoo"] = [ 
                ("d03b2481f60d9e64cb5c0f4bd0c87ec1", "PHP Credits"), 
                ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
                ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
                ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
        self._egg_DB['5.2.8-pl1-gentoo'] = [
                ('c48b07899917dfb5d591032007041ae3', 'PHP Logo'), 
                ('40410284d460552a6c9e10c1f5ae7223', 'PHP Credits'), 
                ('50caaf268b4f3d260d720a1a29c5fe21', 'PHP Logo 2'), 
                ('7675f1d01c927f9e6a4752cf182345a2', 'Zend Logo')]
        
    def discover(self, fuzzableRequest ):
        '''
        Nothing strange, just do some GET requests to the eggs and analyze the response.
        
        @parameter fuzzableRequest: A fuzzableRequest instance that contains (among other things) the URL to test.
        '''
        if not self._exec:
            # This will remove the plugin from the discovery plugins to be runned.
            raise w3afRunOnce()
        else:
            # Get the extension of the URL (.html, .php, .. etc)
            ext = urlParser.getExtension( fuzzableRequest.getURL() )
            
            # Only perform this analysis if we haven't already analyzed this type of extension
            # OR if we get an URL like http://f00b5r/4/     (Note that it has no extension)
            # This logic will perform some extra tests... but we won't miss some special cases
            # Also, we aren't doing something like "if 'php' in ext:" because we never depend
            # on something so changable as extensions to make decisions.
            if ext == '' or ext not in self._already_analyzed_ext:
                
                # Init some internal variables
                GET_results = []
                original_response = self._urlOpener.GET( fuzzableRequest.getURL(), useCache=True )
                
                # Perform the GET requests to see if we have a phpegg
                for egg, egg_desc in self._get_eggs():
                    egg_URL = urlParser.uri2url( fuzzableRequest.getURL() ) + egg
                    try:
                        response = self._urlOpener.GET( egg_URL, useCache=True )
                    except KeyboardInterrupt,e:
                        raise e
                    except w3afException, w3:
                        raise w3
                    else:
                        GET_results.append( (response, egg_desc, egg_URL) )
                        
                #
                #   Now I analyze if this is really a PHP eggs thing, or simply a response that
                #   changes a lot on each request. Before, I had something like this:
                #
                #       if relative_distance(original_response.getBody(), response.getBody()) < 0.1:
                #
                #   But I got some reports about false positives with this approach, so now I'm
                #   changing it to something a little bit more specific.
                images = 0
                not_images = 0
                for response, egg_desc, egg_URL in GET_results:
                    if 'image' in response.getContentType():
                        images += 1
                    else:
                        not_images += 1
                
                if images == 3 and not_images == 1:
                    #
                    #   The remote web server has expose_php = On. Report all the findings.
                    #
                    for response, egg_desc, egg_URL in GET_results:
                        i = info.info()
                        i.setPluginName(self.getName())
                        i.setName('PHP Egg - ' + egg_desc)
                        i.setURL( egg_URL )
                        desc = 'The PHP framework running on the remote server has a "'
                        desc += egg_desc +'" easter egg, access to the PHP egg is possible'
                        desc += ' through the URL: "'+  egg_URL + '".'
                        i.setDesc( desc )
                        kb.kb.append( self, 'eggs', i )
                        om.out.information( i.getDesc() )
                        
                        #   Only run once.
                        self._exec = False
                
                    # analyze the info to see if we can identify the version
                    self._analyze_egg( GET_results )
                
                # Now we save the extension as one of the already analyzed
                if ext != '':
                    self._already_analyzed_ext.add(ext)
Exemple #20
0
class metaTags(baseGrepPlugin):
    '''
    Grep every page for interesting meta tags.
      
    @author: Andres Riancho ( [email protected] )
    '''

    def __init__(self):
        baseGrepPlugin.__init__(self)
        
        self._comments = {}
        self._search404 = False
        
        self._interesting_words = {'user':None, 'pass':None, 'microsoft':None,
        'visual':None, 'linux':None, 'source':None, 'author':None, 'release':None,
        'version':None, 'verify-v1':'Google Sitemap' }
        self._already_inspected = ScalableBloomFilter()
        
        '''
        Can someone explain what this meta tag does?
        <meta name="verify-v1" content="/JBoXnwT1d7TbbWCwL8tXe+Ts2I2LXYrdnnK50g7kdY=" /> 
        
        Answer:
        That's one of the verification elements used by Google Sitemaps. When you sign up
        for Sitemaps you have to add that element to a root page to demonstrate to Google that
        you're the site owner. So there is probably a Sitemaps account for the site, if you 
        haven't found it already. 
        '''
        
    def grep(self, request, response):
        '''
        Plugin entry point, search for meta tags.

        @parameter request: The HTTP request object.
        @parameter response: The HTTP response object
        @return: None
        '''
        uri = response.getURI()
        
        if response.is_text_or_html() and not is_404( response ) and \
            uri not in self._already_inspected:

            self._already_inspected.add(uri)
            
            try:
                dp = dpCache.dpc.getDocumentParserFor( response )
            except w3afException:
                pass
            else:
                meta_tag_list = dp.getMetaTags()
                
                for tag in meta_tag_list:
                    name = self._find_name( tag )
                    for attr in tag:
                        for word in self._interesting_words:

                            # Check if we have something interesting
                            # and WHERE that thing actually is
                            where = value = None
                            if ( word in attr[0].lower() ):
                                where = 'name'
                                value = attr[0].lower()
                            elif ( word in attr[1].lower() ):
                                where = 'value'
                                value = attr[1].lower()
                            
                            # Now... if we found something, report it =)
                            if where:
                                # The atribute is interesting!
                                i = info.info()
                                i.setPluginName(self.getName())
                                i.setName('Interesting META tag')
                                i.setURI( response.getURI() )
                                i.setId( response.id )
                                msg = 'The URI: "' +  i.getURI() + '" sent a META tag with '
                                msg += 'attribute '+ where +' "'+ value +'" which'
                                msg += ' looks interesting.'
                                i.addToHighlight( where, value )
                                if self._interesting_words.get(name, None):
                                    msg += ' The tag is used for '
                                    msg += self._interesting_words[name] + '.'
                                i.setDesc( msg )
                                kb.kb.append( self , 'metaTags' , i )

                            else:
                                # The attribute is not interesting
                                pass
    
    def _find_name( self, tag ):
        '''
        @return: the tag name.
        '''
        for attr in tag:
            if attr[0].lower() == 'name':
                return attr[1]
        return ''
        
    def setOptions( self, optionsMap ):
        self._search404 = optionsMap['search404'].getValue()
    
    def getOptions( self ):
        '''
        @return: A list of option objects for this plugin.
        '''
        d1 = 'Search for meta tags in 404 pages.'
        o1 = option('search404', self._search404, d1, 'boolean')
        
        ol = optionList()
        ol.add(o1)
        return ol
    
    def end(self):
        '''
        This method is called when the plugin wont be used anymore.
        '''
        # Now print the information objects
        self.printUniq( kb.kb.getData( 'metaTags', 'metaTags' ), 'URL' )

    def getPluginDeps( self ):
        '''
        @return: A list with the names of the plugins that should be runned before the
        current one.
        '''
        return []
    
    def getLongDesc( self ):
        '''
        @return: A DETAILED description of the plugin functions and features.
        '''
        return '''
 def __init__(self):
     baseDiscoveryPlugin.__init__(self)
     
     # Internal variables
     self._already_tested = ScalableBloomFilter()
     self._new_fuzzable_requests = []
class wsdlFinder(baseDiscoveryPlugin):
    '''
    Find web service definitions files.
    
    @author: Andres Riancho ( [email protected] )
    '''

    def __init__(self):
        baseDiscoveryPlugin.__init__(self)
        
        # Internal variables
        self._already_tested = ScalableBloomFilter()
        self._new_fuzzable_requests = []
        
    def discover(self, fuzzableRequest ):
        '''
        If url not in _tested, append a ?wsdl and check the response.
        
        @parameter fuzzableRequest: A fuzzableRequest instance that contains (among other things) the URL to test.
        '''
        url = urlParser.uri2url( fuzzableRequest.getURL() )
        if url not in self._already_tested:
            self._already_tested.add( url )
            
            # perform the requests
            for wsdl_parameter in self._get_WSDL():
                url_to_request = url + wsdl_parameter
                
                #   Send the requests using threads:
                targs = ( url_to_request, )
                self._tm.startFunction( target=self._do_request, args=targs, ownerObj=self )
        
            # Wait for all threads to finish
            self._tm.join( self )
        
        return self._new_fuzzable_requests

    def _do_request(self, url_to_request):
        '''
        Perform an HTTP request to the url_to_request parameter.
        @return: None.
        '''
        try:
            self._urlOpener.GET( url_to_request, useCache=True )
        except w3afException:
            om.out.debug('Failed to request the WSDL file: ' + url_to_request)
        else:
            # The response is analyzed by the wsdlGreper plugin
            pass

    def _get_WSDL( self ):
        '''
        @return: A list of parameters that are used to request the WSDL
        '''
        res = []
        
        res.append( '?wsdl' )
        res.append( '?WSDL' )
        
        return res
        
    def getOptions( self ):
        '''
        @return: A list of option objects for this plugin.
        '''    
        ol = optionList()
        return ol
        
    def setOptions( self, OptionList ):
        '''
        This method sets all the options that are configured using the user interface 
        generated by the framework using the result of getOptions().
        
        @parameter OptionList: A dictionary with the options for the plugin.
        @return: No value is returned.
        ''' 
        pass

    def getPluginDeps( self ):
        '''
        @return: A list with the names of the plugins that should be run before the
        current one.
        '''
        return ['grep.wsdlGreper']
    
    def getLongDesc( self ):
        '''
        @return: A DETAILED description of the plugin functions and features.
        '''
        return '''
 def __init__(self):
     baseGrepPlugin.__init__(self)
     self._already_reported = ScalableBloomFilter()
class blankBody(baseGrepPlugin):
    '''
    Find responses with empty body.
      
    @author: Andres Riancho ( [email protected] )
    '''

    def __init__(self):
        baseGrepPlugin.__init__(self)
        self._already_reported = ScalableBloomFilter()
        
    def grep(self, request, response):
        '''
        Plugin entry point, find the blank bodies and report them.

        @parameter request: The HTTP request object.
        @parameter response: The HTTP response object
        @return: None

        Init
        >>> from core.data.url.httpResponse import httpResponse
        >>> from core.data.request.fuzzableRequest import fuzzableRequest
        >>> from core.controllers.misc.temp_dir import create_temp_dir
        >>> o = create_temp_dir()

        Simple test, empty string.
        >>> body = ''
        >>> url = 'http://www.w3af.com/'
        >>> headers = {'content-type': 'text/html'}
        >>> response = httpResponse(200, body , headers, url, url)
        >>> request = fuzzableRequest()
        >>> request.setURL( url )
        >>> request.setMethod( 'GET' )
        >>> b = blankBody()
        >>> b.grep(request, response)
        >>> assert len(kb.kb.getData('blankBody', 'blankBody')) == 1

        With some content.
        >>> kb.kb.save('blankBody','blankBody',[])
        >>> body = 'header body footer'
        >>> headers = {'content-type': 'text/html'}
        >>> response = httpResponse(200, body , headers, url, url)
        >>> b.grep(request, response)
        >>> assert len(kb.kb.getData('ssn', 'ssn')) == 0

        Strange method, empty body.
        >>> kb.kb.save('blankBody','blankBody',[])
        >>> body = ''
        >>> headers = {'content-type': 'text/html'}
        >>> response = httpResponse(200, body , headers, url, url)
        >>> request = fuzzableRequest()
        >>> request.setURL( url )
        >>> request.setMethod( 'ARGENTINA' )
        >>> b.grep(request, response)
        >>> assert len(kb.kb.getData('ssn', 'ssn')) == 0

        Response codes,
        >>> kb.kb.save('blankBody','blankBody',[])
        >>> body = ''
        >>> headers = {'content-type': 'text/html'}
        >>> response = httpResponse(401, body , headers, url, url)
        >>> request = fuzzableRequest()
        >>> request.setURL( url )
        >>> request.setMethod( 'GET' )
        >>> b.grep(request, response)
        >>> len(kb.kb.getData('ssn', 'ssn'))
        0
        '''
        if response.getBody() == '' and request.getMethod() in ['GET', 'POST']\
        and response.getCode() not in [401, 304, 204] and 'location' not in response.getLowerCaseHeaders()\
        and response.getURL() not in self._already_reported:
            
            #   report these informations only once
            self._already_reported.add( response.getURL() )
            
            #   append the info object to the KB.
            i = info.info()
            i.setPluginName(self.getName())
            i.setName('Blank body')
            i.setURL( response.getURL() )
            i.setId( response.id )
            msg = 'The URL: "'+ response.getURL()  + '" returned an empty body. '
            msg += 'This could indicate an error.'
            i.setDesc(msg)
            kb.kb.append( self, 'blankBody', i )
        
    def setOptions( self, OptionList ):
        '''
        Nothing to do here, no options.
        '''
        pass
    
    def getOptions( self ):
        '''
        @return: A list of option objects for this plugin.
        '''    
        ol = optionList()
        return ol
        
    def end(self):
        '''
        This method is called when the plugin wont be used anymore.
        '''
        self.printUniq( kb.kb.getData( 'blankBody', 'blankBody' ), None )
    
    def getPluginDeps( self ):
        '''
        @return: A list with the names of the plugins that should be runned before the
        current one.
        '''
        return []
    
    def getLongDesc( self ):
        '''
        @return: A DETAILED description of the plugin functions and features.
        '''
        return '''
class httpInBody (baseGrepPlugin):
    """
    Search for HTTP request/response string in response body.
    @author: Andres Riancho ( [email protected] )
    """
    def __init__(self):
        baseGrepPlugin.__init__(self)
        
        self._already_inspected = ScalableBloomFilter()
        
        # re that searches for
        #GET / HTTP/1.0
        self._re_request = re.compile('[a-zA-Z]{3,6} .*? HTTP/1.[01]')
        
        # re that searches for
        #HTTP/1.1 200 OK
        self._re_response = re.compile('HTTP/1.[01] [0-9][0-9][0-9] [a-zA-Z]*')
                
    def grep(self, request, response):
        '''
        Plugin entry point.
        
        @parameter request: The HTTP request object.
        @parameter response: The HTTP response object
        @return: None, all results are saved in the kb.
        '''
        uri = response.getURI()
        # 501 Code is "Not Implemented" which in some cases responds with this in the body:
        # <body><h2>HTTP/1.1 501 Not Implemented</h2></body>
        # Which creates a false positive.
        if response.getCode() != 501 and uri not in self._already_inspected \
            and response.is_text_or_html():
            # Don't repeat URLs
            self._already_inspected.add(uri)

            # First if, mostly for performance.
            # 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 'HTTP/1' in response and response.getClearTextBody() is not None:

                # Now, remove tags
                body_without_tags = response.getClearTextBody()

                res = self._re_request.search(body_without_tags)
                if res:
                    i = info.info()
                    i.setPluginName(self.getName())
                    i.setName('HTTP Request in HTTP body')
                    i.setURI(uri)
                    i.setId(response.id)
                    i.setDesc('An HTTP request was found in the HTTP body of a response')
                    i.addToHighlight(res.group(0))
                    kb.kb.append(self, 'request', i)

                res = self._re_response.search(body_without_tags)
                if res:
                    i = info.info()
                    i.setPluginName(self.getName())
                    i.setName('HTTP Response in HTTP body')
                    i.setURI(uri)
                    i.setId(response.id)
                    i.setDesc('An HTTP response was found in the HTTP body of a response')
                    kb.kb.append(self, 'response', i)

    def setOptions( self, optionsMap ):
        pass
            
    def getOptions( self ):
        '''
        @return: A list of option objects for this plugin.
        '''    
        ol = optionList()
        return ol
        
    def end(self):
        '''
        This method is called when the plugin wont be used anymore.
        '''
        for info_type in ['request', 'response']:
            
            if kb.kb.getData('httpInBody', info_type):
                msg = 'The following URLs have an HTTP '+ info_type +' in the HTTP response body:'
                om.out.information(msg)
                for i in kb.kb.getData('httpInBody', info_type):
                    om.out.information('- ' + i.getURI() + '  (id:' + str(i.getId()) + ')' )
        
    def getPluginDeps( self ):
        '''
        @return: A list with the names of the plugins that should be runned before the
        current one.
        '''
        return []
    
    def getLongDesc( self ):
        '''
        @return: A DETAILED description of the plugin functions and features.
        '''
        return '''
class allowedMethods(baseDiscoveryPlugin):
    '''
    Enumerate the allowed methods of an URL.
    @author: Andres Riancho ( [email protected] )
    '''

    def __init__(self):
        baseDiscoveryPlugin.__init__(self)

        # Internal variables
        self._exec = True
        self._already_tested = ScalableBloomFilter()
        self._bad_codes = [ httpConstants.UNAUTHORIZED, httpConstants.NOT_IMPLEMENTED,
                                    httpConstants.METHOD_NOT_ALLOWED, httpConstants.FORBIDDEN]
        
        # Methods
        self._dav_methods = [ 'DELETE', 'PROPFIND', 'PROPPATCH', 'COPY', 'MOVE', 'LOCK', 
                                        'UNLOCK', 'MKCOL']
        self._common_methods = [ 'OPTIONS', 'GET', 'HEAD', 'POST', 'TRACE', 'PUT']
        self._uncommon_methods = ['*', 'SUBSCRIPTIONS', 'NOTIFY', 'DEBUG', 'TRACK', 'POLL', 'PIN', 
                                                    'INVOKE', 'SUBSCRIBE', 'UNSUBSCRIBE']
        
        # Methods taken from http://www.w3.org/Protocols/HTTP/Methods.html 
        self._proposed_methods = [ 'CHECKOUT', 'SHOWMETHOD', 'LINK', 'UNLINK', 'CHECKIN', 
                                                'TEXTSEARCH', 'SPACEJUMP', 'SEARCH', 'REPLY']
        self._extra_methods = [ 'CONNECT', 'RMDIR', 'MKDIR', 'REPORT', 'ACL', 'DELETE', 'INDEX', 
                                        'LABEL', 'INVALID']
        self._version_control = [ 'VERSION_CONTROL', 'CHECKIN', 'UNCHECKOUT', 'PATCH', 'MERGE', 
                                            'MKWORKSPACE', 'MKACTIVITY', 'BASELINE_CONTROL']       
        
        self._supported_methods = self._dav_methods  + self._common_methods + self._uncommon_methods
        self._supported_methods += self._proposed_methods + self._extra_methods
        self._supported_methods += self._version_control

 
        # User configured variables
        self._exec_one_time = True
        self._report_dav_only = True
        
    def discover(self, fuzzableRequest ):
        '''
        Uses several technics to try to find out what methods are allowed for an URL.
        
        @parameter fuzzableRequest: A fuzzableRequest instance that contains (among other things) the URL to test.
        '''
        if not self._exec:
            # This will remove the plugin from the discovery plugins to be runned.
            raise w3afRunOnce()
            
        else:
            # Run the plugin.
            if self._exec_one_time:
                self._exec = False
            
            domain_path = urlParser.getDomainPath( fuzzableRequest.getURL() )
            if domain_path not in self._already_tested:
                self._already_tested.add( domain_path )
                self._check_methods( domain_path )
        return []
    
    def _check_methods( self, url ):
        '''
        Find out what methods are allowed.
        @parameter url: Where to check.
        '''
        allowed_methods = []
        with_options = False
        id_list = []
        
        # First, try to check available methods using OPTIONS, if OPTIONS isn't 
        # enabled, do it manually
        res = self._urlOpener.OPTIONS( url )
        headers = res.getLowerCaseHeaders()
        for header_name in ['allow', 'public']:
            if header_name in headers:
                allowed_methods.extend( headers[header_name].split(',') )
                allowed_methods = [ x.strip() for x in allowed_methods ]
                with_options = True
                allowed_methods = list(set(allowed_methods))

        # Save the ID for later
        if with_options:
            id_list.append( res.id )

        else:
            #
            #   Before doing anything else, I'll send a request with a non-existant method
            #   If that request succeds, then all will...
            #
            try:
                non_exist_response = self._urlOpener.ARGENTINA( url )
                get_response = self._urlOpener.GET( url )
            except:
                pass
            else:
                if non_exist_response.getCode() not in self._bad_codes\
                and get_response.getBody() == non_exist_response.getBody():
                    i = info.info()
                    i.setPluginName(self.getName())
                    i.setName( 'Non existent methods default to GET' )
                    i.setURL( url )
                    i.setId( [non_exist_response.getId(), get_response.getId()] )
                    msg = 'The remote Web server has a custom configuration, in which any non'
                    msg += ' existent methods that are invoked are defaulted to GET instead of'
                    msg += ' returning a "Not Implemented" response.'
                    i.setDesc( msg )
                    kb.kb.append( self , 'custom-configuration' , i )
                    #
                    #   It makes no sense to continue working, all methods will appear as enabled
                    #   because of this custom configuration.
                    #
                    return []

            
            # 'DELETE' is not tested! I don't want to remove anything...
            # 'PUT' is not tested! I don't want to overwrite anything...
            methods_to_test = self._supported_methods[:]
            
            # remove dups, and dangerous methods.
            methods_to_test = list(set(methods_to_test))
            methods_to_test.remove('DELETE')
            methods_to_test.remove('PUT')

            for method in methods_to_test:
                method_functor = getattr( self._urlOpener, method )
                try:
                    response = apply( method_functor, (url,) , {} )
                    code = response.getCode()
                except:
                    pass
                else:
                    if code not in self._bad_codes:
                        allowed_methods.append( method )
        
        # Added this to make the output a little more readable.
        allowed_methods.sort()
        
        # Check for DAV
        if len( set( allowed_methods ).intersection( self._dav_methods ) ) != 0:
            # dav is enabled!
            # Save the results in the KB so that other plugins can use this information
            i = info.info()
            i.setPluginName(self.getName())
            i.setName('Allowed methods for ' + url )
            i.setURL( url )
            i.setId( id_list )
            i['methods'] = allowed_methods
            msg = 'The URL "' + url + '" has the following allowed methods, which'
            msg += ' include DAV methods: ' + ', '.join(allowed_methods)
            i.setDesc( msg )
            kb.kb.append( self , 'dav-methods' , i )
        else:
            # Save the results in the KB so that other plugins can use this information
            # Do not remove these information, other plugins REALLY use it !
            i = info.info()
            i.setPluginName(self.getName())
            i.setName('Allowed methods for ' + url )
            i.setURL( url )
            i.setId( id_list )
            i['methods'] = allowed_methods
            msg = 'The URL "' + url + '" has the following allowed methods:'
            msg += ' ' + ', '.join(allowed_methods)
            i.setDesc( msg )
            kb.kb.append( self , 'methods' , i )
            
        return []
    
    def end( self ):
        '''
        Print the results.
        '''
        # First I get the data from the kb
        all_info_obj = kb.kb.getData( 'allowedMethods', 'methods' )
        dav_info_obj = kb.kb.getData( 'allowedMethods', 'dav-methods' )
        
        # Now I transform it to something I can use with groupbyMinKey
        allMethods = []
        for i in all_info_obj:
            allMethods.append( (i.getURL() , i['methods']) )
        
        davMethods = []
        
        for i in dav_info_obj:
            davMethods.append( (i.getURL() , i['methods']) )

        # Now I work the data...
        to_show, method_type = davMethods, ' DAV'
        if not self._report_dav_only:
            to_show, method_type = allMethods, ''
       

        # Make it hashable
        tmp = []
        for url, methodList in to_show:
            tmp.append( (url, ', '.join( methodList ) ) )
        
        result_dict, itemIndex = groupbyMinKey( tmp )
            
        for k in result_dict:
            if itemIndex == 0:
                # Grouped by URLs
                msg = 'The URL: "%s" has the following' + method_type + ' methods enabled:'
                om.out.information(msg % k)
            else:
                # Grouped by Methods
                msg = 'The methods: ' + k + ' are enabled on the following URLs:'
                om.out.information(msg)
            
            for i in result_dict[k]:
                om.out.information('- ' + i )
    
    def getOptions( self ):
        '''
        @return: A list of option objects for this plugin.
        '''
        d1 = 'Execute plugin only one time'
        h1 = 'Generally the methods allowed for a URL are \
          configured system wide, so executing this plugin only one \
          time is the faster choice. The safest choice is to run it against every URL.'
        o1 = option('execOneTime', self._exec_one_time, d1, 'boolean', help=h1)
        
        d2 = 'Only report findings if uncommon methods are found'
        o2 = option('reportDavOnly', self._report_dav_only, d2, 'boolean')
        
        ol = optionList()
        ol.add(o1)
        ol.add(o2)
        return ol
        
    def setOptions( self, optionsMap ):
        '''
        This method sets all the options that are configured using the user interface 
        generated by the framework using the result of getOptions().
        
        @parameter OptionList: A dictionary with the options for the plugin.
        @return: No value is returned.
        ''' 
        self._exec_one_time = optionsMap['execOneTime'].getValue()
        self._report_dav_only = optionsMap['reportDavOnly'].getValue()

    def getPluginDeps( self ):
        '''
        @return: A list with the names of the plugins that should be runned before the
        current one.
        '''
        return []

    def getLongDesc( self ):
        '''
        @return: A DETAILED description of the plugin functions and features.
        '''
        return '''
Exemple #27
0
class objects(baseGrepPlugin):
    '''
    Grep every page for objects and applets.
      
    @author: Andres Riancho ( [email protected] )
    '''

    def __init__(self):
        baseGrepPlugin.__init__(self)
        
        self._tag_names = []
        self._tag_names.append('object')
        self._tag_names.append('applet')
        
        self._already_analyzed = ScalableBloomFilter()

    def grep(self, request, response):
        '''
        Plugin entry point. Parse the object tags.
        
        @parameter request: The HTTP request object.
        @parameter response: The HTTP response object
        @return: None
        '''
        url = response.getURL()
        if response.is_text_or_html() and url not in self._already_analyzed:

            self._already_analyzed.add(url)
            
            dom = response.getDOM()

            # In some strange cases, we fail to normalize the document
            if dom is not None:
            
                for tag_name in self._tag_names:
                    
                    # Find all input tags with a type file attribute
                    element_list = dom.xpath('//%s' % tag_name )
                    
                    if element_list:
                        i = info.info()
                        i.setPluginName(self.getName())
                        i.setName(tag_name.title() + ' tag')
                        i.setURL(url)
                        i.setId( response.id )
                        i.setDesc( 'The URL: "' + i.getURL() + '" has an '+ tag_name + ' tag.' )          
                        i.addToHighlight( tag_name )

                        kb.kb.append( self, tag_name, i )
    
    def setOptions( self, OptionList ):
        pass
    
    def getOptions( self ):
        '''
        @return: A list of option objects for this plugin.
        '''    
        ol = optionList()
        return ol

    def end(self):
        '''
        This method is called when the plugin wont be used anymore.
        '''
        # Print objects
        self.printUniq( kb.kb.getData( 'objects', 'object' ), 'URL' )
        
        # Print applets
        self.printUniq( kb.kb.getData( 'objects', 'applet' ), 'URL' )
        
    def getPluginDeps( self ):
        '''
        @return: A list with the names of the plugins that should be runned before the
        current one.
        '''
        return []
    
    def getLongDesc( self ):
        '''
        @return: A DETAILED description of the plugin functions and features.
        '''
        return '''
Exemple #28
0
class getMails(baseGrepPlugin):
    '''
    Find email accounts.
      
    @author: Andres Riancho ( [email protected] )
    '''

    def __init__(self):
        baseGrepPlugin.__init__(self)
        # User configured variables
        self._only_target_domain = True
        self._already_inspected = ScalableBloomFilter()

    def grep(self, request, response):
        '''
        Plugin entry point, get the emails and save them to the kb.
        
        @parameter request: The HTTP request
        @parameter request: The HTTP response
        @return: None
        '''
        uri = response.getURI()
        if uri not in self._already_inspected:
            self._already_inspected.add(uri)
            self._grep_worker(request, response, 'mails', \
                    urlParser.getRootDomain(response.getURL()))
    
            if not self._only_target_domain:
                self._grep_worker(request, response, 'external_mails')
            
    def _grep_worker(self, request, response, kb_key, domain=None):
        '''
        Helper method for using in self.grep()
        
        @parameter request: The HTTP request
        @parameter request: The HTTP response
        @parameter kb_key: Knowledge base dict key
        @parameter domain: Target domain for getEmails filter
        @return: None
        '''
        # Modified when I added the pdfParser
        #if isTextOrHtml(response.getHeaders()):
        try:
            dp = dpCache.dpc.getDocumentParserFor( response )
        except w3afException:
            msg = 'If I can\'t parse the document, I won\'t be able to find any emails.'
            msg += ' Ignoring the response for "' + response.getURL() + '".'
            om.out.debug( msg )
            return

        mails = dp.getEmails(domain)
        
        for mail_address in mails:
            # Reduce false positives
            if request.sent( mail_address ):
                continue
                
            # Email address are case insensitive
            mail_address = mail_address.lower()
            url = response.getURL()

            email_map = {}
            for info_obj in kb.kb.getData( 'mails', 'mails'):
                mail_string = info_obj['mail']
                email_map[ mail_string ] = info_obj

            if mail_address not in email_map:
                # Create a new info object, and report it
                i = info.info()
                i.setPluginName(self.getName())
                i.setURL(url)
                i.setId( response.id )
                i.setName( mail_address )
                desc = 'The mail account: "'+ mail_address + '" was found in: '
                desc += '\n- ' + url
                desc += ' - In request with id: '+ str(response.id)
                i.setDesc( desc )
                i['mail'] = mail_address
                i['url_list'] = [url]
                i['user'] = mail_address.split('@')[0]
                i.addToHighlight( mail_address )
                kb.kb.append( 'mails', kb_key, i )
            
            else:
            
                # Get the corresponding info object.
                i = email_map[ mail_address ]
                # And work
                if url not in i['url_list']:
                    # This email was already found in some other URL
                    # I'm just going to modify the url_list and the description message
                    # of the information object.
                    id_list_of_info = i.getId()
                    id_list_of_info.append( response.id )
                    i.setId( id_list_of_info )
                    i.setURL('')
                    desc = i.getDesc()
                    desc += '\n- ' + url
                    desc += ' - In request with id: '+ str(response.id)
                    i.setDesc( desc )
                    i['url_list'].append(url)
        
    def setOptions( self, optionsMap ):
        self._only_target_domain = optionsMap['onlyTargetDomain'].getValue()
    
    def getOptions( self ):
        '''
        @return: A list of option objects for this plugin.
        '''    
        ol = optionList()
        d1 = 'When greping, only search mails for domain of target'
        o1 = option('onlyTargetDomain', self._only_target_domain, d1, 'boolean')
        
        ol = optionList()
        ol.add(o1)
        return ol

    def end(self):
        '''
        This method is called when the plugin wont be used anymore.
        '''
        self.printUniq( kb.kb.getData( 'mails', 'mails' ), None )
        self.printUniq( kb.kb.getData( 'mails', 'external_mails' ), None )
    
    def getPluginDeps( self ):
        '''
        @return: A list with the names of the plugins that should be runned before the
        current one.
        '''
        return []
    
    def getLongDesc( self ):
        '''
        @return: A DETAILED description of the plugin functions and features.
        '''
        return '''
Exemple #29
0
 def __init__(self):
     baseGrepPlugin.__init__(self)
     # User configured variables
     self._only_target_domain = True
     self._already_inspected = ScalableBloomFilter()
Exemple #30
0
 def __init__(self):
     baseDiscoveryPlugin.__init__(self)
     self._exec = True
     
     # Already analyzed extensions
     self._already_analyzed_ext = ScalableBloomFilter()
     
     # This is a list of hashes and description of the egg for every PHP version.
     self._egg_DB = {}
     self._egg_DB["4.1.2"] = [ 
             ("744aecef04f9ed1bc39ae773c40017d1", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("85be3b4be7bfe839cbb3b4f2d30ff983", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.2.2"] = [ 
             ("758ccaa9094cdeedcfc60017e768137e", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("85be3b4be7bfe839cbb3b4f2d30ff983", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.3.10"] = [ 
             ("1e8fe4ae1bf06be222c1643d32015f0c", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("a57bd73e27be03a62dd6b3e1b537a72c", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.3.10-18"] = [ 
             ("1e8fe4ae1bf06be222c1643d32015f0c", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.3.11"] = [ 
             ("1e8fe4ae1bf06be222c1643d32015f0c", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("a8ad323e837fa00771eda6b709f40e37", "PHP Logo 2"), 
             ("a8ad323e837fa00771eda6b709f40e37", "Zend Logo") ]
     self._egg_DB["4.3.2"] = [ 
             ("8a8b4a419103078d82707cf68226a482", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("a57bd73e27be03a62dd6b3e1b537a72c", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.3.8"] = [ 
             ("96714a0fbe23b5c07c8be343adb1ba90", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("a57bd73e27be03a62dd6b3e1b537a72c", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.3.9"] = [ 
             ("f9b56b361fafd28b668cc3498425a23b", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB['4.3.10'] = [
             ('7b27e18dc6f846b80e2f29ecf67e4133', 'PHP Logo'),
             ('43af90bcfa66f16af62744e8c599703d', 'Zend Logo'),
             ('b233cc756b06655f47489aa2779413d7', 'PHP Credits'),
             ('185386dd4b2eff044bd635d22ae7dd9e', 'PHP Logo 2')] 
     self._egg_DB["4.4.0"] = [ 
             ("ddf16ec67e070ec6247ec1908c52377e", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.4.0 for Windows"] = [ 
             ("6d974373683ecfcf30a7f6873f2d234a", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.4.4"] = [ 
             ("bed7ceff09e9666d96fdf3518af78e0e", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.4.4-8+etch6"] = [ 
             ("31a2553efc348a21b85e606e5e6c2424", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["4.4.7"] = [ 
             ("72b7ad604fe1362f1e8bf4f6d80d4edc", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB['4.4.7, PleskWin, ASP.NET'] = [
             ('b8477b9b88e90f12e3200660a70eb765', 'Zend Logo'),
             ('b8477b9b88e90f12e3200660a70eb765', 'PHP Credits'),
             ('b8477b9b88e90f12e3200660a70eb765', 'PHP Logo 2'),
             ('b8477b9b88e90f12e3200660a70eb765', 'PHP Logo')]
     self._egg_DB["4.4.8"] = [ 
             ("4cdfec8ca11691a46f4f63839e559fc5", "PHP Credits"), 
             ("11b9cfe306004fce599a1f8180b61266", "PHP Logo"), 
             ("4b2c92409cf0bcf465d199e93a15ac3f", "PHP Logo 2"), 
             ("da2dae87b166b7709dbd4061375b74cb", "Zend Logo") ]
     self._egg_DB["5.0.3"] = [ 
             ("def61a12c3b0a533146810403d325451", "PHP Credits"), 
             ("8ac5a686135b923664f64fe718ea55cd", "PHP Logo"), 
             ("37e194b799d4aaff10e39c4e3b2679a2", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.1.1"] = [ 
             ("5518a02af41478cfc492c930ace45ae5", "PHP Credits"), 
             ("8ac5a686135b923664f64fe718ea55cd", "PHP Logo"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.1.6"] = [ 
             ("4b689316409eb09b155852e00657a0ae", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.0"] = [ 
             ("e566715bcb0fd2cb1dc43ed076c091f1", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.0-8+etch10"] = [ 
             ("e566715bcb0fd2cb1dc43ed076c091f1", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.0-8+etch7"] = [ 
             ("307f5a1c02155ca38744647eb94b3543", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.1"] = [ 
             ("d3894e19233d979db07d623f608b6ece", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.2"] = [ 
             ("56f9383587ebcc94558e11ec08584f05", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.3-1+b1"] = [ 
             ("c37c96e8728dc959c55219d47f2d543f", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.4"] = [ 
             ("74c33ab9745d022ba61bc43a5db717eb", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.5"] = [ 
             ("f26285281120a2296072f21e21e7b4b0", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.4-2ubuntu5.3"] = [ 
             ("f26285281120a2296072f21e21e7b4b0", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.5-3"] = [ 
             ("b7e4385bd7f07e378d92485b4722c169", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("0152ed695f4291488741d98ba066d280", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.6"] = [ 
             ("bbd44c20d561a0fc5a4aa76093d5400f", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB["5.2.6RC4-pl0-gentoo"] = [ 
             ("d03b2481f60d9e64cb5c0f4bd0c87ec1", "PHP Credits"), 
             ("c48b07899917dfb5d591032007041ae3", "PHP Logo"), 
             ("50caaf268b4f3d260d720a1a29c5fe21", "PHP Logo 2"), 
             ("7675f1d01c927f9e6a4752cf182345a2", "Zend Logo") ]
     self._egg_DB['5.2.8-pl1-gentoo'] = [
             ('c48b07899917dfb5d591032007041ae3', 'PHP Logo'), 
             ('40410284d460552a6c9e10c1f5ae7223', 'PHP Credits'), 
             ('50caaf268b4f3d260d720a1a29c5fe21', 'PHP Logo 2'), 
             ('7675f1d01c927f9e6a4752cf182345a2', 'Zend Logo')]