Skip to content

Captive Portal Attack

strasharo edited this page Mar 4, 2026 · 6 revisions

The Captive Portal attack attempts to retrieve the target access point's WPA/WPA2 key by means of a rogue network with a border authentication captive portal. It is recommended this attack is done in close, to semi-close, proximity to the target access point. This is due to the fact the attack host (your machine) will be serving the captive portal, meaning, clients will need to have a decent Wi-Fi connection to your machine.

Prerequisites

Before running the attack, you need:

  • Two wireless interfaces — one for jamming (monitor mode + injection), one for hosting the rogue AP (AP/master mode). If you assign both roles to the same interface, fluxion will create a virtual interface automatically.
  • A handshake .cap file for the target network — captured via the Handshake Snooper attack. The file is stored at attacks/Handshake Snooper/handshakes/<SSID>-<BSSID>.cap and auto-detected if present.
  • Root privileges.

Required tools

fluxion checks for these at startup:

Tool Purpose
hostapd Recommended AP service
dhcpd DHCP server (assigns IPs to clients)
lighttpd + php-cgi Web server & PHP for the portal
dnsspoof DNS spoofing (redirects all domains to the portal)
mdk4 or aireplay-ng Deauthentication on 2.4 GHz
python3 + scapy + pyric Deauthentication on 5 GHz (deauth-ng.py)
openssl SSL/TLS certificate generation
cowpatty / pyrit / aircrack-ng Password verification (at least one required)

Running the Attack

From the fluxion directory, execute fluxion:

./fluxion.sh

Or with optional flags:

# Kill any processes using selected wireless interfaces before starting
./fluxion.sh -k

# For a full list of flags, see the Flags & Preferences page

Select Captive Portal from the attack menu and follow the steps below.


Step-by-Step Setup

1. Select target network

  • Select a wireless interface supporting monitor mode to scan for targets.
  • Optionally, select an independent interface for target tracking (channel hopping). This must be a separate interface since channel hopping conflicts with a fixed-channel AP.

2. Select jammer interface

  • This interface must support packet injection.
  • fluxion uses mdk4 (default, 2.4 GHz), aireplay-ng, or deauth-ng.py (5 GHz via scapy) to deauthenticate clients from the real AP.

3. Select AP service

  • hostapd (recommended) — uses the driver's native AP mode. Required for DFS channels (52–64, 100–144).
  • airbase-ng — uses monitor mode + packet injection to emulate an AP; less reliable and generally not recommended.
  • If using an ethernet interface for the AP, you must configure and manage the wireless AP hardware manually using the settings displayed at attack launch.

4. Select handshake file & verifier

  • If a matching handshake was previously captured with Handshake Snooper, fluxion will detect it automatically.
  • Choose a verification method:
    • cowpatty — recommended; fastest and most reliable for single-password checks.
    • pyrit — GPU-accelerated alternative.
    • aircrack-ng — fallback; less reliable.

5. Configure SSL/TLS

  • Disabled — HTTP only (port 80). Fastest option; note that some browsers warn users about submitting passwords over an unencrypted connection.
  • Auto-generate — fluxion creates a self-signed RSA-2048 certificate valid for 365 days (CN: captive.gateway.lan). Browsers will show an untrusted-certificate warning.
  • User-supplied — place your PEM-format certificate (cert + key combined) at attacks/Captive Portal/certificate/server.pem; fluxion will detect and use it automatically.

When SSL is enabled, lighttpd serves the portal on both port 80 and port 443. All traffic is redirected to the portal via iptables DNAT rules.

6. Select connectivity mode

Controls how connected clients perceive internet availability:

  • Disconnected (recommended) — all DNS queries resolve to 192.169.254.1 (the rogue gateway) and all HTTP/HTTPS traffic is redirected to the portal. Clients see "No Internet" but the portal is still accessible. Most reliable option.
  • Emulated — the web server mimics Apple's and Google's connectivity-check endpoints so iOS and Android clients believe internet is available. This suppresses the automatic "sign in to network" prompt on some devices — clients will see the portal only when they try to browse. Warning: if SSL is disabled while emulation is on, clients may hang waiting for HTTPS responses.

7. Select captive portal UI

  • Generic portal — a clean, minimal interface with multilingual support (25 languages). Assets are bundled with fluxion.
  • Brand-specific portals — 50+ pre-built portals mimicking router manufacturers (Belkin, NETGEAR, TP-LINK, etc.), downloadable separately from the sites repository.

Select an interface appropriate to the target network's router brand.


How the Attack Works

Once launched, fluxion:

  1. Assigns gateway IP 192.169.254.1/24 to the AP interface.
  2. Starts hostapd to broadcast a rogue AP matching the target SSID on the same channel.
  3. Starts dhcpd to assign IPs in the range 192.169.254.100–254.
  4. Starts dnsspoof to redirect all DNS queries to 192.169.254.1.
  5. Configures iptables to DNAT ports 80 and 443 to the local web server.
  6. Starts lighttpd + php-cgi to serve the portal.
  7. Starts the deauth service to continuously kick clients off the real AP.

Clients deauthenticated from the real AP see the rogue network (same SSID), connect, and are served the captive portal asking for the Wi-Fi password.

Credential verification

  1. Client submits password via the portal form (POST to check.php).
  2. authenticator.php writes the candidate password to a temp file and signals the authenticator.
  3. The authenticator runs the chosen verification tool against the captured handshake.
  4. On success: check.php redirects to final.html; fluxion stops the attack and logs the result. The deauth jammer stops and clients reconnect to the real AP.
  5. On failure: check.php redirects to error.html with an option to try again.

All password attempts are logged to $CaptivePortalPassLog/<SSID>-<BSSID>.log. On success, the full result (SSID, BSSID, channel, password, client MAC/IP, time) is written to $CaptivePortalNetLog/<SSID>-<BSSID>.log.


Contributing a Translated Generic Portal

The generic portal generates its HTML from a .lang file. Adding a new language takes only two files — no HTML knowledge required.

1. Create the language file

Language files live at:

attacks/Captive Portal/generic/languages/

Copy English.lang as a starting point:

cp "attacks/Captive Portal/generic/languages/English.lang" \
   "attacks/Captive Portal/generic/languages/YourLanguage.lang"

The file must define exactly these 10 keys:

DIALOG_WEB_INFO="Authentication required for Internet access."
DIALOG_WEB_INPUT="WPA Key:"
DIALOG_WEB_SUBMIT="Connect"
DIALOG_WEB_ERROR="Error: The password entered is incorrect!"
DIALOG_WEB_OK="Please wait while the password is verified."
DIALOG_WEB_BACK="Back"
DIALOG_WEB_ERROR_MSG="This field is required."
DIALOG_WEB_LENGTH_MIN="The password must be more than {0} characters!"
DIALOG_WEB_LENGTH_MAX="The password must be less than {0} characters!"
DIALOG_WEB_DIR="ltr"

Translate all quoted strings into your language. For right-to-left languages (Arabic, Hebrew, etc.), set:

DIALOG_WEB_DIR="rtl"

This sets the dir="rtl" attribute on all relevant HTML elements automatically.

Important: Keep all 10 keys present. Missing keys will cause the portal HTML to generate incorrectly.

2. Test locally

Run fluxion against a test AP, choose Captive Portal, and select Generic Portal — YourLanguage from the UI list. Verify:

  • All strings display correctly in the browser.
  • The form submits and verification works end-to-end.
  • RTL text (if applicable) renders and aligns correctly.

3. Submit a pull request

Contributions are welcome at the fluxion repository. Open a PR adding your .lang file to attacks/Captive Portal/generic/languages/. No other files need to change for a generic portal translation.

For custom brand portals, see the Preparing Portals for Fluxion wiki page.

Clone this wiki locally