-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathFindFavIcon.py
107 lines (98 loc) · 4.13 KB
/
FindFavIcon.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import argparse
import configparser
import requests
import logging
from bs4 import BeautifulSoup
from urllib.parse import urljoin
import codecs
import mmh3
import shodan
# Configuración inicial de logging
logging.basicConfig(level=logging.INFO)
def main():
parser = argparse.ArgumentParser(prog='faviconfrenzy', description='Busca el favicon de una URL proporcionada, calcula su hash y lo envía a Shodan para análisis.')
parser.add_argument('-u', '--url', type=str, required=True, help='URL para buscar el FavIcon.')
parser.add_argument('-ak', '--addshodankey', dest='shodankey', type=str, help='Almacena o reemplaza la clave Shodan en el archivo de configuración.')
parser.add_argument('-t', '--topresults', type=int, default=10, help='Número máximo de resultados a mostrar, por defecto es 10.')
parametros = parser.parse_args()
session = requests.Session() # Uso de sesiones para optimizar las solicitudes HTTP
absoluteIconPath = getFavIconPath(session, parametros.url)
if absoluteIconPath:
logging.info(f'url: {parametros.url}')
logging.info(f'FavIconPath: {absoluteIconPath}')
favicon, hash = getfavicon(absoluteIconPath)
if hash:
logging.info(f'hash: {hash}')
shodanQuery(hash, parametros.topresults, session)
if parametros.shodankey:
store_shodan_key(parametros.shodankey)
else:
logging.warning('No se encontró favicon.')
else:
logging.warning('No se encontró favicon.')
def getFavIconPath(session, url):
headers = {
'User-Agent': 'Mozilla/5.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'es-ES,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1'
}
favicon_paths = ['', 'favicon.ico', 'html_public/favicon.ico']
for path in favicon_paths:
try:
icon_url = urljoin(url, path) if path else url
response = session.get(icon_url, headers=headers, timeout=10)
if response.status_code == 200:
logging.info(f'Favicon encontrado en: {icon_url}')
return icon_url
except requests.RequestException as e:
logging.error(f'Error al obtener favicon: {e}')
logging.warning('No se encontró favicon en las rutas probadas')
return None
def getfavicon(absoluteIconPath):
try:
response = requests.get(absoluteIconPath, timeout=10)
favicon = codecs.encode(response.content, 'base64')
hash = mmh3.hash(favicon)
return favicon, hash
except requests.RequestException as e:
logging.error(f'Error al obtener hash de favicon: {e}')
return None, None
def shodanQuery(hash, topresults, session):
api_key = get_shodan_key()
if api_key:
api = shodan.Shodan(api_key)
query = f'http.favicon.hash:{hash}'
try:
results = api.search(query, limit=topresults)
if not results['matches']:
logging.warning('No se encontraron resultados en Shodan')
else:
for count, host in enumerate(results['matches'], start=1):
# Imprimir detalles de cada host aquí
pass
except shodan.APIError as e:
logging.error(f'Error en consulta Shodan: {e}')
else:
logging.warning('Clave API de Shodan no encontrada')
def store_shodan_key(shodankey):
config = configparser.ConfigParser()
config['SHODAN'] = {'key': shodankey}
try:
with open('faviconfrenzy.ini', 'w') as configfile:
config.write(configfile)
logging.info('Clave Shodan almacenada con éxito')
except IOError as e:
logging.error(f'Error al almacenar clave Shodan: {e}')
def get_shodan_key():
config = configparser.ConfigParser()
try:
config.read('faviconfrenzy.ini')
return config.get('SHODAN', 'key', fallback=None)
except configparser.Error as e:
logging.error(f'Error al leer clave Shodan: {e}')
return None
if __name__ == '__main__':
main()