Metodolija phishing radara
#1

Izvinjavam se ako ovde nije pravo mesto za pokretanje ove teme, zanima me vaše mišljenje za metodologiju:

Radim na projektu Phishing Radar, koji u realnom vremenu prati izdavanje novih SSL/TLS sertifikata i pokušava da prepozna domene koji liče na poznate srpske brendove.
Voleo bih da čujem mišljenje ljudi koji se bave phishingom, threat intelligenceom, domenima ili razvojem sličnih sistema, pre svega o metodologiji detekcije i načinu bodovanja.
Sistem koristi Certificate Transparency podatke preko certstream.calidog.io WebSocket feeda. Svaki novi domen iz sertifikata poredi se sa listom praćenih brendova.
Trenutno je obuhvaćeno 28 brendova iz kategorija kao što su banke, telekomunikacije, državne institucije, kladionice, kurirske službe i energetika.
Za svaki domen izračunava se indikator sumnje od 0 do 100. Trenutni signali i bodovi su:
  • domen sadrži ključnu reč brenda: +40
  • homoglifska zamena karaktera: +50
  • typosquatting, odnosno jedna ili dve izmene prema Levenshtein distanci: +35
  • sumnjiv prefiks, poput secure, login, moj ili verify: +25
  • sumnjiv sufiks, poput login, auth, nalog ili pristup: +25
  • sumnjiv TLD, poput .xyz, .top, .club, .online ili .site: +15
  • strani TLD, odnosno domen koji nije pod .rs: +10
Domen se prikazuje kao potencijalno sumnjiv kada pređe prag od 30 bodova.
Važno je naglasiti da sistem trenutno ne utvrđuje da je domen zaista phishing. Ne proverava sadržaj sajta, DNS zapise, hosting, WHOIS podatke, reputaciju IP adrese niti da li je domen već prijavljen ili blokiran. To je za sada sistem za rano izdvajanje potencijalno interesantnih domena iz CT feeda, a ne alat koji donosi konačnu presudu.
Trenutna ograničenja su:
  • nema trajnog čuvanja podataka
  • nema deduplikacije domena
  • nema istorijskog prikaza
  • nema DNS ili HTTP provere
  • kratke ključne reči mogu praviti dosta lažnih pozitivnih rezultata
  • homoglif detekcija ne pokriva sve Unicode varijante
  • strani TLD trenutno automatski povećava rezultat, što možda nije uvek opravdano
  • svi signali se sabiraju linearno, bez uzimanja u obzir njihovih međusobnih odnosa
Najviše me zanimaju mišljenja o sledećem:
  1. Da li su signali koje koristim smisleni za početnu detekciju?
  2. Da li su bodovi približno dobro raspoređeni ili su neki signali precenjeni?
  3. Da li je prag od 30 prenizak?
  4. Da li bi domen koji nije pod .rs uopšte trebalo da dobija dodatne bodove?
  5. Kako biste rešili kratke nazive brendova poput A1, MTS, EPS ili APR?
  6. Da li bi Levenshtein distanca trebalo da zavisi od dužine naziva brenda?
  7. Koje dodatne signale biste smatrali najkorisnijim: starost domena, DNS, MX zapise, ASN, hosting provajdera, sadržaj stranice, favicon, forme za unos kredencijala ili nešto drugo?
  8. Da li bi bilo bolje koristiti pravila po brendu umesto jedinstvenog sistema bodovanja za sve?
  9. Kako biste merili kvalitet ovakvog sistema bez kvalitetnog skupa označenih phishing i legitimnih domena?
Svaka kritika metodologije je dobrodošla, naročito ako vidite očigledan način na koji bi trenutni model pravio veliki broj lažnih pozitivnih rezultata ili propuštao realne phishing domene.
Reply
#2

I ja pratim CT logove preko svog servera koristeći https://github.com/d-Rickyy-b/certstream-server-go

Nemam sad vremena da ti odgovorim na sva pitanja ali evo ti komanda kojom vadim samo ono što me zanima iz CT strima u fajl za dalju obradu, praćenje celog strima i procesirajne svakog zapisa je ekstremno zahtevno pa ovim suzavam ono što moram dalje da pregledam. Dobićeš neke ideje iz toga, prevaranti često registruju domene kao što su imefirme-rs.nekiTLD ili imefirme-srb.nekiTLD pa ti to može biti visoki indikator, rade i nešto kao što je banca.intesa-rs.com gde registruju samo deo imena a ostalo stave kao poddomen pa i to treba pratiti...

Code:
websocat -t --ping-interval 30 - autoreconnect:ws://127.0.0.1:8080/domains-only | grep --line-buffered -E 'serbia|srbija|belgrade|beograd|paket|postars|rsposta|posta|nalog|muphr|muprs|govrs|govhr|rsgov|eprekrsaj|euprav|iddeea|putev|rfzo|gov-rs|-srb\.|-rs\.|\.rs-"' >>
Reply
#3

Hvala, ovo je zlata vredno.
Grep pristup sa --line-buffered je pametan za initialni prefilter. Ja sam krenuo sličnom logikom ali sam na kraju napravio dedicated detector koji radi boundary matching po tokenima - upravo zbog problema koje si pomenuo:

- banca.intesa-rs.com - cross-label brand split, sad ga prepoznajem
- imefirme-rs.nekiTLD - imam to kao regional_impersonation_marker, dodaje bodove samo kad postoji potvrđen brand match
- imefirme-srb.nekiTLD - isto, pokrivam rs/srb/srbija/serbia/govrs/gov-rs

Tvoj regex mi je dao ideju za par stvari koje nisam pokrivao - eprekrsaj, iddeea, muphr, govhr. Vidim da pratiš i širi region (HR). To je logično jer napadači ciljaju ceo Balkan istom kampanjom.

Pitanje: koliko ti fajl dnevno naraste sa ovim filterom? I da li radiš neku dalju klasifikaciju posle grep-a ili ručno pregledaš?
Reply
#4

Fajl pa varira ali izgleda da je 5-8MB dnevno ali pored gornjeg regexa grabim i sve izdate na .rs ccTLD. Ali samo grepujem /domains-only sa imenima domena, ne čuvam specifikacije samih sertifikata što bi pravilo daleko glomaznije fajlove. Ne vidim potrebu za samim sertifikatima.

Nemam nikakvu aktivnu automatsku klasifikaciju nego ručno pregledam kad mi nešto treba ili kada nešto tražim evo sada intezu tražim često jer su pod kampanjom napada Detektovani lažni domeni Banca Intesa - intesa-banka.com i intesa-rs.com

Pregledam opet putem grepa, na primer trenutno za intezu

Code:
rg "intes" cert83.txt -N | cut -d\" -f 4 | sort -u

i onda ručno vidim dalje i ako treba da nađem sertifikat gledam na crt.sh ili pošto uglavnom ne radi idem na https://ipv4.bgp.he.net/certs, problem starih domena koji mi izlaze a ne trebaju rešavam redovnom promenom fajla u koji izbacujem grepovan strim tako da stari duplikati ne izlaze i uglavnom brzo nađem šta mi treba.

Naravno imam ideju da sve to bude daleko bolje odrađeno i automatizovano sa pretragom ali naći vremena za to je uvek problem, svakako čuvam istoriju svega što sam našao od kad sam krenuo početkom 2025. do danas.
Reply
#5

Jasno, znači ručni workflow ali efikasan - grep + sort -u + crt.sh/bgp.he.net za brzu istragu kad zatreba. I realno, za ciljano traženje (tipa Intesa kampanja) to sasvim radi.
Ono što si pomenuo za Intezu je zanimljivo - intesa-banka.com i intesa-rs.com su upravo obrasci koje moj detector pokriva. intesa-rs mi automatski dobija keyword + regional marker, a intesa-banka bi bio keyword + sufiks kad dodam "banka" u listu sumnjivih sufiksa (za sad nemam, ali ovo je dobar razlog da dodam).

Za problem starih duplikata - kod mene to rešavam dedup po canonical hostnameu sa occurrenceCount. Kad se isti domen pojavi opet, ne pravi novi zapis nego samo inkrementira counter i ažurira lastSeen. Tako uvek znam i kad se prvi put pojavio i koliko puta se vratio.
Za .rs ccTLD praćenje - to je odlična ideja koju nemam. Ja trenutno gledam samo domene koji matchuju brendove, ali novi .rs domen koji nije u mojoj allowlisti a sadrži nešto slično poznatom brendu bi bio jako dobar signal. Razmisliću da dodam .rs-specific filter. Što se tiče automatizacije - upravo to radim, da pretvori taj tvoj grep workflow u nešto sa live alertima i scoring-om. Ako bude zanimljivo kad bude gotovo, mogu ti dati pristup da uporediš sa svojim fajlovima.
Jedno pitanje: koliko često se vraćaju isti domeni u tvojim logovima? Tipa, da li napadači koriste isti domen danima ili brzo rotiraju?
Reply
#6

Svaka čast za projekat!

There is no patch for stupidity - Kevin Mitnick
Reply
#7

(08-08-2026, 03:32 PM)VincaSec Wrote:  Svaka čast za projekat!

Odlučio sam da zbog obima projekta se baziram samo na obrazovne sisteme. Sad cu malo detaljnije napisati kako je rađeno i svaki dodatni savet je dobrodošao.

Trenutno pratim CertStream i svaki novi hostname upoređujem sa kompletnim registrom od 2.059 obrazovnih ustanova, uz još 6 obrazovnih portala.
Da ne bih radio prosto poređenje svakog domena sa svih 2.059 ustanova, napravljen je invertovani indeks tokena, normalizacija ćirilice/latinice i dijakritika, kao i nekoliko različitih načina matchovanja u zavisnosti od toga koliko je naziv škole karakterističan.
Coverage audit trenutno pokazuje da je 2.057 od 2.059 ustanova moguće jednoznačno identifikovati.
Uz svaki pronađeni signal radi se i dodatni enrichment: DNS podaci (A/AAAA/MX/NS/CNAME), RDAP podaci poput registrara, datuma i statusa domena, kao i CT podaci - issuer, SAN itd.
Bitna stvar je da se target nikada ne otvara niti aktivno skenira. Sve se zasniva na pasivnim izvorima.
Podaci se čuvaju u SQLite-u, postoji SSE live stream, trenutno je oko 650 testova, registry matcher ima maksimalni score 75, a domeni se prikazuju defangovani.
Fokus sam namerno ograničio samo na obrazovanje, jer ovde imamo dobar javni izvor podataka, a škole i obrazovne ustanove su istovremeno vrlo zahvalna meta za phishing i impersonation napade.
Što se same matcher logike tiče, trenutno radi ovako:
1. Normalizacija naziva
I registry nazivi i hostname prolaze kroz potpuno istu funkciju.
Ćirilica se prevodi u latinicu, uklanjaju se dijakritici, a crtice, tačke, zarezi, zagrade i ostali separatori postaju granice između tokena.
Na primer:
Code:
hemijsko-prehrambena
i registarsko:
Code:
Хемијско-прехрамбена
na kraju daju iste tokene.
2. Izbor kandidata
Ne prolazim kroz svih 2.059 ustanova za svaki novi hostname.
Koristim nekoliko indeksa:
  • invertovani token indeks sa oko 1.472 tokena
  • indeks spojenih, kanonskih naziva
  • poseban lokacijski indeks za česta imena poput Vuk Karadžić ili Nikola Tesla
  • stop-set za reči kao što su
    Code:
    skola
    ,
    Code:
    osnovna
    ,
    Code:
    gimnazija
    ,
    Code:
    nikola
    ,
    Code:
    jovan
    itd.
Takve reči same po sebi nisu dovoljne da bi nešto bilo proglašeno signalom.
3. Ustanove su podeljene u tri grupe
Code:
distinctive_multi
- oko 1.526 ustanova.
Imaju najmanje dva dovoljno karakteristična tokena. Ako je naziv jedinstven, dovoljan je i dodatni kontekst poput
Code:
login
,
Code:
portal
,
Code:
nalog
itd. Ako naziv nije jedinstven, mora da postoji i odgovarajuća lokacija.
Code:
distinctive_single
- oko 392 ustanove.
Imaju samo jedan karakterističan token, pa su pravila stroža. Uglavnom se traže i lokacija i dodatni kontekst, osim kada je kompletan naziv ustanove direktno prisutan u hostnameu.
Code:
generic_location_bound
- oko 141 ustanova.
To su nazivi tipa „Gimnazija“ ili „Tehnička škola“. Tu nije dovoljan samo tip škole - mora da postoji pun naziv u pravilnom redosledu, jednoznačna lokacija i dodatni kontekst.
4. Dosta pažnje sam posvetio false-positive slučajevima
Na primer:
  • lokacija se ne računa kao distinctive deo naziva
  • pogrešan redosled tokena ne prolazi
  • ne mogu da se ubacuju proizvoljne reči između delova naziva
  • nepotpuna višerečna lokacija ne prolazi
  • ako hostname navede tip ustanove, matcher filtrira samo ustanove tog tipa
  • duži i specifičniji rezultat potiskuje kraći
  • registry matcher nikada ne može imati score veći od 75
Znači, recimo:
Code:
vuk-karadzic-login.com
nije dovoljan signal jer takvih ustanova ima više.
Ali:
Code:
nikola-tesla-boljevac-login.com
već ima i naziv, i lokaciju, i kontekst.
5. Scoring
Trenutna logika je otprilike:
  • jedinstven naziv + context = 40
  • jedinstven naziv + suspicious token odmah uz naziv = 65
  • čest naziv + lokacija + context = 75
  • generic tip + jedinstvena lokacija + context = 75
Adjacent bonus od +25 se daje samo ako je suspicious token poput
Code:
login
,
Code:
secure
,
Code:
verify
itd. neposredno pre ili posle naziva.
Na primer:
Code:
aleksinacka-gimnazija-login.com
→ 65
ali:
Code:
aleksinacka-gimnazija-foo-login.com
→ 40
jer
Code:
foo
prekida vezu između naziva i suspicious tokena.
Nekoliko konkretnih primera:
Code:
aleksinacka-gimnazija-login.com
→ MATCH, 65
Code:
nikola-tesla-boljevac-login.com
→ MATCH, 75
Code:
nikola-tesla-login.com
→ nema matcha, jer naziv nije jedinstven i nema lokacije
Code:
tehnicka-skola-nis-login.com
→ nema matcha, jer nije dovoljno jednoznačno
Code:
valjevo-login.com
→ nema matcha, jer sama lokacija nije signal
Code:
gimnazija-vrnjacka-banja-login.com
→ MATCH, 75
Pored toga postoji i mali kurirani sloj za 6 obrazovnih portala i 12 univerziteta.
Za njih postoje dodatna pravila za aliase, skraćenice poput
Code:
jisp
,
Code:
uns
,
Code:
zsk
, legitimne domene, leetspeak i typosquatting. Tu score može da ide do 100.
Registry matcher i taj kurirani matcher rade paralelno, a eventualni duplikati se kasnije spajaju preko
Code:
CURATED_REGISTRY_LINKS
.
Poenta mi je da sistem ne reaguje samo na fazon „u domenu se pojavilo ime škole“, jer bi to pravilo ogroman broj glupih alarma. Cilj je da signal mora da ima dovoljno konteksta da stvarno bude interesantan za proveru.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)