Often, I find myself using the same tools on bare Windows, on WSL, on Kali VM, and on various remote shells. The installed version or configuration details vary, and I have to debug why things broke instead of simply running the intended tool. Maybe one dependency is missing? Maybe I forgot to use a proper API token? Maybe a tool is in the wrong version? There’s just too much to investigate.

I’ve recently fallen in love with Docker. It’s so easy to run a container - do whatever is needed - then get rid of it. I don’t have to worry about any dependencies, extra bloat required by the package, and so on. That’s my new go-to way of managing tools I want to customize and reuse. This might be slightly inconsistent with Docker’s philosophy, but it simply does work.

Docker-compose started in terminal

There are plenty of interesting things one can do with Docker. The pentester’s perspective has been well summarized in Docker for Pentesters blogpost. I want to rather focus on my reasoning and methods I found useful. For instance, I like the ability of grouping tools into specific domains and then building a single container. My long-term goal is to have a couple of images, categorized and configured according to my preferences. Lots of things don’t fit into containers, but some fit very nicely.

OSINT container

Today, I want to explain how I began working on a container with OSINT tools I use. There is no strong policy on what is OSINT, what not, but active tools like ffuf are not included. When I’m writing these words, it’s still WIP, though I’m not even sure if it will ever stop being WIP, so…

What tools were selected so far? The ones I used last time I had to perform such testing :)

Besides just packaging the tools into an image, I’ve also tried to create some friendly aliases/functions to automate common actions. Remembering switches to all of those tools is a bit challenging, hence it’s always nice to have a more friendly alias. It’s common to mix DNS generation and probing into single a call so there’s a function for that:

1
2
3
function dns_discover_names() {
    dnsgen <(echo $*) | /opt/massdns -r /opt/massdns-lists/resolvers.txt -o S -w >(cat)
}

This one is really nice for another reason. Both tools (dnsgen + massdns) use files - either as input or output. This doesn’t feel right, I want them to just accept arg, then print the result on stdout! Both sources should be accessible without any extra volumes. Fortunately, bash process substitution works like a charm here. Whenever I want to save to a file, I will just redirect again (a slight performance hit doesn’t matter). Also, I’m aware this is sorta unsafe, but it’s our little, trusted container.

I also want the container to start a shell by default. Aliases cover common use cases, but I also need flexibility, so being able to jump in, pipe the commands, mix switches, etc. is a must-have.

They can still be run to do one job and exit. The syntax is slightly different as we need to force bash to load profile file.

Docker-compose running single command

Build

Clone repository from https://github.com/adenkiewicz/docker-osint.

Use docker-compose build osint to build and run the image locally. You can tweak all the settings in Dockerfile beforehand.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# build tools in temp container
FROM golang:1.17-alpine AS build-env
RUN apk -U upgrade --no-cache \
    && apk add --no-cache bash make git build-base
RUN go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
RUN go install github.com/tomnomnom/anew@latest
RUN go install github.com/tomnomnom/httprobe@latest
RUN go install -v github.com/OWASP/Amass/v3/...@master

# build wraith (https://github.com/N0MoreSecr3ts/wraith)
RUN cd /tmp/ \
    && git clone https://github.com/N0MoreSecr3ts/wraith.git \
    && cd wraith \
    && make build \
    && git clone https://github.com/N0MoreSecr3ts/wraith-signatures.git \
    && mv ./bin/wraith-linux /opt/wraith

# build massdns
RUN cd /tmp \
    && git clone https://github.com/blechschmidt/massdns.git \
    && cd massdns \
    && make \
    && mv ./bin/massdns /opt \
    && mv lists /opt/massdns-lists \
    && mv scripts /opt/massdns-scripts

# copy everything to /opt
RUN cp -R /go/bin/* /opt

# Create OSINT container
FROM alpine:3.15.0
RUN apk -U upgrade --no-cache \
    && apk add --no-cache bind-tools ca-certificates bash python3 py3-pip \
    && rm -rf /var/lib/apt/lists/
COPY --from=build-env /opt /opt

# add wraith signatures
RUN mkdir -p /root/.wraith/signatures
COPY --from=build-env /tmp/wraith/wraith-signatures/signatures /root/.wraith/signatures

# add dnsgen
RUN pip3 install dnsgen

# save and autoload aliases
COPY profile /root/.bashrc

WORKDIR /shared
ENTRYPOINT ["/bin/bash"]

This is a multi-stage build, meaning the first container is a (golang) build environment - stuff is built there, then necessary files are copied into a final image. Almost all tools are Go binaries, so no dependencies are needed and they can be directly copied. dnsgen is installed from pip. The final image is based on Alpine Linux. bash, and py3 are two extra packages added to it. Whatever else is needed should be added to Dockerfile or downloaded on the fly.

Run

To (re)start the container, use docker-compose run --rm osint. Almost all tools are present in /opt directory which is also added to the $PATH. If you need to exchange data between host and docker, then /shared directory should be used. Basically, this is rw volume to exchange any kind of information.

Another important volume is /private (ro). This is where private files are stored (configs, secrets, and customization). This is something I will not share on Github, but you should populate locally with proper configs. E.g. subfinder expects its config in /private/subfinder/config.yaml.

Summary

This was a brief overview of my workflow. Obviously, it’s nothing outstanding, but a step forward. In the future, I plan to prepare quick setups of pentested environments to hunt for bugs efficiently. I also want to play a bit more with Windows Server images.