Lion Cipher Lab
Flag impossible-travel logins by enriching auth logs with offline GeoIP
- SOC Analyst / Blue Team
- Intermediate
- ~45 min
- Free · no account required
Why it matters
When an attacker signs in with a stolen password the login is not malformed -- right username, right password, maybe even a passed MFA prompt. MITRE ATT&CK tracks this as T1078, Valid Accounts, and it is one of the hardest things a SOC catches because nothing is technically wrong. One of the few physical tells left is geography: a real person cannot sign in from New York and, twenty minutes later, from Singapore. Microsoft Entra ID Protection ships exactly this as a built-in risk detection. But the raw auth log your SIEM collects does not contain locations -- it contains IP addresses. Before…
What you'll learn
- treating an auth log as raw IPs and recognizing that impossible-travel detection is first an ENRICHMENT problem: you cannot judge travel until every source IP is mapped to a location
- building a tiny OFFLINE IP->(lat,lon,city,kind) lookup table in Python standard library that stands in for a commercial GeoIP database (MaxMind GeoLite2), using only non-routable test prefixes so it makes no false claim about real IP geography
- doing a longest-prefix CIDR lookup with the ipaddress module, and handling the IPs a GeoIP DB cannot place: CGNAT and some datacenter ranges carry no meaningful location, so their pairs must be skipped rather than guessed
- computing great-circle distance with the haversine formula and dividing by elapsed time to get an implied velocity, flagging anything faster than a commercial jet (> 900 km/h)
- measuring the detection honestly with precision and recall against a planted answer key: raw velocity scored precision 0.40 (2 true account takeovers among 5 flags) at recall 1.00
- raising precision without losing recall by adding a minimum-distance floor (0.40 -> 0.50, dropping an 8 km same-metro GeoIP-jitter flag) and then an egress/infra allowlist (-> 1.00, dropping the VPN and datacenter hops)
- naming where GeoIP enrichment lies: city accuracy is often only country-accurate, VPN and corporate egress relocate a real user, datacenter/CGNAT IPs have no location, and a shared account or a same-country attacker looks nothing like impossible travel
Steps in this lab
- Why enrichment is the hard part
- Generate a synthetic auth log -- IPs only, with a hidden answer key
- Build the offline GeoIP stub (a stand-in for MaxMind GeoLite2)
- Enrich with a CIDR lookup, then flag by haversine velocity (BEFORE)
- Tune 1: a minimum-distance floor for GeoIP jitter (AFTER, part 1)
- Tune 2: an egress/infra allowlist (AFTER, part 2)
- The honest negatives: where GeoIP enrichment lies
- The judgment: when impossible travel earns its noise