Contact CTF writeups Notes

Running EyeWitness on Mac via Docker

Eyewitness

Chris Truncer's EyeWitness is a great tool that allows easy visual reconnaissance of HTTP, VNC and RDP servers. It's an essential recommended by sources such as Jason Haddix's "bug hunter methodology" or Peter Kim's "the hacker playbook".

Problem

Unfortunately, it is pretty troublesome to setup on MacOS. Fortunately, the repo does provide a Dockerfile. But when following the docker instructions given in the README on a Mac, capture modes that require a display (vnc, rdp and web) fail with the following error :

cannot connect to X server

Solution

First, MacOS doesn't ship with an X server. One must be installed before running anything. So install XQuartz

Second, XQuartz uses a named socket as $DISPLAY and mounting those in Docker is troublesome (I'm actually not sure if it's supported at the moment). It is way easier to have the display server listen on the network and use that channel instead.

In order to do that, open the XQuartz preferences, navigate to Security and tick the Allow connections from network clients checkbox. Then run the following command to disable X ACLs:

xhost +

(there is probably a safer way to do this, but that's how I got it to work)

Third, the example command provided in the EyeWitness README is the following :

docker run \
    --rm \
    -it \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v ~/EyeWitness:/tmp/EyeWitness \
    eyewitness \
    -f /tmp/EyeWitness/urls.txt
    --vnc

It has to be changed to :

docker run \
    --rm \
    -it \
    -e DISPLAY=$IPADDRESS:0 \
    -v ~/EyeWitness:/tmp/EyeWitness \
    -f /tmp/EyeWitness/urls.txt
    --vnc

where $IPADDRESS is your host's local IP address. localhost or 127.0.0.1 won't work here, even when using the --net=host Docker option.

Bonus : use a bind mount instead of a volume mount

The -v option mounts a host directory as a volume. This has some (arguably negligible) overhead as it uses the union filesystem, tends to clog up the filesystem by leaving dangling volumes and can create some sync issues where the state of the directory differs on the host and on the container.

In EyeWitness' case (the mounted directory is only used to write the tool's output) it's better to use a bind mount. The syntax for that is :

docker run --mount type=bind,source=$HOST_DIRECTORY_PATH,target=$CONTAINER_DIRECTORY_PATH

where $HOST_DIRECTORY_PATH is the absolute path to the host directory and $CONTAINER_DIRECTORY_PATH the absolute path to the mount point on the container.

Using a bind mount, the example command becomes :

docker run \
    --rm \
    -it \
    -e DISPLAY=$IPADDRESS:0 \
    --mount type=bind,source=$HOST_DIRECTORY_PATH,target=/tmp/EyeWitness \
    -f /tmp/EyeWitness/urls.txt
    --vnc

$HOST_DIRECTORY_PATH would be /Users/$USER/EyeWitness on MacOS or /home/$USER/EyeWitness on Linux.