Build a Docker Penetration Test environment

Today we build a penetration test environment via Docker. That means no Plug-Ins (for example: Java) are needed! If you are Mac OS X users, a VNC client is already included (since Yosemite).

Preparation:

# download all needed Docker images
$ docker pull owasp/zap2docker-stable
$ docker pull citizenstig/dvwa
$ docker pull jmbmxer/threadfix

# list local Docker images
$ docker images
...
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
owasp/zap2docker-stable   latest              a774bdc65502        3 months ago        1.557 GB
jmbmxer/threadfix         latest              b6f1907a61cd        5 months ago        941 MB
citizenstig/dvwa          latest              c8312743bc09        23 months ago       478.5 MB

ZAP Attack Proxy

# run Docker container with ZAP Attack Proxy (insert and remember password)
$ docker run -u zap -p 5900:5900 -p 8080:8080 -v /tmp/reports:/home/zap/reports --name zap -i owasp/zap2docker-stable x11vnc --forever --usepw --create

# start VNC (Mac OS X)
$ open /System/Library/CoreServices/Applications/Screen\ Sharing.app/

…or use the short way via: [cmd] + [space] and type screen sharing

vnc connection to zap

Insert “localhost” and your given password… and follow introduction for ZAP startup. Now you configure the ZAP Proxy Settings.

zap proxy configuration

Note: Select IP “0.0.0.0” for later use. You can also use “$ docker inspect zap” to find out the internal IP, but this could change on next start.

DVWA

# run Docker container with DVWA (2nd terminal)
$ docker run -d -p 8081:80 --name dvwa citizenstig/dvwa

# wait for startup
$ docker logs -f dvwa

# get host ip (from where you run browser)
$ ifconfig

Now start your Firefox browser and change proxy settings. Insert your IP!

firefox proxy settings

Call URL for DVWA in Firefox and run your penetration tests.

pentest firefox zap

When you are done, export XML report

zap xml report
From now on, you can stop all running docker container.

ThreadFix

# run Docker container with ThreadFix
$ docker run -d -p 8443:8443 --name threadfix jmbmxer/threadfix start

# wait for startup
$ docker logs -f threadfix

Open Safari and call URL: https://localhost:8443/threadfix. Login with User: “user” and Password: “password”. Create a new team and add a application to team.

# open directory in finder
$ open /tmp/reports/

Import the ZAP XML report.

threadfix zap report

That is it… enjoy and expand your pentest laboratory!

Create Alpine Linux VM with VirtualBox

Today a tutorial for creating a Alpine Linux VM with VirtualBox. The only limitation is that VirtualBox is already installed. Furthermore,  all of the steps are performed in the terminal (without VirtualBox-GUI).

Creation of VM

# change directory
$ cd VirtualBox\ VMs/

# download alpine iso
$ curl -o alpine-3.4.3-x86_64.iso http://dl-cdn.alpinelinux.org/alpine/v3.4/releases/x86_64/alpine-3.4.3-x86_64.iso

# checksum sha1 (optional)
$ openssl sha1 alpine-3.4.3-x86_64.iso

# create new directory
$ mkdir AlpineVM

# create storage medium for VM
$ VBoxManage createhd --filename ./AlpineVM/AlpineVM.vdi --size 8192

# list available OS types (just for fun and good to know)
$ VBoxManage list ostypes

# register new alpine VM
$ VBoxManage createvm --name "AlpineVM" --ostype Linux26_64 --register

# configure system settings of alpine VM
$ VBoxManage modifyvm "AlpineVM" --memory 1024 --cpus 1 --acpi on --pae off --hwvirtex on --nestedpaging on --rtcuseutc on --vram 16 --audio none --accelerate3d off --accelerate2dvideo off --usb on

# configure boot settings of VM
$ VBoxManage modifyvm "AlpineVM" --boot1 dvd --boot2 disk --boot3 none --boot4 none

# modify a storage controller (IDE)
$ VBoxManage storagectl "AlpineVM" --name "IDE" --add ide

# modify a storage controller (SATA)
$ VBoxManage storagectl "AlpineVM" --name "SATA" --add sata

# add storage medium to VM
$ VBoxManage storageattach "AlpineVM" --storagectl "SATA" --port 0 --device 0 --type hdd --medium ./AlpineVM/AlpineVM.vdi

# add alpine iso
$ VBoxManage storageattach "AlpineVM" --storagectl "IDE" --port 1 --device 0 --type dvddrive --medium alpine-3.4.3-x86_64.iso

# start alpine VM
$ VBoxManage startvm "AlpineVM"

Basic Alpine installation

# after login as user "root" (passwordless)

# run setup
$ setup-alpine

>>>
keyboard layout: "us"
keyboard variant: "us"
system hostname: "localhost"
initialise interface: "eth0, dhcp, no manual setup"
enter root password
timezone: "UTC"
HTTP/FTP proxy URL: "none"
Detect and add fastest mirror: "f"
SSH server: "openssh"
NTP client: "chrony"
install to disk: "sda"
install type: "sys"
erase & continue: "y"
<<<

# shutdown system
$ poweroff

Note: if you have an answers file you can do…

# download answers file
$ wget http://<uri>/<answers file>

# configuration via answers file
$ alpine-setup -f <path/to/answers file>

Remove medium (ISO)

# remove alpine iso
$ VBoxManage storageattach "AlpineVM" --storagectl "IDE" --port 1 --device 0 --type dvddrive --medium emptydrive

# start VM
$ VBoxManage startvm "AlpineVM"

Update Packages and install VirtualBox additions

# change directory
$ cd /etc

# enable repositories
$ vi apk/repositories

>>>
#/media/cdrom/apks
http://liskamm.alpinelinux.uk/v3.4/main
http://liskamm.alpinelinux.uk/v3.4/community
http://liskamm.alpinelinux.uk/edge/main
http://liskamm.alpinelinux.uk/edge/community
http://liskamm.alpinelinux.uk/edge/testing
<<<

# update and upgrade system
$ apk update && apk upgrade

# install virtualbox additions
$ apk add virtualbox-guest-modules-grsec virtualbox-additions-grsec

# reboot system
$ reboot

Optional steps

# install vim
$ apk add vim

# change directory
$ cd /etc

# modify sshd (manual) 
$ vim ssh/sshd_config

# restart sshd
$ init.d/sshd restart

# modify network interfaces (manual)
$ vim network/interfaces

# restart network
$ init.d/networking restart

Explain Shell direct from terminal

Explainshell.com rocks! Nevertheless, you lose time to leave the terminal (open browser, copy-paste). But there is a cool solution from ManKier. All what you need is curl.

Usage

# curl request for whoami
$ curl -Gs "https://www.mankier.com/api/explain/?cols="$(tput cols) --data-urlencode "q=whoami"

# curl request for df -h
$ curl -Gs "https://www.mankier.com/api/explain/?cols="$(tput cols) --data-urlencode "q=df -h"

Simpler usage

With a tiny script it will be more comfortable! Add the following to your .bashrc or .bash_profile (MAC OS X).

# explain.sh begins
explain () {
	if [ "$#" -eq 0 ]; then
		while read  -p "Command: " cmd; do
			curl -Gs "https://www.mankier.com/api/explain/?cols="$(tput cols) --data-urlencode "q=$cmd"
		done
		echo "Bye!"
	elif [ "$#" -eq 1 ]; then
		curl -Gs "https://www.mankier.com/api/explain/?cols="$(tput cols) --data-urlencode "q=$1"
	else
		echo "Usage"
		echo "explain                  interactive mode."
		echo "explain 'cmd -o | ...'   one quoted command to explain it."
	fi
}

Now you can do …

# explain one command
$ explain 'df -h'
...
df(1)
  df displays the amount of disk space available on the file system containing each file name
  argument. If no file name is given, the space available on all currently mounted file systems is
  shown. Disk space is shown in 1K blocks by default, unless the environment variable
  POSIXLY_CORRECT is set, in which case 512-byte blocks are used. If an argument is the absolute
  file name of a disk device node containing a mounted file system, df shows the space available on
  that file system rather than on the file system containing the device node. This version of df
  cannot show the space available on unmounted file systems, because on most kinds of systems doing
  so requires very nonportable intimate knowledge of file system structures.

  -h (-H, --HUMAN-READABLE)
    print sizes in powers of 1024 (e.g., 1023M)

… if you insert only “explain” an interactive mode will started!

Create own Docker port scanner

Today’s tutorial shows how quickly and easily a Docker port scanner can be created. With the knowledge you can then create additional Docker applications.

Preparation

# prepare knocker project (local)
$ mkdir ~/Projects/Knocker && cd ~/Projects/Knocker

# create Dockerfile (local)
$ vim Dockerfile

# create KnockerVM (local)
$ docker-machine create -d virtualbox KnockerVM

# pointing shell to KnockerVM (local)
$ eval $(docker-machine env KnockerVM)

# copy Dockerfile into KnockerVM (local)
$ docker-machine scp ~/Projects/Knocker/Dockerfile KnockerVM:Dockerfile

# SSH into KnockerVM (local)
$ docker-machine ssh KnockerVM

Dockerfile

FROM alpine

# install needed packages
RUN apk --update add wget build-base gcc abuild binutils binutils-doc gcc-doc

# download and unzip
RUN wget http://prdownloads.sourceforge.net/knocker/knocker-0.7.1.tar.gz
RUN tar -zxvf knocker-0.7.1.tar.gz && rm -f knocker-0.7.1.tar.gz

# configure, install and clean up
WORKDIR /knocker-0.7.1
RUN ./configure \
    && make install \
    && make clean

# create mountable directory
RUN mkdir /results
VOLUME /results
WORKDIR /results

# remove packages
RUN apk del wget build-base gcc abuild binutils binutils-doc gcc-doc \
    && rm -fr /knocker-0.7.1

ENTRYPOINT ["knocker"]

Usage

# build Docker image (KnockerVM)
$ docker build -t alpine/knocker .

# run Knocker help (KnockerVM)
$ docker run -ti --rm alpine/knocker --help

# run simple port scan (KnockerVM)
$ docker run -ti --rm alpine/knocker -H 192.168.192.1 -SP 1 -EP 10

# run port scan with (KnockerVM)
$ docker run -ti --rm -v /home/docker:/results alpine/knocker -H 192.168.192.1 -SP 80 -EP 90 -lf /results/report

# read report (KnockerVM)
$ cat report

Feel free to edit and/or expand! Knocker self can be found here.

Command-line fake data generator

In my search for a command-line fake data generator I’ve found phony. What can I say, the tool does exactly what it should! After installation, you no longer need to leave the terminal.

Installation

# install go and git (Debian 8)
$ apt-get install -y golang git

# set GOPATH environment variable for workspace
$ mkdir ~/.go
$ echo "GOPATH=$HOME/.go" >> ~/.bashrc
$ echo "export GOPATH" >> ~/.bashrc
$ echo "PATH=\$PATH:\$GOPATH/bin" >> ~/.bashrc
$ source ~/.bashrc

# install phony
$ go get github.com/yields/phony

# verfiy installation
$ phony --version

Usage

# show help
$ phony --help

# list phony generators
$ phony --list

# generate 10 e-mails
$ echo '{{email}}' | phony --max 10

# generate 5 users (first name, last name)
$ echo 'User: {{name.first}} {{name.last}}' | phony --max 5

There is more! Look at the examples!

Record and share terminal sessions

Sometimes it is so boring to tell other software testers what to do … and nobody read documentations. Here now a easy solution! Just record and share your terminal sessions.

Installation

# install Python3 with pip (on Debian 8)
$ apt-get install -y python3 python3-pip

# verify installation
$ python3 --version && pip3 --version

# install asciinema
$ apt-get install -y asciinema

# verify installation
$ asciinema --version

Note: read the documentation of asciinema for other OS!

Usage

# start recording
$ asciinema rec

# do some great stuff on new shell instance
...

# stop recording (Ctrl-D)
$ exit

# open/send URL

Tip: Sensitive data should be shared directly (via JSON file)!

# record to local file
$ asciinema rec record.json

# distribute in any way
...

# play local record
$ asciinema play record.json

Automate Bash testing with Bats

With Bats (Bash Automated Testing System) it is easy to automate Bash and command line testing. It is an awesome open source framework written in Bash by Sam Stephenson. In combination with Jenkins you are able to use it via build.

Installation

# clone from github
$ git clone https://github.com/sstephenson/bats.git

# change directory
$ cd bats

# start installation
$ sudo ./install.sh /usr/local

Usage

# create new project
$ mkdir ~/Project/Bats && cd ~/Projects/Bats

# create Bats file
$ vim test.bats

# execute test
$ bats test.bats
...
✓ Simple check for date command
✓ Check for current user
- Test for something that does not exist (skipped: This test is skipped)
✓ Test for something that should not exist
✓ Check for individual line of output

5 tests, 0 failures, 1 skipped

# execute test with TAP output
$ bats --tap test.bats
...
1..5
ok 1 Simple check for date command
ok 2 Check for current user
ok 3 # skip (This test is skipped) Test for something that does not exist
ok 4 Test for something that should not exist
ok 5 Check for individual line of output

Example Bats file

#!/usr/bin/env bats

@test "Simple check for date command" {
  date
}

@test "Check for current user" {
  result="$(whoami)"
  [ "$result" == "lupin" ]
}

@test "Test for something that does not exist" {
  skip "This test is skipped"
  ls /test/no/test
}

@test "Test for something that should not exist" {
  run ls /test/no
  [ "$status" -eq 1 ]
}

@test "Check for individual line of output" {
  run ping -c 1 google.com
  [ "$status" -eq 0 ]
  [ "${lines[3]}" = "1 packets transmitted, 1 packets received, 0.0% packet loss" ]
}

Note: There is much more! Read documentation and have a look on projects which are using it!

Docker Audit

This tutorial shows software testers some simple examples for Docker audit. Here now we will make some audits on Docker environment and Dockerfiles.

Docker environment audit

# check Docker environment with docker-bench-security
$ docker run -it --net host --pid host --cap-add audit_control \
    -v /var/lib:/var/lib \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /usr/lib/systemd:/usr/lib/systemd \
    -v /etc :/etc --label docker_bench_security \
    docker/docker-bench-security

Note: 1st the space after /etc is only because of security settings from my provider! 2nd create os specific docker-bench-security (example CentOS)

Dockerfile audit

# install on RedHat, CentOS, Fedora ...
$ yum install epel-release && yum install lynis

# install on Debian, Ubuntu ...
$ apt-get install lynis

# Suse
$ zypper install lynis

# install via Homebrew
$ brew install lynis

# audit Dockerfile
$ lynis audit dockerfile Dockerfile

# check log file
$ cat /var/log/lynis.log
$ cat /var/log/lynis-report.dat

Lint Dockerfile with Haskell Dockerfile Linter

# simply run Container again Dockerfile
$ docker run --rm -i lukasmartinelli/hadolint < Dockerfile