A Bluetooth Beacon is a loudspeaker in a crowded room: it broadcasts the same packet to everyone within range, with no pairing and no authentication by default. That openness is what makes beacons cheap and easy to deploy – but it also means anyone with a phone can read, clone, or forge your beacon traffic. This article maps the real threat model for a Bluetooth Beacon and the engineering controls that actually stop an attacker.
Why a beacon is exposed by design
A beacon advertises to be heard. Advertising packets are readable by any scanner, and the payload (iBeacon UUID / Major / Minor, Eddystone namespace/instance, or a custom MSD) is sent in cleartext unless you specifically encrypt it. There is no shared key negotiated at advertising time, so the radio cannot tell a legitimate gateway from a stranger’s phone.
The threat model
| Threat | What the attacker does | What it breaks |
|---|---|---|
| Eavesdropping | Passively logs advertising | Privacy, location leakage |
| Spoofing | Broadcasts a fake beacon with your IDs | Presence fraud, trigger abuse |
| Replay | Captures a valid packet, rebroadcasts later | “Still present” illusion |
| MITM / rogue gateway | Impersonates the gateway uplink | Data injection, tampering |
Eavesdropping: plaintext leaks location
A standard iBeacon frame carries a fixed UUID plus Major/Minor that often encode floor, zone, or asset class. An attacker sitting in the lobby logs the UUIDs and builds a map of your zones in an afternoon. Mitigations: use opaque, rotating IDs; never embed meaningful data in the static fields; keep the real mapping server-side.
Spoofing: fake presence
Because the beacon ID is public, an attacker broadcasts the same UUID/Major/Minor from a $10 dev board and your system now thinks an asset (or a customer) is where it isn’t. Retail: fake “loyalty present” events. Logistics: phantom pallets. The fix is authenticity – the receiver must cryptographically verify the packet came from a key holder, not just that the ID matches.
Replay: capture and rebroadcast
Replay is the simplest attack and the easiest to miss. An attacker records a valid advertising packet today and replays it next week to claim a beacon is “still here.” A raw iBeacon frame has no timestamp and no nonce, so the receiver cannot tell old from new. Adding a signed timestamp defeats it.
MITM and the rogue gateway
If your beacon talks to a gateway over an unencrypted link, a rogue gateway can inject or modify readings. The same applies if the gateway-to-cloud link is unauthenticated. Every hop needs its own integrity and, where the data is sensitive, confidentiality.
Crypto mitigations that work
Encrypted advertising. Put the meaningful payload inside an encrypted blob (AES-CCM under LE Secure Connections or a pre-shared key). The radio still broadcasts, but only key holders can read it.
Signed beacons. Stamp each packet with an ECDSA signature over the payload plus a timestamp. The receiver verifies before trusting:
def sign_beacon(payload, ts, priv_key):
msg = payload + ts # ts = coarse counter or unix time
sig = ecdsa_sign(msg, priv_key) # P-256 or Ed25519
return payload + ts + sig
def verify_beacon(advert, pub_key, window):
payload, ts, sig = split(advert)
if now() - ts > window: # e.g. 60 s
return REPLAY_DETECTED
return ecdsa_verify(payload + ts, sig, pub_key)
Rotating, volatile IDs. Mirror the privacy model of resolvable private addresses: broadcast a key-derived rotating ID that only your server can resolve. An eavesdropper sees a different ID every few minutes and cannot track.
Timestamp + nonce anti-replay. A monotonic counter or coarse timestamp inside the signed envelope makes each packet unique and short-lived.
Security vs cost trade-off
| Scheme | Confidentiality | Integrity | Replay resist | Power cost | Compatibility |
|---|---|---|---|---|---|
| Plaintext | None | None | None | None | Universal |
| Rotating ID | Weak | None | Partial | Low | Universal |
| Signed | None | Strong | Yes (timestamp) | Medium | Needs verifier |
| Encrypted | Strong | Strong | Yes (nonce) | High | Needs key |
Key provisioning and hardware root
The signature is only as trustworthy as the private key. Store it in a secure element or derive it from a PUF so it cannot be read out of the firmware image. This is the same root-of-trust discipline used for secure boot: the beacon’s identity is burned in at the factory, not loaded from flash at runtime.
Operational detection
Even with crypto, watch the air:
- RSSI anomaly: a beacon suddenly reading +20 dB stronger suggests a closet spoofer nearby.
- Duplicate ID from two locations at once: physically impossible – flag it.
- Gateway whitelisting: only accept uplinks from known gateway certificates.
Standards to lean on
Apple Find My and the cross-platform Detecting Unwanted Location Trackers spec define anti-stalking behaviors (separation alerts, audible chirps) you should mirror for consumer tags. Device Provisioning Protocol (DPP) gives a clean onboarding story for gateways.
OEM checklist
1. Decide the threat model before picking a scheme – most deployments need signed, not encrypted.
2. Store keys in a secure element / PUF, never in app flash.
3. Add a timestamp or counter to every packet; verify the window.
4. Rotate public IDs on a schedule the server can resolve.
5. Ship a way to revoke and re-key a compromised beacon.
A Bluetooth Beacon earns trust the same way anything else does: by proving, on every packet, that it is who it claims to be.