June 7, 2026
Visualizing Physical Attack Surface Exposure with Python, WiGLE, and Shodan
When preparing for an open-source investigation or a physical security assessment, it is easy to treat digital reconnaissance and physical…
Bharath Dibbadahalli Hanumanthappa
3 min read
When preparing for an open-source investigation or a physical security assessment, it is easy to treat digital reconnaissance and physical reconnaissance as two completely separate tasks. You look at an office building on Google Street View, and then you jump to a completely different browser tab to look up its corporate networks.
But in the real world, the digital footprint of a facility often extends beyond the physical boundaries of the property. If a company is running unencrypted Wi-Fi or exposing vulnerable IoT hardware to the public internet, those signals don't stop at the property line.
I wanted a simple, automated way to see exactly what a target facility is broadcasting into its immediate 500-meter environment before anyone ever steps foot on the property. To do that, I built a lightweight Python utility called Physical Attack Surface Mapper (GeoMapper).
The script essentially bridges the gap between geographic coordinates and open-source threat intelligence APIs, generating a localized, interactive HTML threat map. Here is how the tool works under the hood and why visualizing this data matters.
The Blueprint: How the Mapper Works
The core logic of the script is straightforward. It takes a single physical address and processes it through four main phases: geocoding, boundary math, API data harvesting, and map generation.
1. Geocoding and Bounding Box Math
You can't query spatial databases using a standard mailing address. The script uses the geopy library to interface with the Nominatim geocoding service, converting a human-readable address into precise latitude and longitude coordinates.
Once the target coordinates are locked, the script calculates a 500-meter bounding box. Because the Earth is a sphere, you can't just add flat numbers to latitude and longitude. The script utilizes basic spherical trigonometry (math.degrees and math.asin) to determine the exact North, South, East, and West GPS boundaries needed to constrain the upcoming API queries.
2. Sourcing the Wireless Footprint (WiGLE API)
With the boundary coordinates set, the script queries the WiGLE API. WiGLE is a massive, crowdsourced database of wireless networks observed globally through wardriving.
The tool pulls down every wireless network recorded within that 500-meter box, extracting the SSID (network name), BSSID (MAC address), and the configured encryption type. To make this information useful at a glance, the script automatically parses the encryption data and applies a basic risk matrix:
- Red: High-risk networks that are completely open, unencrypted, or using obsolete protocols like OWE.
- Orange: Medium-risk legacy setups, specifically flagging WEP networks.
- Blue: Standard wireless configurations utilizing WPA2 or WPA3.
3. Spotting Exposed Infrastructure (Shodan API)
Wireless access points are only half the story. The script concurrently interfaces with the Shodan API using its geographic filter (geo:lat,lon,radius).
This query searches for any internet-facing hardware, servers, or IoT devices physically located within that exact radius. It pulls back public IP addresses, open ports, and organization data, providing visibility into internet-facing infrastructure located within the target area.
4. Compiling the Intelligence Map
Finally, the script uses the folium library to ingest all these disparate data points and plot them onto an interactive map using CartoDB Voyager tiles.
The output is a single, self-contained target_map.html file. The target facility is marked with a black flag, surrounded by a faint red 500-meter collection ring. The surrounding area is populated with color-coded circles for the wireless networks and dark red warning markers for any exposed Shodan devices. Clicking on any marker pops up a clean HTML window detailing the technical specifics (SSIDs, encryption types, public IPs, and open ports).
Why Visualizing This Data Matters
When you are conducting passive reconnaissance, staring at raw JSON printouts or long CSV spreadsheets of MAC addresses and coordinates can quickly lead to alert fatigue. It is difficult to spot patterns in text.
By mapping the data geographically, an analyst can instantly identify structural security gaps. For example:
- Signal Leakage: You can visually track whether an unencrypted guest network or a legacy device is broadcasting far outside the physical perimeter of the building, making it accessible from a public parking lot or a nearby coffee shop.
- Infrastructure Proximity: You can see if an exposed web camera or server flagged by Shodan maps directly onto the target asset or if it belongs to a neighboring business sharing the same block.
Setup and Code
The script is entirely modular and written in Python 3. It relies on standard external libraries (folium, requests, shodan, geopy) and requires standard API keys from both WiGLE and Shodan.
The complete code, along with step-by-step setup instructions and installation requirements, is open-source and hosted on my GitHub:
🔗 Physical Attack Surface Mapper on GitHub
Like any OSINT-driven workflow, the results are only as accurate as the underlying data sources. WiGLE observations may be outdated, geolocation data may be imprecise, and Shodan indexing depends on when a host was last scanned. The map should therefore be treated as a reconnaissance aid rather than a definitive inventory of assets.
If you have any questions about getting the script running or want to chat about spatial reconnaissance workflows, feel free to drop a comment below or reach out on LinkedIn.
Note: This tool is intended entirely for authorized security assessments, threat intelligence research, and educational purposes. Always ensure you have explicit permission before analyzing or assessing any physical facility or its surrounding network footprint.