💚 Image full credits go to Dirk Hoenes: https://pixabay.com/users/ptdh-275507
.
Tip
Even though this box is primarily intended for offensive operation, many tools and scripts can also be used for defensive purposes, for example, in CI/CD pipelines as security validation.
Important
The image do not use the root
system user anymore and instead use a basic system user named righettod
.
📒 Quick access:
🎯 The goal of this image is to provide an, always up to date "box", containing materials (tools + scripts) useful in the context of the assessment of a web-based application: site, API, etc.
📢 The image is based on the alpine base image. Previously, it was based on the kali-rolling image but the final size of the image, once the toolbox was built, was really too heavy (more than 14GB).
📱 Recently, I started to add content for mobile assessment to gather information/tools in a single box.
🏷️ Issues with the label idea
, contains general ideas on a project/code/script/payload/research/etc not necessarily directly linked to the toolbox itself. Indeed, as this project is my central toolbox's forge, I used it also to gather/centralize my ideas.
sequenceDiagram
participant T as Toolbox
participant S as SecLists
participant N as Nuclei templates
participant P as Param-Miner
alt Is a missing discovery dictionary entry
T->>S: Propose a PR with the missing element
S->>T: Get updates from the GitHub repository once the PR is merged
end
alt Is a missing detection generic point
T->>N: Propose a PR with the missing template
N->>T: Get updates from the GitHub repository once the PR is merged
end
alt Is a missing hidden http parameter/header entry
T->>P: Propose a PR with the missing element
P->>T: Get updates from the GitHub repository once the PR is merged
end
alt Is a missing useful existing tool
T->>T: Add the tool in a way to always use the latest version
end
alt Is a missing specific need or without existing tool
T->>T: Add a new custom scripts
end
I have created and maintain several public toolboxes (as docker images), for which, the present toolbox toolbox-pentest-web
is the central one:
mindmap
root["💻toolbox-pentest-web"]
id1("🔬toolbox-codescan")
id2("📋toolbox-jwt")
id3("🔎toolbox-regex")
id4("🔎toolbox-jsoncrack")
id5("🏹toolbox-patator")
- toolbox-pentest-web: Toolbox for pentest of web-based application.
- toolbox-codescan: Toolbox to perform offline scanning of a code base.
- toolbox-jwt: Toolbox with different scripts having for the objective to perform different kinds of attacks against JWT tokens.
- toolbox-jsoncrack: Toolbox to have a local instance of JsonCrack to inspect JSON/CSV/XML/YAML sensitive/private content.
- toolbox-regex: Toolbox to have a local instance of RegExr to create regex against sensitive/private content.
- toolbox-patator: Toolbox to have an always up-to-date docker image of the tools named patator.
The folder build contains utility internal scripts and materials used to build the docker image.
All tools are installed in the folder /tools and a transfer zone between the container and the host has been defined via the folder /tools/reports.
Tip
The index of all the scripts available is automatically updated, at each push on the master branch, via this workflow.
The folder scripts contains helper scripts for some operations using embedded tools.
Tip
The trial of the software Foxit PDF Editor can be used to create custom malicious PDF files.
Tip
The VB code, stored in the file doc-vbs-exfiltrating-envvars.vbs, can be used to create a custom office malicious file.
The folder misc contains materials that can be used for testing specific cases like for example when an app is using:
- HTTP Signature.
- eIDAS certificate and key materials.
- RSA weak key pair:
- File upload feature accepting Microsoft Office documents, PDF documents, SVG images and so on:
- Excel 97-2003 format document with a VBA macro exfiltrating environment variables, via an HTTP POST request, to a defined domain.
- Excel OpenXML format document with a VBA macro exfiltrating environment variables, via an HTTP POST request, to a defined domain.
- Word OpenXML format document with a VBA macro exfiltrating environment variables, via an HTTP POST request, to a defined domain.
- Word 2003 XML format document with a VBA macro exfiltrating environment variables, via an HTTP POST request, to a defined domain.
- PDF document with a link to a file considered as a malware by some Antivirus or Browsers.
- PDF document with a QRCODE with a link to a file considered as a malware by some Antivirus or Browsers.
- PDF document with an embedded (attached) build of LaZagne file considered as a malware by some Antivirus or Browsers.
- PDF document with an embedded (attached) build of NetCat file considered as a malware by some Antivirus or Browsers.
- PDF document with an embedded (attached) file simulating a malicious file.
- PDF document with a malicious file, considered as a malware by some Antivirus or Browsers, concatenated at the end after the delimiter
[NEWFILE]
(see below for the extraction of the malicious file from the pdf). - PDF document with JS code showing an alert box when the document is open.
- PDF document with a XXE payload embedded in a XFA form (based on CVE-2025-54988 and POC-CVE-2025-54988).
- XPS document embedding files (LaZagne and Mimikatz) detected, as malicious programs, by antivirus (at least from VirusTotal ones).
- SVG image with an XSS payload, see files
misc/doc-test-xss-*.svg
for the different versions. - Java application, as an executable jar file compiled for Java 1.8 minimum runtime, performing an HTTP GET request to a defined domain.
- Go application, as a native executable, performing an HTTP GET request to a defined domain:
- VBS script exfiltrating environment variables, via an HTTP POST request, to a defined domain.
💻 Use the code below to extract the executable file (LaZagne.exe) from the PDF file doc-pdf-with-malicious-files-concatenated.pdf:
delimiter = "5b4e455746494c455d" # String "[NEWFILE]" encoded in HEX
with open("doc-pdf-with-malicious-files-concatenated.pdf", mode="rb") as f:
content_hex = f.read().hex()
delimiter_position = content_hex.find(delimiter)
bin_file_hex = content_hex[delimiter_position + len(delimiter):]
bin_file_bytes = bytes.fromhex(bin_file_hex)
with open("malicious-files.exe", mode="wb") as f:
f.write(bin_file_bytes[1:])
The folder templates contains several scripts/files that can be used, as a basis for custom scripts, to speed up the implementation of a POC.
The folder dictionaries contains several, home-made custom dictionaries, that can be used for discovery operations.
This file contains several technical hints for different kinds of context/issues/goals.
💻 It's my tailor-made cheat sheet.
Use the following set of commands:
$ git clone https://github.com/righettod/toolbox-pentest-web.git
$ cd toolbox-pentest-web
$ docker build . -t righettod/toolbox-pentest-web --file Dockerfile
...
# Create a volume to share files with the container (ex: reports)
$ docker volume create --name shared_space
$ docker volume inspect shared_space
# Run container
$ docker run -v shared_space:/tools/reports -p 127.0.0.1:80:80 -i -t ghcr.io/righettod/toolbox-pentest-web:master
$ docker run -v shared_space:/tools/reports -p 192.168.206.128:80:80 -p 192.168.206.128:443:443 -i -t ghcr.io/righettod/toolbox-pentest-web:master
# Build image into local cache
$ docker build -t righettod/toolbox-pentest-web .
# Remove image from local cache
$ docker rmi -f righettod/toolbox-pentest-web
rem Run container and defines a shared folder
C:\> docker run -v F:/SharedFolder:/tools/reports -p 127.0.0.1:80:80 -i -t ghcr.io/righettod/toolbox-pentest-web:master
Note
This mode of exposure was chosen as the image use a basic system user named righettod
instead of the root
user.
Tip
In case of need or issue with ttyd
, the tool shellinabox is installed.
The tool ttyd is used to expose a zsh shell via the browser on port TCP 8000
. This mode of exposure is used by the launch script container-launcher.sh when an environment variable named WEB_SHELL_ACCESS_PASSWORD
is defined. This variable refers to the password used for the BASIC authentication defined to access the container with the user named righettod
.
💡 When the environment variable is not defined then the launch script start a zsh shell directly.
$ docker run -p 8000:8000 -e "WEB_SHELL_ACCESS_PASSWORD=MyComplexPassword" ghcr.io/righettod/toolbox-pentest-web:master
ttyd 1.7.7 (libwebsockets 4.3.5)
tty configuration:
...
💡 When the remote access mode is used, it is recommended to also expose the port TCP 9000
to allow the start of a web server from the container to upload/download data to/from it in more convenient way. The python package uploadserver is installed to help for upload case. For download case, the python embedded server (python -m http.server 9000
) can be used or the installed tool simplehttpserver:
$ docker run -p 8000:8000 -p 9000:9000 -e "WEB_SHELL_ACCESS_PASSWORD=MyComplexPassword" ghcr.io/righettod/toolbox-pentest-web:master
ttyd 1.7.7 (libwebsockets 4.3.5)
tty configuration:
...
Image is published into the GitHub container registry, every week, via this workflow.
🔒 Build attestations are here.
- Refer here for information about reporting a vulnerability.
- Image is audited every week by Snyk to detect presence of any vulnerability.
Note
The mentioned tools are not added to the image because I do not perform such type of assessment. I added this section for my colleagues that sometimes uses this image in such context 😉
Tools commonly used in such type of assessment can be added by appending this content to the script add-tools.sh of your fork of this repository:
# Add NetExec, impacket and Responder tools
python -m pip install impacket aioquic
git clone --depth 1 https://github.com/lgandx/Responder.git /tools/Responder
python -m pip install git+https://github.com/Pennyw0rth/NetExec
CFLAGS="-Wno-int-conversion" python -m pip install netifaces
netexec --version
python /tools/Responder/Responder.py --version
Note
Model ChatGPT.
I deploy a container on a OpenShift instance. The container is launched with another user that the one specified by the USER directive. What is the reason ?
The Root Cause?
OpenShift (unlike plain Docker or Kubernetes) does not run containers as the user specified in your image’s USER
directive by default.
Instead, it enforces a random, non-root user ID at runtime for security reasons.
This happens because of OpenShift’s Security Context Constraints (SCCs) — especially the default one, called restricted
.
Why OpenShift Overrides the USER
Directive?
In OpenShift’s restricted SCC:
- Containers must not run as root.
- Containers must run as an arbitrary, non-root UID assigned dynamically when the pod starts.
- This UID is not necessarily the same as the one defined in your Dockerfile (
USER
directive).
This design ensures:
- Better isolation between tenants and workloads.
- No need for cluster administrators to pre-approve or hardcode UIDs.
- Filesystem access remains safe if images are built correctly (see below).
What This Means Practically?
If your Dockerfile contains:
USER 1001
and you deploy it on OpenShift, your container may run as something like UID 1023840001
instead.
This UID:
- Has no name mapping in
/etc/passwd
inside the container. - Still has the same group ID as the
root
group (GID0
) unless overridden. - Can access files owned by
0
(root group), which is why many OpenShift images usechmod g+w
on directories that need to be writable.
How to Make Your Image Compatible?
If your app needs write access to certain directories, do the following in your Dockerfile:
# Allow group write permissions
RUN mkdir -p /app && chgrp -R 0 /app && chmod -R g+rwX /app
# Switch to non-root user
USER 1001
💡 This ensures that even if OpenShift assigns an arbitrary UID, it will still belong to group 0
(root) and have the necessary permissions.
Summary
Behavior | Explanation |
---|---|
Container runs as different user than USER |
OpenShift enforces non-root random UID via SCC. |
Why | Security isolation (no privilege escalation, multi-tenant safety). |
Fix | Ensure filesystem permissions are g+rwX and owned by group 0 . |
Common SCC name | restricted |