A security research toolkit for analyzing wireless payment terminals on commercial laundry machines. Demonstrates critical vulnerabilities in BLE-based payment systems including plaintext command transmission, static device secrets, and missing payment-activation coupling.
Commercial laundry machines using wireless payment terminals (e.g. Airwallet/Circuit GO) have several architectural security flaws:
- Plaintext BLE Commands — Activation commands are sent as readable ASCII strings over GATT characteristics with no encryption
- Static Secrets — 9-character device passwords are stored in Firebase and never rotated
- No Payment Verification — The physical terminal does not verify that a payment was processed before accepting activation
- Weak Access Controls — Any authenticated Firebase user can read device configurations for all locations
You need a Mac with Bluetooth and an iPhone on the same Wi-Fi network.
Skip this if you already have Homebrew. If you're not sure, type brew --version in Terminal — if it prints a version number, skip to Step 2.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"This takes a few minutes. It may look like nothing is happening — that's normal. Don't close the terminal. When it finishes, it will print 2-3 commands to run. Copy and run those commands, then close and reopen your terminal.
brew install python@3.13 pipx mitmproxyThis can take 2-5 minutes depending on your internet speed. The terminal may appear frozen while it downloads — this is normal, just let it run. If you see warnings like "already installed" that's totally fine, it just means you already have it.
Then run:
pipx ensurepathClose and reopen your terminal after this step. This is important — the commands won't be found if you skip this.
pipx install git+https://github.com/alexanderthegreat124680-hub/airwave.gitVerify it worked:
airwave --versionIf you see
airwave, version 1.0.0you're good to go. If you get "command not found", close and reopen your terminal and try again.
Make sure your Mac and iPhone are on the same Wi-Fi network before starting.
airwave setupThis automatically starts a proxy on your Mac. You'll see instructions like:
Proxy running on 192.168.1.42:8080
On your iPhone:
1. Go to Settings → Wi-Fi → tap your network → Configure Proxy → Manual
Server: 192.168.1.42 Port: 8080
2. Open Safari → go to mitm.it → tap Apple → download the profile
Then go to Settings → General → VPN & Device Management → install it
3. Go to Settings → General → About → Certificate Trust Settings
Toggle ON full trust for mitmproxy
4. Open the Circuit Laundry (or Airwallet) app and browse your machines
Waiting for app traffic...
"Waiting for app traffic..." will sit there until you complete the phone steps. This is normal — it's waiting for you. It is not frozen. Just follow the steps on your phone and it will automatically detect the traffic and continue.
Once the app traffic is captured, airwave automatically extracts credentials, downloads device configs, and scans for nearby BLE devices. You'll see "Setup complete" when it's done.
IMPORTANT — Turn off the proxy when done: After setup completes, immediately go to your iPhone: Settings → Wi-Fi → tap your network → Configure Proxy → Off. If you skip this, your phone won't be able to access the internet until you turn it off. This is because the proxy on your Mac stops running after setup, so your phone will be trying to route traffic through something that no longer exists.
If mitm.it doesn't load on your phone: Make sure your Mac and phone are on the same Wi-Fi. Double-check the IP address and port in your proxy settings match exactly what the terminal shows. If it still doesn't work, press Ctrl+C in the terminal, disconnect from Wi-Fi on your phone and reconnect, then run
airwave setupagain.
If the laundry app doesn't trigger capture: Make sure you actually browse the machines in the app (tap into a location, view the washers/dryers). Just opening the app to the home screen may not be enough — you need to navigate into a location so the app fetches device data.
Alternative method — if you have the laundry app email/password and are standing near the machines:
airwave setup --loginYou need to be within Bluetooth range of the machine (a few meters).
airwave run washerairwave run dryerIf you get "Device not found nearby": Make sure Bluetooth is on and you're close to the machine. Try running
airwave scanfirst to check what's in range.
airwave scanLists all compatible BLE devices in range with their names, addresses, and signal strength.
airwave infoShows your saved site, machines, and whether your auth token is set.
| Problem | Fix |
|---|---|
command not found after install |
Close and reopen your terminal, then try again |
brew: command not found |
You need to install Homebrew (Step 1) or run the PATH commands it printed |
mitmproxy is not installed |
Run brew install mitmproxy |
| Phone can't load websites after setup | Go to Wi-Fi settings on phone → Configure Proxy → Off |
mitm.it doesn't load on phone |
Check phone and Mac are on same Wi-Fi, and proxy IP/port match |
| "Waiting for app traffic" sits forever | Open the laundry app and browse into a location to trigger traffic |
| Setup timed out | Press Ctrl+C, check your phone proxy settings, and run airwave setup again |
Device not found nearby |
Make sure Bluetooth is on and you're within a few meters of the machine |
externally-managed-environment error |
Use pipx install instead of pip install |
- Traffic Capture: Intercepts the mobile app's HTTPS traffic to extract Firebase auth tokens and location IDs
- Device Discovery: Queries Firebase Realtime Database for device configurations (passwords, program settings)
- BLE Scan: Uses Bluetooth LE to find nearby compatible terminals
- Command Sequence: Sends
[HANDSHAKE:ENABLE]→[ACTIVATE:...]→[EXEC]over GATT characteristics - No Payment: The terminal accepts the command without verifying any payment occurred
airwave/
├── app.py # CLI commands and user interface
├── proxy.py # Automated mitmproxy traffic capture
├── firebase.py # Firebase auth and data retrieval
├── scanner.py # BLE device discovery
├── command.py # BLE command construction and transmission
└── storage.py # Local credential and config persistence
See SECURITY.md for detailed vulnerability findings and responsible disclosure guidance.
This tool is intended for authorized security research and educational purposes only. Only use it on equipment you own or have explicit written permission to test. The authors are not responsible for misuse.
MIT