Example #1
0
    def check(self, address):

        self.webservices = []
        while (len(self.stack)):
            port = self.stack.pop()
            for protocol in ['http', 'https']:

                # Omite conflictos
                if (((protocol == 'http') and (port == 443))
                        or ((protocol == 'https') and (port == 80))):
                    continue
                h = Helper()
                if (((protocol == 'http') and (port == 80))
                        or ((protocol == 'https') and (port == 443))):
                    continue
                url = h.formatter(
                    '{}://{}:{}/',
                    [protocol, address, str(port)])
                # Uso del crawler
                crawler = WCrawler()

                result = None
                try:
                    result = crawler.httpRequest(url)
                    crawler.clearContext()

                except Exception as e:
                    pass

                if (
                        # No fue posible conectar con el servidor
                    (result is None) or

                        # Puerto abierto pero no es un servicio HTTP
                    (result['status-code'] == 0)):
                    continue

                # Obtiene el contenido de la etiqueta HTML <title>
                matches = re.search(br'<title>(.+?)<\/title>',
                                    result['response-content'], re.I | re.M)

                title = None
                if (matches):
                    title = str(matches.group(1))[2:][:-1]

                sm = result.get('status-message', '-').decode()
                sc = result.get('status-code')
                t = title if title else ''

                self.webservices.append({
                    'url': url,
                    'title': t,
                    'status-code': sc,
                    'status-message': sm
                })
Example #2
0
    def find(self, hostname, url=None):
        h = Helper()
        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo json
        result = None
        if url is None:
            req = h.formatter(
                'https://www.virustotal.com/ui/domains/{}/subdomains?limit=40',
                [hostname])
        else:
            req = url
        try:

            result = crawler.httpRequest(req)
            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            return []

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            return []

        try:
            # Convierte el resultado en un objeto de tipo json
            result = json.loads(result['response-content'])

        except Exception as e:
            return []

        # ¿Hay contenido de la respuesta HTTP?
        if (len(result['data']) == 0):
            return []

        # Procesa todos los subdominios encontrados en la página actual
        for item in result['data']:

            # Evita los resultados duplicados utilizando la pila local
            if (str(item['id']) in self.hostnames):
                continue

            # Agrega el subdominio encontrado a la pila local
            self.hostnames.append(str(item['id']))

        # ¿Necesita continuar paginando resultados?
        if (('links' in result) and ('next' in result['links'])
                and (result['links'])):
            self.find(hostname=hostname, url=str(result['links']['next']))

        return self.hostnames
Example #3
0
    def find(self, hostname):

        h = Helper()
        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo json
        result = None

        mp = 15
        q = h.formatter('domain:{}', [hostname])

        for p in range(1, 16):
            req = h.formatter('https://www.bing.com/search?q={}&first={}',
                              [q, p])
            try:
                result = crawler.httpRequest(req)
                # Libera la memoria (no es necesario un contexto de navegación)
                crawler.clearContext()
            except Exception as e:
                return []

            # ¿La respuesta HTTP es OK?
            if (result['status-code'] != 200):
                return []
            # Busca cada nombre de dominio
            # Ejemplo de resultados: <cite>https://foo<strong>ejemplo.com</strong>
            matches = re.findall(
                br'>([\w\.\-\_\$]+?\.' + re.escape(hostname).encode() + br')',
                result['response-content'].replace(
                    b'<strong>' + hostname.encode(), b'.' + hostname.encode()))

            if (len(matches) == 0):
                return []

            # Procesa cada nombre de dominio encontrado
            for item in matches:
                # ¿El resultado es un subdominio inválido?
                if (not item.decode().endswith('.' + hostname)):
                    continue

                # Evita los resultados duplicados utilizando la pila local
                if (item.decode() in self.hostnames):
                    continue

                # Agrega el subdominio encontrado a la pila local
                self.hostnames.append(item.decode())

        return self.hostnames
Example #4
0
    def findInLink(self, url, linkId, totalLinks, hostname):

        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo HTML
        result = None

        try:
            result = crawler.httpRequest(url=url)

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            return []

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            # Nothing
            return []

        # Busca todos los posibles subdominios
        matches = re.findall(
            br'>([\w\.\-\_\$]+?\.' + re.escape(hostname).encode() + br')<',
            result['response-content'])

        # ¿Hay resultados?
        if (len(matches) == 0):
            return []

        # Procesa cada nombre de dominio
        links = []
        for item in matches:
            it = item.decode()
            # Agrega el subdominio encontrado a la pila local
            links.append(it)

        return links
Example #5
0
    def find(self, hostname):
        h = Helper()
        # Uso del crawler
        crawler = WCrawler()
        crawler.defaultTimeout = 60

        # El resultado es de tipo json
        result = None

        req = h.formatter('https://crt.sh/?q=%.{}&output=json', [hostname])

        try:
            result = crawler.httpRequest(req)

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            return []

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            return []

        try:
            # Convierte el resultado en un objeto de tipo json
            result = json.loads(result['response-content'])

        except Exception as e:
            return []

        if ((not isinstance(result, list)) or (len(result) == 0)):
            return []

        hostnames = []
        # Procesa cada nombre de dominio encontrado
        for item in result:

            # Evita los resultados duplicados utilizando la pila local
            if (item['name_value'] in hostnames):
                continue

            # Agrega el subdominio encontrado a la pila local
            hostnames.append(item['name_value'])

        return hostnames
Example #6
0
    def find(self, hostname):
        h = Helper()
        # Uso del crawler
        crawler = WCrawler()
        crawler.defaultTimeout = 30

        # Resultado de tipo HTML
        result = None
        req = h.formatter('https://www.robtex.com/dns-lookup/{}', [hostname])
        try:
            result = crawler.httpRequest(req)

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            return []

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            return []

        # Elimina las etiquetas de negritas del resultado: foo.<b>domain.com</b>
        result['response-content'] = result['response-content'].replace(
            b'<b>', b'').replace(b'</b>', b'')

        # Busca todos los posibles subdominios
        matches = re.findall(
            br'>([\w\.\-\_\$]+?\.' + re.escape(hostname).encode() + br')<',
            result['response-content'])

        # ¿Hay resultados?
        if (len(matches) == 0):
            return []

        result = []
        # Procesa todos los resultados
        for item in matches:
            result.append(item.decode())

        return result
Example #7
0
    def paginate(self, pageNumber=1):

        # Contexto de la búsqueda de la página actual
        searchContext = {
            'max-pages': 15,
            'max-result': 10,
            'start-index': 1,
            'query': 'domain:' + self.context.baseHostname
        }

        # ¿Hay resultados del método actual?
        if (self.hostnames):

            # Excluye los subdominios ya conocidos
            searchContext['query'] += (' -domain:' +
                                       ' -domain:'.join(self.hostnames))

        # Número del resultado de inicio actual
        searchContext['start-index'] = ((
            (pageNumber - 1) * searchContext['max-result']) + 1)

        # Header message for pagination
        self.context.out(
            message=self.context.strings['methods']['bing']['pagination'])

        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo json
        result = None

        try:
            result = crawler.httpRequest(
                'https://www.bing.com/search?' + '&q=' +
                crawler.urlencode(searchContext['query']) + '&first=' +
                str(searchContext['start-index']))

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            self.context.out(
                self.context.strings['methods']['bing']['no-connect'])
            return

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            self.context.out(message=self.context.strings['methods']['bing']
                             ['wrong-status-http'],
                             parseDict={'id': result['status-code']})
            return

        # Busca cada nombre de dominio
        # Ejemplo de resultados: <cite>https://foo<strong>ejemplo.com</strong>
        matches = re.findall(
            br'>([\w\.\-\_\$]+?\.' +
            re.escape(self.context.baseHostname).encode() + br')',
            result['response-content'].replace(
                b'<strong>' + self.context.baseHostname.encode(),
                b'.' + self.context.baseHostname.encode()))

        if (len(matches) == 0):
            # No hay resultados
            self.context.out(
                self.context.strings['methods']['bing']['no-more-results'])
            return

        # Procesa cada nombre de dominio encontrado
        for item in matches:

            # ¿El resultado es un subdominio inválido?
            if (not item.decode().endswith('.' + self.context.baseHostname)):
                continue

            # Evita los resultados duplicados utilizando la pila local
            if (item.decode() in self.hostnames):
                continue

            # Agrega el subdominio encontrado a la pila local
            self.hostnames.append(item.decode())

            # Agrega el subdominio encontrado a la pila global de resultados
            self.context.addHostName(
                hostname=item.decode(),
                messageFormat=self.context.strings['methods']['bing']
                ['item-found'])

        # ¿Hay mas páginas donde buscar?
        if (not b'sw_next' in result['response-content']):
            self.context.out(
                self.context.strings['methods']['bing']['no-more-results'])
            return

        # Límite de busqueda de páginas
        if (pageNumber >= searchContext['max-pages']):
            self.context.out(
                self.context.strings['methods']['bing']['no-more-results'])
            return

        # Continua con la siguiente página
        self.paginate(pageNumber=pageNumber + 1)
Example #8
0
    def find(self):

        # Mensaje de la cabecera del método
        self.context.out(
            message=self.context.strings['method-begin'],
            parseDict={
                'current':
                self.context.progress['methods']['current'],
                'total':
                self.context.progress['methods']['total'],
                'title':
                self.context.strings['methods']['certificate-details']['title']
            })

        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo json
        result = None

        try:
            result = crawler.httpRequest(
                url='https://certificatedetails.com/api/list/' +
                crawler.urlencode(self.context.baseHostname))

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            self.context.out(self.context.strings['methods']
                             ['certificate-details']['no-connect'])
            return

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            self.context.out(message=self.context.strings['methods']
                             ['certificate-details']['wrong-status-http'],
                             parseDict={'id': result['status-code']})
            return

        try:
            # Convierte el resultado en un objeto de tipo json
            result = json.loads(result['response-content'])

        except Exception as e:
            self.context.out(self.context.strings['methods']
                             ['certificate-details']['corrupt-response'])
            return

        if ((not isinstance(result, list)) or (len(result) == 0)):
            self.context.out(self.context.strings['methods']
                             ['certificate-details']['empty'])
            return

        # Procesa cada nombre de dominio encontrado
        for item in result:

            # ¿Es un subdominio válido?
            if (not item['CommonName'].endswith('.' +
                                                self.context.baseHostname)):
                continue

            # Evita los resultados duplicados utilizando la pila local
            if (item['CommonName'] in self.hostnames):
                continue

            # Agrega el subdominio encontrado a la pila local
            self.hostnames.append(item['CommonName'])

            # Agrega el subdominio encontrado a la pila global de resultados
            self.context.addHostName(
                hostname=item['CommonName'],
                messageFormat=self.context.strings['methods']['crt-sh']
                ['item-found'])

        # Mensaje de cabecera del comienzo de la obtención de todos los enlaces
        self.context.out(self.context.strings['methods']['certificate-details']
                         ['find-links'])

        # Identificador actual del enlace
        linkId = 0

        # Procesa cada enlace
        # Precaución: Un mismo nombre de dominio repetido puede contener uno o
        #             más certificados diferentes.
        for item in result:

            linkId += 1

            self.findInLink(url='https://certificatedetails.com' +
                            item['Link'],
                            linkId=linkId,
                            totalLinks=len(result))
Example #9
0
    def findInLink(self, url, linkId, totalLinks):

        # Mensaje de cabereca de inicio de obtención del enlace
        self.context.out(message=self.context.strings['methods']
                         ['certificate-details']['find-link'],
                         parseDict={
                             'link-id': linkId,
                             'total-links': totalLinks
                         },
                         end='')

        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo HTML
        result = None

        try:
            result = crawler.httpRequest(url=url)

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            self.context.out(self.context.strings['methods']
                             ['certificate-details']['find-clear'],
                             end='')
            return

        self.context.out(self.context.strings['methods']['certificate-details']
                         ['find-clear'],
                         end='')

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            # Nothing
            return

        # Busca todos los posibles subdominios
        matches = re.findall(
            br'>([\w\.\-\_\$]+?\.' +
            re.escape(self.context.baseHostname).encode() + br')<',
            result['response-content'])

        # ¿Hay resultados?
        if (len(matches) == 0):
            return

        # Procesa cada nombre de dominio
        for item in matches:

            if (
                    # Evita los resultados duplicados utilizando la pila local
                (not item.decode() in self.hostnames) and

                    # ¿Es un subdominio válido?
                (item.decode().endswith('.' + self.context.baseHostname))):

                # Agrega el subdominio encontrado a la pila local
                self.hostnames.append(item.decode())

                # Agrega el subdominio encontrado a la pila global de resultados
                self.context.addHostName(
                    hostname=item.decode(),
                    messageFormat=self.context.strings['methods']
                    ['certificate-details']['item-found'])
Example #10
0
    def find(self, hostname):
        h = Helper()
        # Uso del crawler, por defecto guardará la cookie de sesión manteniendo
        # el contexto del flujo de la navegación.
        crawler = WCrawler()

        # El resultado es de tipo HTML
        result = None

        try:
            result = crawler.httpRequest(url='https://dnsdumpster.com/')

        except Exception as e:
            return []

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            return []

        # Busca el token XSRF
        matches = re.search(
            br'name=["\']csrfmiddlewaretoken["\']\s+value=["\'](.+?)["\']',
            result['response-content'], re.I | re.M)

        if (not matches):
            return []

        # Guarda el roken XSRF en la variable local para reutilizar la variable
        # 'matches'.
        tokenXsrf = matches.group(1)

        # El resultado es de tipo HTML
        result = None

        try:
            result = crawler.httpRequest(url='https://dnsdumpster.com/',
                                         postData={
                                             'csrfmiddlewaretoken': tokenXsrf,
                                             'targetip': hostname
                                         })

        except Exception as e:
            return []

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            return []

        # Busca todos los resultados
        matches = re.findall(
            br'>([\w\.\-\_\$]+?\.' + re.escape(hostname).encode() + br')<',
            result['response-content'])

        # ¿Hay resultados?
        if (len(matches) == 0):
            return []

        hostnames = []
        # Procesa todos los subdominios encontrados
        for item in matches:
            hostnames.append(item.decode())

        return hostnames
Example #11
0
    def find(self):

        # Mensaje de la cabecera del método
        self.context.out(
            message=self.context.strings['method-begin'],
            parseDict={
                'current': self.context.progress['methods']['current'],
                'total': self.context.progress['methods']['total'],
                'title':
                self.context.strings['methods']['dnsdumpster']['title']
            })

        # Paso 1: BçObtiene el Token XSRF y mantiene el contexto de navegación
        # para conservar la cookie de sesión.
        self.context.out(self.context.strings['methods']['dnsdumpster']
                         ['getting-token-xsrf'])

        # Uso del crawler, por defecto guardará la cookie de sesión manteniendo
        # el contexto del flujo de la navegación.
        crawler = WCrawler()

        # El resultado es de tipo HTML
        result = None

        try:
            result = crawler.httpRequest(url='https://dnsdumpster.com/')

        except Exception as e:
            self.context.out(
                self.context.strings['methods']['dnsdumpster']['no-connect'])
            return

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            self.context.out(message=self.context.strings['methods']
                             ['dnsdumpster']['wrong-status-http'],
                             parseDict={'id': result['status-code']})
            return

        # Busca el token XSRF
        matches = re.search(
            br'name=["\']csrfmiddlewaretoken["\']\s+value=["\'](.+?)["\']',
            result['response-content'], re.I | re.M)

        if (not matches):
            # No se pudo encontrar el token
            self.context.out(self.context.strings['methods']['dnsdumpster']
                             ['no-xsrf-token-found'])
            return

        # Guarda el roken XSRF en la variable local para reutilizar la variable
        # 'matches'.
        tokenXsrf = matches.group(1)

        # Paso 2: Envía la solicitud HTTP con el subdominio a buscar
        self.context.out(self.context.strings['methods']['dnsdumpster']
                         ['getting-subdomains'])

        # El resultado es de tipo HTML
        result = None

        try:
            result = crawler.httpRequest(url='https://dnsdumpster.com/',
                                         postData={
                                             'csrfmiddlewaretoken': tokenXsrf,
                                             'targetip':
                                             self.context.baseHostname
                                         })

        except Exception as e:
            self.context.out(
                self.context.strings['methods']['dnsdumpster']['no-connect'])
            return

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            print(result)
            self.context.out(message=self.context.strings['methods']
                             ['dnsdumpster']['wrong-status-http'],
                             parseDict={'id': result['status-code']})
            return

        # Busca todos los resultados
        matches = re.findall(
            br'>([\w\.\-\_\$]+?\.' +
            re.escape(self.context.baseHostname).encode() + br')<',
            result['response-content'])

        # ¿Hay resultados?
        if (len(matches) == 0):
            self.context.out(
                self.context.strings['methods']['dnsdumpster']['empty'])
            return

        # Procesa todos los subdominios encontrados
        for item in matches:

            # Agrega el subdominio encontrado a la pila global de resultados
            self.context.addHostName(
                hostname=item.decode(),
                messageFormat=self.context.strings['methods']['dnsdumpster']
                ['item-found'])
Example #12
0
    def find(self):

        # Mensaje de la cabecera del método
        self.context.out(message=self.context.strings['method-begin'],
                         parseDict={
                             'current':
                             self.context.progress['methods']['current'],
                             'total':
                             self.context.progress['methods']['total'],
                             'title':
                             self.context.strings['methods']['robtex']['title']
                         })

        # Uso del crawler
        crawler = WCrawler()
        crawler.defaultTimeout = 30

        # Resultado de tipo HTML
        result = None

        try:
            result = crawler.httpRequest(
                url='https://www.robtex.com/dns-lookup/' +
                crawler.urlencode(self.context.baseHostname))

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:

            # Imposible navegar
            self.context.out(
                self.context.strings['methods']['robtex']['no-connect'])

            return

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            self.context.out(message=self.context.strings['methods']['robtex']
                             ['wrong-status-http'],
                             parseDict={'id': result['status-code']})
            return

        # Elimina las etiquetas de negritas del resultado: foo.<b>domain.com</b>
        result['response-content'] = result['response-content'].replace(
            b'<b>', b'').replace(b'</b>', b'')

        # Busca todos los posibles subdominios
        matches = re.findall(
            br'>([\w\.\-\_\$]+?\.' +
            re.escape(self.context.baseHostname).encode() + br')<',
            result['response-content'])

        # ¿Hay resultados?
        if (len(matches) == 0):
            self.context.out(
                self.context.strings['methods']['robtex']['empty'])
            return

        # Procesa todos los resultados
        for item in matches:

            # Agrega el subdominio encontrado a la pila global de resultados
            self.context.addHostName(
                hostname=item.decode(),
                messageFormat=self.context.strings['methods']['robtex']
                ['item-found'])
Example #13
0
    def paginate(self, pageNumber=1):

        # Contexto de la búsqueda de la página actual
        searchContext = {
            'max-pages': 15,
            'max-result': 10,
            'start-index': 1,
            'query': 'site:' + self.context.baseHostname
        }

        # ¿Hay resultados del método actual?
        if (self.hostnames):

            # Excluye los subdominios ya conocidos
            searchContext['query'] += ' -site:' + ' -site:'.join(
                self.hostnames)

        # Número del resultado de inicio actual
        searchContext['start-index'] = ((
            (pageNumber - 1) * searchContext['max-result']) + 1)

        # Mensaje inicial de la paginación
        self.context.out(
            self.context.strings['methods']['google']['pagination'])

        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo json
        result = None

        try:
            # Navega
            result = crawler.httpRequest(
                'https://www.googleapis.com/customsearch/v1?' + 'cx=' +
                crawler.urlencode(self.googleCx) + '&key=' +
                crawler.urlencode(self.googleApiKey) + '&q=' +
                crawler.urlencode(searchContext['query']) + '&start=' +
                str(searchContext['start-index']) + '&filter=1&safe=off&num=' +
                str(searchContext['max-result']))

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:

            # Imposible navegar
            self.context.out(
                self.context.strings['methods']['google']['no-connect'])

            return

        # Los estados 403 y 400 indican que no hay más resultados o que la API
        # está saturada con solicitudes.
        if (result['status-code'] in [403, 400]):
            self.context.out(
                self.context.strings['methods']['google']['no-more-results'])
            return

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            self.context.out(message=self.context.strings['methods']['google']
                             ['wrong-status-http'],
                             parseDict={'id': result['status-code']})
            return

        try:
            # Convierte el resultado en un objeto de tipo json
            result = json.loads(result['response-content'])

        except Exception as e:

            # Contenido corrupto, no es de tipo json procesable
            self.context.out(
                self.context.strings['methods']['google']['corrupt-response'])

            return

        # ¿Hay resultados procesables?
        if ((not 'items' in result) or (len(result['items']) == 0)):

            # No hay más resultados
            self.context.out(
                self.context.strings['methods']['google']['no-more-results'])

            return

        # Procesa cada resultado
        for item in result['items']:

            # ¿El resultado es un subdominio inválido?
            if (not item['displayLink'].endswith('.' +
                                                 self.context.baseHostname)):
                continue

            # Evita los resultados duplicados utilizando la pila local
            if (item['displayLink'] in self.hostnames):
                continue

            # Agrega el subdominio encontrado a la pila local
            self.hostnames.append(item['displayLink'])

            # Agrega el subdominio encontrado a la pila global de resultados
            self.context.addHostName(
                hostname=item['displayLink'],
                messageFormat=self.context.strings['methods']['google']
                ['item-found'])

            # Retorna a la primera página nuevamente debido a que la búsqueda
            # debe contener la exclusión del subdominio encontrado, por ejemplo:
            # site: example.com -site:foo.example.com
            pageNumber = 0

        # Límite de busqueda de páginas
        if (pageNumber >= searchContext['max-pages']):
            self.context.out(
                self.context.strings['methods']['google']['no-more-results'])
            return

        # Continua con la siguiente página
        self.paginate(pageNumber=pageNumber + 1)
Example #14
0
    def find(self, hostname):

        h = Helper()

        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo json
        result = None
        req = h.formatter('https://certificatedetails.com/api/list/{}',
                          [hostname])
        try:
            result = crawler.httpRequest(req)
            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            return []

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            return []

        try:
            # Convierte el resultado en un objeto de tipo json
            result = json.loads(result['response-content'])

        except Exception as e:
            return []

        if ((not isinstance(result, list)) or (len(result) == 0)):
            return []

        # Procesa cada nombre de dominio encontrado
        items = []
        for item in result:
            subdomain = h.formatter('.{}', [hostname])
            # ¿Es un subdominio válido?
            if (not item['CommonName'].endswith(subdomain)):
                continue

            # Evita los resultados duplicados utilizando la pila local
            if (item['CommonName'] in items):
                continue

            # Agrega el subdominio encontrado a la pila local
            items.append(item['CommonName'])

        self.hostnames.append({'subdomains': list(set(items))})

        # Identificador actual del enlace
        linkId = 0

        # Procesa cada enlace
        # Precaución: Un mismo nombre de dominio repetido puede contener uno o
        #             más certificados diferentes.
        linkres = []
        for item in result:

            linkId += 1
            req = h.formatter('https://certificatedetails.com{}',
                              [item['Link']])
            linkres += self.findInLink(url=req,
                                       linkId=linkId,
                                       totalLinks=len(result),
                                       hostname=hostname)
        self.hostnames.append({'links': list(set(linkres))})
        return self.hostnames
Example #15
0
    def threadCheck(self):

        while (True):

            if (len(self.hostnameContext['check-ports']) == 0):
                # No hay mas puertos donde buscar
                break

            # Obtiene el siguente puerto a buscar de la pila local
            port = int(self.hostnameContext['check-ports'].pop())

            for protocol in ['http', 'https']:

                # Omite conflictos
                if (((protocol == 'http') and (port == 443))
                        or ((protocol == 'https') and (port == 80))):
                    continue

                # Compone la dirección URL final
                url = protocol + '://' + self.hostnameContext[
                    'current-hostname'] + '/'
                if (((protocol == 'http') and (port != 80))
                        or ((protocol == 'https') and (port != 443))):
                    url = protocol + '://' + self.hostnameContext[
                        'current-hostname'] + ':' + str(port) + '/'

                self.context.out(message=(
                    self.context.strings['filters']['http']['progress-clear'] +
                    self.context.strings['filters']['http']['progress']),
                                 parseDict={'url': url},
                                 end='')

                # Uso del crawler
                crawler = WCrawler()

                result = None
                try:
                    result = crawler.httpRequest(url)
                    crawler.clearContext()

                except Exception as e:
                    pass

                if (
                        # No fue posible conectar con el servidor
                    (result is None) or

                        # Puerto abierto pero no es un servicio HTTP
                    (result['status-code'] == 0)):
                    continue

                # Obtiene el contenido de la etiqueta HTML <title>
                matches = re.search(br'<title>(.+?)<\/title>',
                                    result['response-content'], re.I | re.M)

                title = None
                if (matches):
                    title = str(matches.group(1))[2:][:-1]

                self.context.out(message=(
                    self.context.strings['filters']['http']['progress-clear'] +
                    self.context.strings['filters']['http']['found'] + '\n' +
                    self.context.strings['filters']['http']['progress-wait']),
                                 parseDict={
                                     'url':
                                     url,
                                     'title': (title if title else ''),
                                     'status-code':
                                     (result['status-code']
                                      if result['status-code'] else '-'),
                                     'status-message':
                                     (result['status-message'].decode()
                                      if result['status-message'] else '-')
                                 },
                                 end='')

                # ¿Existe una estructura definida para el nombre de dominio?
                if (self.context.results['ip-address']['items'][
                        self.hostnameContext['current-ip-address']]['items']
                    ['hostnames']['items'][
                        self.hostnameContext['current-hostname']] is None):

                    # Crea la estructura de resultados
                    self.context.results['ip-address']['items'][
                        self.hostnameContext['current-ip-address']]['items'][
                            'hostnames']['items'][
                                self.hostnameContext['current-hostname']] = {
                                    'title':
                                    self.hostnameContext['current-hostname'],
                                    'items': {
                                        'http-services': {
                                            'title':
                                            self.context.strings['filters']
                                            ['http']['node-tree']
                                            ['http-title'],
                                            'items': {}
                                        }
                                    }
                                }

                # ¿La estructura de servicios HTTP existe para el nombre de dominio actual?
                if (not 'http-services' in self.context.results['ip-address']
                    ['items'][self.hostnameContext['current-ip-address']]
                    ['items']['hostnames']['items'][self.hostnameContext[
                        'current-hostname']]['items'].keys()):

                    # Añade la estructura de resultados a una ya existente
                    self.context.results['ip-address']['items'][
                        self.hostnameContext['current-ip-address']]['items'][
                            'hostnames']['items'][
                                self.hostnameContext['current-hostname']][
                                    'items']['http-services'] = {
                                        'title':
                                        self.context.strings['filters']['http']
                                        ['node-tree']['http-title'],
                                        'items': {}
                                    }

                # Mensaje final con el resultado
                nodeLine = self.context.parseString(
                    message=self.context.strings['filters']['http']
                    ['node-tree']['http-service'],
                    parseDict={
                        'url':
                        url,
                        'title': (title if title else ''),
                        'status-code': (result['status-code']
                                        if result['status-code'] else '-'),
                        'status-message': (result['status-message'].decode() if
                                           result['status-message'] else '-')
                    })

                # Agrega a lapila de resultados si no existe (como objeto)
                if (not nodeLine in self.context.results['ip-address']['items']
                    [self.hostnameContext['current-ip-address']]['items']
                    ['hostnames']['items'][
                        self.hostnameContext['current-hostname']]['items']
                    ['http-services']['items'].keys()):
                    self.context.results['ip-address']['items'][
                        self.hostnameContext['current-ip-address']]['items'][
                            'hostnames']['items'][self.hostnameContext[
                                'current-hostname']]['items']['http-services'][
                                    'items'][nodeLine] = None
Example #16
0
    def find(self, hostname):
        h = Helper()
        # ¿La llave de la API de Google existe?
        if (not self.googleApiKey.strip()):
            return []

        q = h.formatter('site:{}', [hostname])
        hostnames = []

        for i in range(1, 16):
            # ¿Hay resultados del método actual?
            if (hostnames):
                # Excluye los subdominios ya conocidos
                q += h.formatter('-site:{}', [' -site:'.join(hostnames)])
            # Uso del crawler
            crawler = WCrawler()

            # El resultado es de tipo json
            result = None
            req = h.formatter(
                'https://www.googleapis.com/customsearch/v1?cx={}&key={}&q={}&start={}&filter=1&safe=off&num={}',
                [self.googleCx, self.googleApiKey, q, i, 10])
            try:
                # Navega
                result = crawler.httpRequest(req)

                # Libera la memoria (no es necesario un contexto de navegación)
                crawler.clearContext()

            except Exception as e:
                break

            # Los estados 403 y 400 indican que no hay más resultados o que la API
            # está saturada con solicitudes.
            if (result['status-code'] in [403, 400]):
                break

            # ¿La respuesta HTTP es OK?
            if (result['status-code'] != 200):
                break

            try:
                # Convierte el resultado en un objeto de tipo json
                result = json.loads(result['response-content'])
            except Exception as e:
                break

            # ¿Hay resultados procesables?
            if ((not 'items' in result) or (len(result['items']) == 0)):
                break

            # Procesa cada resultado
            for item in result['items']:

                f = h.formatter('.{}', [hostname])
                # ¿El resultado es un subdominio inválido?
                if (not item['displayLink'].endswith(f)):
                    continue

                # Evita los resultados duplicados utilizando la pila local
                if (item['displayLink'] in hostnames):
                    continue

                # Agrega el subdominio encontrado a la pila local
                hostnames.append(item['displayLink'])

        return hostnames
Example #17
0
    def findInApi(self, nextUrl=None, pageId=1):

        # Mensaje de la paginación
        self.context.out(
            message=self.context.strings['methods']['virus-total']['paginating'],
            parseDict={
                'number': pageId
            }
        )

        # Uso del crawler
        crawler = WCrawler()

        # El resultado es de tipo json
        result = None

        try:
            if(nextUrl is None):
                result = crawler.httpRequest(
                    url='https://www.virustotal.com/ui/domains/' + crawler.urlencode(self.context.baseHostname) + '/subdomains?limit=40'
                )
            else:
                result = crawler.httpRequest(nextUrl)

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:

            # Imposible navegar
            self.context.out(
                self.context.strings['methods']['virus-total']['no-connect']
            )

            return

        # ¿La respuesta HTTP es OK?
        if(result['status-code'] != 200):
            self.context.out(
                message=self.context.strings['methods']['virus-total']['wrong-status-http'],
                parseDict={
                    'id': result['status-code']
                }
            )
            return

        try:
            # Convierte el resultado en un objeto de tipo json
            result = json.loads(result['response-content'])

        except Exception as e:

            # Contenido corrupto, no es de tipo json procesable
            self.context.out(
                self.context.strings['methods']['virus-total']['corrupt-response']
            )

            return

        # ¿Hay contenido de la respuesta HTTP?
        if(len(result['data']) == 0):

            # No hay contenido, por lo cual tampoco hay más resultados
            self.context.out(self.context.strings['methods']['virus-total']['no-more'])

            return

        # Procesa todos los subdominios encontrados en la página actual
        for item in result['data']:

            # Evita los resultados duplicados utilizando la pila local
            if(str(item['id']) in self.hostnames):
                continue

            # Agrega el subdominio encontrado a la pila local
            self.hostnames.append(str(item['id']))

            # Agrega el subdominio encontrado a la pila global de resultados
            self.context.addHostName(
                hostname=str(item['id']),
                messageFormat=self.context.strings['methods']['virus-total']['item-found']
            )

        # ¿Necesita continuar paginando resultados?
        if(
            ('links' in result) and
            ('next' in result['links']) and
            (result['links'])
        ):
            # Continua con la siguiente página
            self.findInApi(
                nextUrl=str(result['links']['next']),
                pageId=(pageId + 1)
            )
Example #18
0
    def find(self):

        # Mensaje de la cabecera del método
        self.context.out(message=self.context.strings['method-begin'],
                         parseDict={
                             'current':
                             self.context.progress['methods']['current'],
                             'total':
                             self.context.progress['methods']['total'],
                             'title':
                             self.context.strings['methods']['crt-sh']['title']
                         })

        # Uso del crawler
        crawler = WCrawler()
        crawler.defaultTimeout = 60

        # El resultado es de tipo json
        result = None

        try:
            result = crawler.httpRequest(
                url='https://crt.sh/?q=' +
                crawler.urlencode('%.' + self.context.baseHostname) +
                '&output=json')

            # Libera la memoria (no es necesario un contexto de navegación)
            crawler.clearContext()

        except Exception as e:
            self.context.out(
                self.context.strings['methods']['crt-sh']['no-connect'])
            return

        # ¿La respuesta HTTP es OK?
        if (result['status-code'] != 200):
            self.context.out(message=self.context.strings['methods']['crt-sh']
                             ['wrong-status-http'],
                             parseDict={'id': result['status-code']})
            return

        try:
            # Convierte el resultado en un objeto de tipo json
            result = json.loads(result['response-content'])

        except Exception as e:
            self.context.out(
                self.context.strings['methods']['crt-sh']['corrupt-response'])
            return

        if ((not isinstance(result, list)) or (len(result) == 0)):
            self.context.out(
                self.context.strings['methods']['crt-sh']['empty'])
            return

        # Procesa cada nombre de dominio encontrado
        for item in result:

            # Evita los resultados duplicados utilizando la pila local
            if (item['name_value'] in self.hostnames):
                continue

            # Agrega el subdominio encontrado a la pila local
            self.hostnames.append(item['name_value'])

            # Agrega el subdominio encontrado a la pila global de resultados
            self.context.addHostName(
                hostname=item['name_value'],
                messageFormat=self.context.strings['methods']['crt-sh']
                ['item-found'])