Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,13 @@ board-up: ## Start Homer dashboard
board-down: ## Stop Homer dashboard
@docker compose -f $(DOTSEC_HOME)/homer/docker-compose.yml --project-name dotsec-homer down

exegol-setup: ## Deploy my-resources to ~/.exegol/my-resources/
@echo "[*] Deploying Exegol my-resources..."
@mkdir -p $(HOME)/.exegol/my-resources/dotenv-sec
@cp $(DOTSEC_HOME)/exegol/my-resources/setup.sh $(HOME)/.exegol/my-resources/dotenv-sec/setup.sh
@chmod +x $(HOME)/.exegol/my-resources/dotenv-sec/setup.sh
@echo " → $(HOME)/.exegol/my-resources/dotenv-sec/setup.sh"
@echo "[+] Exegol my-resources deployed"
exegol-setup: ## Deploy recon bundle to ~/.exegol/my-resources/ (merge)
@echo "[*] Deploying Exegol my-resources bundle..."
@DOTSEC_HOME="$(DOTSEC_HOME)" bash $(DOTSEC_HOME)/exegol/my-resources/deploy.sh

exegol-install-tools: ## Run setup.sh inside EXEGOL_CONTAINER (uv + pnpm)
@echo "[*] Installing tools in Exegol container..."
@docker exec -it $(EXEGOL_CONTAINER) bash /opt/resources/dotenv-sec/setup.sh
@docker exec -it $(EXEGOL_CONTAINER) bash /opt/my-resources/setup/load_user_setup.sh
@echo "[+] Tools installed"

scan: ## Scan images with Trivy (requires: trivy)
Expand Down
29 changes: 20 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,30 @@ dotsec exegol setup # install uv + pnpm inside Exegol

### Exegol tool provisioning

The project ships a `my-resources` bundle deployed to `~/.exegol/my-resources/dotenv-sec/`
(via `make install` or `make exegol-setup`).
The project ships a `my-resources` bundle deployed (merged) to `~/.exegol/my-resources/`
via `make exegol-setup` (also run by `make install`).

The bundle includes:
- **bin/** scripts: `recon-subs`, `recon-alive`, `recon-crawl`, `recon-loot`, `recon-sourcemaps`, `recon-full`, `dl`
- Shell aliases and preloaded history

```bash
# Inside the Exegol container, run:
dotsec exegol setup
# or manually:
docker exec -it exegol bash /opt/resources/dotenv-sec/setup.sh
make exegol-setup # deploy/merge bundle to ~/.exegol/my-resources/
```

Scripts run **inside** the Exegol container, driven by engagement env vars (`$DOMAIN`, `$WORKSPACE`).
Example in a loaded engagement window:

```bash
recon-full
```

This installs:
- **uv** - fast Python package manager (https://docs.astral.sh/uv/)
- **pnpm** - fast, disk-efficient Node.js package manager (https://pnpm.io/)
On first container start, Exegol auto-runs `/opt/my-resources/setup/load_user_setup.sh`.
To trigger it manually:

```bash
dotsec exegol setup
```

## Docker Security

Expand Down
Empty file added exegol/my-resources/bin/.keep
Empty file.
24 changes: 24 additions & 0 deletions exegol/my-resources/bin/dl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Source an engagement's env into the CURRENT shell (must be `source`d, not run).
# Usage: source dl <target> (or via the `dl` alias)
_dl_target="${1:-}"
if [[ -z "$_dl_target" ]]; then
printf '[!] usage: source dl <target>\n' >&2
# shellcheck disable=SC2317
return 1 2>/dev/null || exit 1
fi
_dl_env="${WORKSPACE_ROOT:-/workspace}/${_dl_target}/.env"
if [[ ! -f "$_dl_env" ]]; then
printf '[!] no .env for %s at %s\n' "$_dl_target" "$_dl_env" >&2
# shellcheck disable=SC2317
return 1 2>/dev/null || exit 1
fi
if grep -qE '^[[:space:]]*(export[[:space:]]+)?[a-zA-Z_][a-zA-Z0-9_]*=.*(\$\(|`)' "$_dl_env"; then
printf '[!] %s contains command substitution — refusing\n' "$_dl_env" >&2
# shellcheck disable=SC2317
return 1 2>/dev/null || exit 1
fi
# shellcheck source=/dev/null
source "$_dl_env"
[[ -f "${_dl_env}.secrets" ]] && source "${_dl_env}.secrets"
printf ' loaded %s (%s)\n' "${TARGET:-$_dl_target}" "${DOMAIN:-?}"
11 changes: 11 additions & 0 deletions exegol/my-resources/bin/recon-alive
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl <target>}"
OUT="${WORKSPACE:-$PWD}/recon"
mkdir -p "$OUT"

[[ -s "$OUT/subdomains.txt" ]] || { echo "[!] run recon-subs first"; exit 1; }
echo "[*] httpx alive check"
httpx-toolkit -l "$OUT/subdomains.txt" -mc 200 -ports 443,80,8080,8000,8888 -threads 200 2>/dev/null \
| sort -u > "$OUT/subdomains_alive.txt"
echo "[+] $(wc -l < "$OUT/subdomains_alive.txt") alive → $OUT/subdomains_alive.txt"
13 changes: 13 additions & 0 deletions exegol/my-resources/bin/recon-crawl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl <target>}"
OUT="${WORKSPACE:-$PWD}/recon"
mkdir -p "$OUT"

[[ -s "$OUT/subdomains_alive.txt" ]] || { echo "[!] run recon-alive first"; exit 1; }
echo "[*] katana crawl"
katana -list "$OUT/subdomains_alive.txt" -d 5 -jc -kf -ps -pss waybackarchive,commoncrawl,alienvault \
-ef woff,css,png,svg,jpg,woff2,jpeg,gif -o "$OUT/allurls.txt" 2>/dev/null || true
grep -iE '\.js($|\?)' "$OUT/allurls.txt" 2>/dev/null | sort -u > "$OUT/js.txt" || true
gau "$DOMAIN" 2>/dev/null | sort -u > "$OUT/params.txt" || true
echo "[+] $(wc -l < "$OUT/allurls.txt" 2>/dev/null || echo 0) urls, $(wc -l < "$OUT/js.txt" 2>/dev/null || echo 0) js"
13 changes: 13 additions & 0 deletions exegol/my-resources/bin/recon-full
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl <target>}"
OUT="${WORKSPACE:-$PWD}/recon"
mkdir -p "$OUT"

echo "[*] full recon pipeline for $DOMAIN"
recon-subs
recon-alive
recon-crawl
recon-loot || echo "[i] loot step skipped"
recon-sourcemaps || echo "[i] sourcemaps step skipped"
echo "[+] done → $OUT"
27 changes: 27 additions & 0 deletions exegol/my-resources/bin/recon-loot
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl <target>}"
OUT="${WORKSPACE:-$PWD}/recon"
mkdir -p "$OUT"

# Pull juicy files (configs/archives/backups/data) from the crawled link list.
[[ -s "$OUT/allurls.txt" ]] || { echo "[!] run recon-crawl first (need allurls.txt)"; exit 1; }
LOOT="$OUT/loot"; mkdir -p "$LOOT"

# juicy extensions: configs, archives, backups, data
exts='json|jsonc|js|map|xml|yml|yaml|sql|conf|config|cfg|env|ini|properties|bak|backup|old|swp|zip|tar|tar\.gz|tgz|gz|rar|7z|log|csv'
echo "[*] filtering juicy files from allurls.txt"
grep -iE "\.(${exts})($|\?)" "$OUT/allurls.txt" 2>/dev/null | sort -u > "$LOOT/juicy_urls.txt" || true
echo "[+] $(wc -l < "$LOOT/juicy_urls.txt" 2>/dev/null || echo 0) juicy urls → $LOOT/juicy_urls.txt"

echo "[*] downloading"
got=0
while read -r u; do
[[ -n "$u" ]] || continue
fname="$(printf '%s' "$u" | sed -E 's|https?://||; s|[/?&=:]|_|g')"
# shellcheck disable=SC2086
if curl -fsSL --max-time 20 ${HTTP_PROXY:+--proxy "$HTTP_PROXY"} ${UA:+-A "$UA"} "$u" -o "$LOOT/$fname" 2>/dev/null; then
got=$((got+1))
fi
done < "$LOOT/juicy_urls.txt"
echo "[+] $got files downloaded → $LOOT"
28 changes: 28 additions & 0 deletions exegol/my-resources/bin/recon-sourcemaps
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail
: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl <target>}"
OUT="${WORKSPACE:-$PWD}/recon"
mkdir -p "$OUT"

[[ -s "$OUT/js.txt" ]] || { echo "[!] run recon-crawl first"; exit 1; }
SRC="$OUT/src"; mkdir -p "$SRC"
have_tool=""
command -v unwebpack-sourcemap >/dev/null && have_tool="unwebpack-sourcemap"
[[ -z "$have_tool" ]] && command -v sourcemapper >/dev/null && have_tool="sourcemapper"
[[ -z "$have_tool" ]] && { echo "[!] no sourcemap tool (unwebpack-sourcemap/sourcemapper) — see load_user_setup"; exit 1; }
found=0
while read -r js; do
[[ -n "$js" ]] || continue
map="${js}.map"
# shellcheck disable=SC2086
if curl -fsS --max-time 15 ${HTTP_PROXY:+--proxy "$HTTP_PROXY"} "$map" -o /tmp/_dotsec_map 2>/dev/null \
&& head -c 32 /tmp/_dotsec_map | grep -q '"version"'; then
host="$(printf '%s' "$js" | awk -F/ '{print $3}')"
echo "[+] sourcemap: $map"
"$have_tool" -url "$map" -output "$SRC/$host" 2>/dev/null \
|| unwebpack-sourcemap "$map" "$SRC/$host" 2>/dev/null || true
found=$((found+1))
fi
done < "$OUT/js.txt"
rm -f /tmp/_dotsec_map
echo "[+] $found source maps reconstructed → $SRC"
9 changes: 9 additions & 0 deletions exegol/my-resources/bin/recon-subs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl <target>}"
OUT="${WORKSPACE:-$PWD}/recon"
mkdir -p "$OUT"

echo "[*] subfinder $DOMAIN"
subfinder -d "$DOMAIN" -all -recursive 2>/dev/null | sort -u > "$OUT/subdomains.txt"
echo "[+] $(wc -l < "$OUT/subdomains.txt") subdomains → $OUT/subdomains.txt"
35 changes: 35 additions & 0 deletions exegol/my-resources/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Deploy the dotsec recon bundle into the Exegol my-resources volume, merging
# delimited blocks idempotently (never clobbering the user's own customizations).
set -euo pipefail

DOTSEC_HOME="${DOTSEC_HOME:-$(cd "$(dirname "$(readlink -f "$0")")/../.." && pwd)}"
SRC="${DOTSEC_HOME}/exegol/my-resources"
DEST="${MYRES_DIR:-${HOME}/.exegol/my-resources}"
BEGIN="# >>> dotsec >>>"
END="# <<< dotsec <<<"

# merge_block <dest_file> <fragment_file>: replace existing dotsec block or append.
merge_block() {
local target="$1" fragment="$2"
[[ -f "$fragment" ]] || return 0
mkdir -p "$(dirname "$target")"
touch "$target"
if grep -qF "$BEGIN" "$target"; then
sed -i "\|${BEGIN}|,\|${END}|d" "$target"
fi
{ printf '%s\n' "$BEGIN"; cat "$fragment"; printf '%s\n' "$END"; } >> "$target"
}

mkdir -p "${DEST}/bin"
if compgen -G "${SRC}/bin/recon-*" >/dev/null; then
cp "${SRC}/bin/"recon-* "${DEST}/bin/"
fi
[[ -f "${SRC}/bin/dl" ]] && cp "${SRC}/bin/dl" "${DEST}/bin/"
chmod +x "${DEST}/bin/"* 2>/dev/null || true

merge_block "${DEST}/setup/zsh/aliases" "${SRC}/fragments/aliases.dotsec"
merge_block "${DEST}/setup/zsh/history" "${SRC}/fragments/history.dotsec"
merge_block "${DEST}/setup/load_user_setup.sh" "${SRC}/fragments/load_user_setup.dotsec.sh"

printf '[+] dotsec recon toolkit deployed to %s\n' "${DEST}"
5 changes: 5 additions & 0 deletions exegol/my-resources/fragments/aliases.dotsec
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# dotsec recon aliases (env-driven: needs $DOMAIN / an engagement loaded)
alias dl='source /opt/my-resources/bin/dl'
alias subs='subfinder -d "$DOMAIN" -all -recursive'
alias alive='httpx-toolkit -mc 200 -ports 443,80,8080,8000,8888 -threads 200'
alias crawl='katana -d 5 -jc -kf -ps -pss waybackarchive,commoncrawl,alienvault'
12 changes: 12 additions & 0 deletions exegol/my-resources/fragments/history.dotsec
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
: 0:0;subfinder -d $DOMAIN -all -recursive > subdomains.txt
: 0:0;cat subdomains.txt | httpx-toolkit -mc 200 -l subdomains.txt -ports 443,80,8080,8000,8888 -threads 200 > subdomains_alive.txt
: 0:0;katana -u subdomains_alive.txt -d 5 -ps -pss waybackarchive,commoncrawl,alienvault -kf -jc -ef woff,css,png,svg,jpg,woff2,jpeg,gif -o allurls.txt
: 0:0;cat allurls.txt | grep -E "\.js($|\?)" | sort -u > js.txt
: 0:0;cat subdomains_alive.txt | gau > params.txt
: 0:0;cat js.txt | while read url; do python3 ~/tools/secretfinder/SecretFinder.py -i $url -o cli; done >> secrets.txt
: 0:0;dirsearch -u https://$DOMAIN -e conf,config,bak,old,sql,json,js,zip,tar.gz
: 0:0;feroxbuster -u https://$DOMAIN -w /usr/share/seclists/Discovery/Web-Content/big.txt -C 404,403,429,401,405,302,400,301 -t 50
: 0:0;nuclei -l subdomains_alive.txt -t ~/nuclei-templates/http/cves -severity critical,high,medium -c 100
: 0:0;ffuf -w /usr/share/seclists/Discovery/Web-Content/big.txt -u https://$DOMAIN/FUZZ -mc 200,403 -fs 0
: 0:0;sqlmap -u "https://$DOMAIN/?id=1" --level=5 --risk=3 -p id --dbs
: 0:0;subzy run --targets subdomains.txt --concurrency 100 --hide_fails --verify_ssl
11 changes: 11 additions & 0 deletions exegol/my-resources/fragments/load_user_setup.dotsec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# shellcheck shell=bash
# dotsec recon tooling — runs on first container start. Idempotent.
if ! command -v uv >/dev/null 2>&1; then
curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh
fi
if ! command -v pnpm >/dev/null 2>&1; then
npm install -g pnpm 2>/dev/null || true
fi
if ! command -v unwebpack-sourcemap >/dev/null 2>&1; then
npm install -g unwebpack-sourcemap 2>/dev/null || true
fi
87 changes: 0 additions & 87 deletions exegol/my-resources/setup.sh

This file was deleted.

2 changes: 1 addition & 1 deletion lib/exegol.sh
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ cmd_exegol() {
printf '%b\n' " ${DIM}Start it with:${RESET} ${YELLOW}exegol start ${container}${RESET}" >&2
exit 1
fi
docker exec ${docker_tty} "$container" bash /opt/resources/dotenv-sec/setup.sh
docker exec ${docker_tty} "$container" bash /opt/my-resources/setup/load_user_setup.sh
;;
*)
printf '%b\n' "${RED}[!] Usage: dotsec exegol exec|shell|setup${RESET}" >&2
Expand Down
Loading
Loading