Phishing strani so pogosto narejeni tako, da 1:1 prekopirajo originalno stran, vključno s faviconom. Shodan za vsako HTTP storitev, ki jo skenira, izračuna hash favicona. Če poznaš hash favicona originalne strani, lahko najdeš vse strežnike, ki prikazujejo isto ikono, tudi tiste, ki niso uradni.
Korak 1: Poišči pravi favicon
Favicon ni vedno na /favicon.ico. Odpri izvorno kodo strani (Ctrl+U) in poišči oznako <link rel="icon" ...> ali <link rel="shortcut icon" ...>. Pot v atributu href je pravi favicon.
Korak 2: Izračunaj hash
Shodan ne uporablja klasičnega MD5 ali SHA-256 hasha. Vsebino ikone najprej pretvori v zapis Base64 (z prelomi vrstic na vsakih 76 znakov po standardu RFC 2045) in nad tem nizom izračuna 32-bitni predznačeni MurmurHash3.
Skripta favhash.py:
import sys, codecs, mmh3, requests, urllib3
from urllib.parse import urlparse, urljoin
from html.parser import HTMLParser
# Phishing strani in slabo nastavljeni strezniki imajo pogosto neveljaven
# ali nepopoln certifikat. Za prenos ikone preverjanje ni potrebno.
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
HEADERS = {"User-Agent": "Mozilla/5.0"}
class IconParser(HTMLParser):
"""Poisce vse <link rel="icon">, "shortcut icon", "apple-touch-icon" ..."""
def __init__(self):
super().__init__()
self.icons = []
def handle_starttag(self, tag, attrs):
if tag != "link":
return
a = dict(attrs)
if "icon" in (a.get("rel") or "").lower() and a.get("href"):
self.icons.append(a["href"])
def prenesi(url):
r = requests.get(url, timeout=10, verify=False, headers=HEADERS)
r.raise_for_status()
return r
if len(sys.argv) != 2:
sys.exit(f"Uporaba: python3 {sys.argv[0]} <URL strani ali ikone>")
url = sys.argv[1]
p = urlparse(url)
base = f"{p.scheme}://{p.netloc}/"
# Vedno preverimo /favicon.ico v korenu domene
kandidati = [urljoin(base, "favicon.ico")]
# Ce je URL stran, poiscemo ikone v HTML-ju, sicer je URL ze ikona
try:
r = prenesi(url)
if "text/html" in r.headers.get("Content-Type", ""):
parser = IconParser()
parser.feed(r.text)
kandidati += [urljoin(url, h) for h in parser.icons]
else:
kandidati.append(url)
except requests.RequestException as e:
print(f"[!] {url}: {e}")
for ikona in dict.fromkeys(kandidati): # odstrani duplikate, ohrani vrstni red
try:
r = prenesi(ikona)
except requests.RequestException as e:
print(f"[!] {ikona}: {e}")
continue
tip = r.headers.get("Content-Type", "?")
if "text/html" in tip:
print(f"[!] {ikona}: vrne HTML namesto slike (verjetno stran 404), preskakujem")
continue
h = mmh3.hash(codecs.encode(r.content, "base64"))
print(f"\n{ikona} ({tip}, {len(r.content)} B)")
print(f" Shodan: http.favicon.hash:{h}")
print(f" FOFA: icon_hash=\"{h}\"")
Skripta potrebuje knjižnico:
pip install mmh3 requests
Zagon:
python3 favhash.py https://www.primer-banka.si/favicon.ico

Hash lahko preveriš tudi brez skripte: v Shodanu odpri katerikoli rezultat uradne strani in v podrobnostih HTTP storitve najdeš vrednost
http.favicon.hash.
Korak 3: Poizvedba v Shodanu
Osnovna poizvedba:
http.favicon.hash:-1160765396
Rezultat vsebuje tudi uradne strežnike organizacije. Te izločiš z negativnimi filtri:
http.favicon.hash:-1234567890 -org:"Ime uradnega ponudnika" -ssl.cert.subject.cn:"primer-banka.si"
Uporabne kombinacije:
http.favicon.hash:X -ssl:“primer-banka.si” - Strežnike z ikono, a s tujim certifikatom
http.favicon.hash:X http.title:“Prijava” - Strani z ikono in naslovom prijavne strani
http.favicon.hash:X http.html:“password” - Strani z ikono in poljem za geslo
http.favicon.hash:X -country:SI - Kopije, gostovane izven Slovenije
http.favicon.hash:X port:8080,8443 - Kopije na nestandardnih vratih
Phishing ChatGPT:



